diff --git a/.gitignore b/.gitignore index 156b10d1f1..b827cf50da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ - ################# ## Eclipse ################# @@ -215,7 +214,7 @@ pip-log.txt #Mr Developer .mr.developer.cfg -.gitignore +#.gitignore ======= @@ -235,7 +234,7 @@ hs_err_pid* .recommenders -*.xml +#*.xml *.iml .idea *.iml @@ -248,7 +247,7 @@ rebel-remote.xml .metadata target -*.class +#*.class log *.log @@ -257,8 +256,26 @@ tmp .metadata RemoteSystemsTempFiles -.gitignore +#.gitignore + +build/ +.idea/ +.gradle/ +*.class +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +#ide config +.metadata .recommenders .idea/ *.iml @@ -269,3 +286,9 @@ target *.DS_Store liuxin/.DS_Store liuxin/src/.DS_Store + + + + + + diff --git a/group01/1298552064/src/week05/basic/StackUtil.java b/group01/1298552064/src/week05/basic/StackUtil.java new file mode 100644 index 0000000000..7a7f459d2f --- /dev/null +++ b/group01/1298552064/src/week05/basic/StackUtil.java @@ -0,0 +1,110 @@ +package week05.basic; + +import java.util.Stack; + +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack reverseStack = new Stack<>(); + Stack sequenceStack = new Stack<>(); + while(!s.isEmpty()){ + reverseStack.push(s.pop()); + } + + while(!reverseStack.isEmpty()){ + sequenceStack.push(reverseStack.pop()); + } + + while(!sequenceStack.isEmpty()){ + s.push(sequenceStack.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static void remove(Stack s,Object o) { + Stack tmpStack = new Stack<>(); + while(!s.isEmpty()){ + if(s.peek().equals(o)){ + s.pop(); + }else{ + tmpStack.push(s.pop()); + } + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Object[] getTop(Stack s,int len) { + if(len < 0 ||len > s.size()){ + throw new IllegalArgumentException("len is invalid argument."); + } + + Object[] objects = new Object[len]; + Stack tmpStack = new Stack<>(); + int index = 0; + while(!s.isEmpty() && index < len){ + Object o = s.pop(); + tmpStack.push(o); + objects[index++] = o; + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + return objects; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的,该方法返回false; + * + * @param s + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static boolean isValidPairs(String s){ + String symStr = ""; + Stack symStack = new Stack<>(); + for(int i = 0; i < s.length(); i++){ + if(!Character.isLetter(s.charAt(i))){ + symStack.push(s.charAt(i)); + symStr += s.charAt(i); + } + } + + for(int i=0; i< symStr.length();i++){ + char s1 = symStr.charAt(i); + char s2 = (char) symStack.pop(); + if(s1 == '(' && s2 != ')'){ + return false; + } + if(s1 == '[' && s2 != ']'){ + return false; + } + if(s1 == '{' && s2 != '}'){ + return false; + } + } + + return true; + } +} diff --git a/group01/1298552064/src/week05/test/StackUtilTest.java b/group01/1298552064/src/week05/test/StackUtilTest.java new file mode 100644 index 0000000000..9ad9eb04f8 --- /dev/null +++ b/group01/1298552064/src/week05/test/StackUtilTest.java @@ -0,0 +1,68 @@ +package week05.test; + +import java.util.Stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week05.basic.StackUtil; + +public class StackUtilTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + System.out.println(s.toString()); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group01/1298552064/src/week06/basic/InfixExpr.java b/group01/1298552064/src/week06/basic/InfixExpr.java new file mode 100644 index 0000000000..8e8718e839 --- /dev/null +++ b/group01/1298552064/src/week06/basic/InfixExpr.java @@ -0,0 +1,102 @@ +package week06.basic; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + private String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + /** + * 计算 + * @param operator 运算符 + * @param i1 操作数1 + * @param i2 操作数2 + * @return + */ + private int cal(char operator, int i1, int i2){ + int result = 0; + switch(operator){ + case '+' : result = i1 + i2 ; break; + case '-' : result = i1 - i2 ; break; + case '*' : result = i1 * i2 ; break; + case '/' : + if(i1 == 0){ + throw new ArithmeticException("除数不能为0"); + } + result = i1 / i2 ; break; + } + return result; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + Stack operatorStack = new Stack<>(); + Stack operandStack = new Stack<>(); + for(Token token : tokens){ + if(token.isNumber()){ + operandStack.push(token.getIntValue()); + continue; + } + + if(token.isOperator()){ + if(operatorStack.isEmpty()){ + operatorStack.push(token); + continue; + } + + Token pre = operatorStack.peek(); + boolean hasHigherPriority = token.hasHigherPriority(pre); + if(hasHigherPriority){ + operatorStack.push(token); + }else{ + int n2 = operandStack.pop(); + int n1 = operandStack.pop(); + String operator = operatorStack.pop().value; + operatorStack.push(token); + operandStack.push(cal(operator.charAt(0), n1, n2)); + } + } + } + + while(!operatorStack.isEmpty()){ + if(operatorStack.size() == 1){ + int n2 = operandStack.pop(); + int n1 = operandStack.pop(); + String operator = operatorStack.pop().value; + operandStack.push(cal(operator.charAt(0), n1, n2)); + break; + } + + Token cur = operatorStack.pop(); + Token pre = operatorStack.pop(); + if(cur.hasHigherPriority(pre)){ + int n2 = operandStack.pop(); + int n1 = operandStack.pop(); + operandStack.push(cal(cur.value.charAt(0), n1, n2)); + + operatorStack.push(pre); + }else{ + int n3 = operandStack.pop(); + int n2 = operandStack.pop(); + int n1 = operandStack.pop(); + operandStack.push(cal(pre.value.charAt(0), n1, n2)); + operandStack.push(n3); + + operatorStack.push(cur); + } + + } + return (float)operandStack.pop(); + } + + public static void main(String[] args) { + InfixExpr expr = new InfixExpr("10-2*3+50"); + System.out.println(expr.evaluate()); + } + +} diff --git a/group01/1298552064/src/week06/basic/Token.java b/group01/1298552064/src/week06/basic/Token.java new file mode 100644 index 0000000000..c817040815 --- /dev/null +++ b/group01/1298552064/src/week06/basic/Token.java @@ -0,0 +1,53 @@ +package week06.basic; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Token { + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + 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); + } + + + public Token(int type, String value){ + this.type = type; + this.value = value; + } + + public boolean isOperator(){ + return type == OPERATOR; + } + + public boolean isNumber(){ + return type == NUMBER; + } + + public int getIntValue(){ + return Integer.parseInt(value); + } + + @Override + 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; + + } + +} diff --git a/group01/1298552064/src/week06/basic/TokenParser.java b/group01/1298552064/src/week06/basic/TokenParser.java new file mode 100644 index 0000000000..6a44e4260f --- /dev/null +++ b/group01/1298552064/src/week06/basic/TokenParser.java @@ -0,0 +1,44 @@ +package week06.basic; + +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 token = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(token); + i++; + }else if(Character.isDigit(c)){ + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token token = new Token(Token.NUMBER, value); + tokens.add(token); + i = nextOperatorIndex; + }else{ + System.out.println("char :[" + c + "] is not number or operator,ignore"); + i++; + } + } + return tokens; + } + + public int indexOfNextOperator(int i,String expr){ + while(Character.isDigit(expr.charAt(i))){ + i++; + if(i == expr.length()){ + break; + } + } + return i; + } + + public boolean isOperator(char c){ + String s = String.valueOf(c); + return Token.OPERATORS.contains(s); + } +} diff --git a/group01/1298552064/src/week06/test/InfixExprTest.java b/group01/1298552064/src/week06/test/InfixExprTest.java new file mode 100644 index 0000000000..9a20193fb4 --- /dev/null +++ b/group01/1298552064/src/week06/test/InfixExprTest.java @@ -0,0 +1,53 @@ +package week06.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week06.basic.InfixExpr; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + // InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group01/1298552064/src/week06/test/TokenParserTest.java b/group01/1298552064/src/week06/test/TokenParserTest.java new file mode 100644 index 0000000000..7f1632fceb --- /dev/null +++ b/group01/1298552064/src/week06/test/TokenParserTest.java @@ -0,0 +1,40 @@ +package week06.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week06.basic.Token; +import week06.basic.TokenParser; + +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/group01/1298552064/src/week07/basic/InfixToPostfix.java b/group01/1298552064/src/week07/basic/InfixToPostfix.java new file mode 100644 index 0000000000..0d0c2c5b34 --- /dev/null +++ b/group01/1298552064/src/week07/basic/InfixToPostfix.java @@ -0,0 +1,45 @@ +package week07.basic; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + public static List convert(String expr) { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + List rsTokens = new ArrayList<>(); + Stack operatorStack = new Stack<>(); + for(int i=0 ; i < tokens.size(); i++){ + Token token = tokens.get(i); + if(token.isNumber()){ + rsTokens.add(token); + continue; + } + + if(token.isOperator()){ + if(operatorStack.isEmpty()){ + operatorStack.push(token); + continue; + } + + Token curStack = operatorStack.peek(); + if(token.hasHigherPriority(curStack)){ + operatorStack.push(token); + }else{ + while(!operatorStack.isEmpty() && (curStack = operatorStack.peek()).hasHigherPriority(token)){ + rsTokens.add(curStack); + operatorStack.pop(); + } + operatorStack.push(token); + } + + } + } + + while(!operatorStack.isEmpty()){ + rsTokens.add(operatorStack.pop()); + } + return rsTokens; + } +} diff --git a/group01/1298552064/src/week07/basic/PostfixExpr.java b/group01/1298552064/src/week07/basic/PostfixExpr.java new file mode 100644 index 0000000000..1a414b5ba2 --- /dev/null +++ b/group01/1298552064/src/week07/basic/PostfixExpr.java @@ -0,0 +1,51 @@ +package week07.basic; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + /** + * 计算 + * @param operator 运算符 + * @param i1 操作数1 + * @param i2 操作数2 + * @return + */ + private int cal(char operator, int i1, int i2){ + int result = 0; + switch(operator){ + case '+' : result = i1 + i2 ; break; + case '-' : result = i1 - i2 ; break; + case '*' : result = i1 * i2 ; break; + case '/' : + if(i1 == 0){ + throw new ArithmeticException("除数不能为0"); + } + result = i1 / i2 ; break; + } + return result; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + Stack numStack = new Stack<>(); + for(int i = 0; i < tokens.size(); i++){ + Token token = tokens.get(i); + if(token.isNumber()){ + numStack.push(token.getIntValue()); + }else if(token.isOperator()){ + int n2 = numStack.pop(); + int n1 = numStack.pop(); + numStack.push(cal(token.value.charAt(0),n1,n2)); + } + } + return (float)numStack.pop() ; + } +} diff --git a/group01/1298552064/src/week07/basic/PrefixExpr.java b/group01/1298552064/src/week07/basic/PrefixExpr.java new file mode 100644 index 0000000000..f52942dfbb --- /dev/null +++ b/group01/1298552064/src/week07/basic/PrefixExpr.java @@ -0,0 +1,51 @@ +package week07.basic; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + private String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + /** + * 计算 + * @param operator 运算符 + * @param i1 操作数1 + * @param i2 操作数2 + * @return + */ + private int cal(char operator, int i1, int i2){ + int result = 0; + switch(operator){ + case '+' : result = i1 + i2 ; break; + case '-' : result = i1 - i2 ; break; + case '*' : result = i1 * i2 ; break; + case '/' : + if(i1 == 0){ + throw new ArithmeticException("除数不能为0"); + } + result = i1 / i2 ; break; + } + return result; + } + + public float evaluate() { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + Stack numStack = new Stack<>(); + for(int i = tokens.size() - 1; i >= 0;i--){ + Token token = tokens.get(i); + if(token.isNumber()){ + numStack.push(token.getIntValue()); + }else if(token.isOperator()){ + int n1 = numStack.pop(); + int n2 = numStack.pop(); + numStack.push(cal(token.value.charAt(0), n1, n2)); + } + } + return (float)numStack.pop() ; + } +} diff --git a/group01/1298552064/src/week07/basic/Token.java b/group01/1298552064/src/week07/basic/Token.java new file mode 100644 index 0000000000..e2a13816ca --- /dev/null +++ b/group01/1298552064/src/week07/basic/Token.java @@ -0,0 +1,52 @@ +package week07.basic; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Token { + static final int OPERATOR = 1; + static final int NUMBER = 2; + String value; + int type; + 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); + } + + public Token(int type, String value) { + this.type = type; + this.value = value; + } + + public boolean isOperator() { + return type == OPERATOR; + } + + public boolean isNumber() { + return type == NUMBER; + } + + public int getIntValue() { + return Integer.parseInt(value); + } + + @Override + 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; + + } + +} diff --git a/group01/1298552064/src/week07/basic/TokenParser.java b/group01/1298552064/src/week07/basic/TokenParser.java new file mode 100644 index 0000000000..7f7e5bc83e --- /dev/null +++ b/group01/1298552064/src/week07/basic/TokenParser.java @@ -0,0 +1,44 @@ +package week07.basic; + +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 token = new Token(Token.OPERATOR, String.valueOf(c)); + tokens.add(token); + i++; + }else if(Character.isDigit(c)){ + int nextOperatorIndex = indexOfNextOperator(i, expr); + String value = expr.substring(i, nextOperatorIndex); + Token token = new Token(Token.NUMBER, value); + tokens.add(token); + i = nextOperatorIndex; + }else{ + System.out.println("char :[" + c + "] is not number or operator,ignore"); + i++; + } + } + return tokens; + } + + public int indexOfNextOperator(int i,String expr){ + while(Character.isDigit(expr.charAt(i))){ + i++; + if(i == expr.length()){ + break; + } + } + return i; + } + + public boolean isOperator(char c){ + String s = String.valueOf(c); + return Token.OPERATORS.contains(s); + } +} diff --git a/group01/1298552064/src/week07/test/InfixToPostfixTest.java b/group01/1298552064/src/week07/test/InfixToPostfixTest.java new file mode 100644 index 0000000000..f747e5be3f --- /dev/null +++ b/group01/1298552064/src/week07/test/InfixToPostfixTest.java @@ -0,0 +1,35 @@ +package week07.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.basic.InfixToPostfix; + +public class InfixToPostfixTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testconvert() { + + Assert.assertEquals("[2, 3, 4, *, +, 5, +]", InfixToPostfix.convert("2+3*4+5").toString()); + + Assert.assertEquals("[3, 20, *, 12, 5, *, +, 40, 2, /, -]", InfixToPostfix.convert("3*20+12*5-40/2").toString()); + + Assert.assertEquals("[10, 2, 3, *, -, 50, +]", InfixToPostfix.convert("10-2*3+50").toString()); + + Assert.assertEquals("[3, 20, 2, /, *]", InfixToPostfix.convert("3*20/2").toString()); + + Assert.assertEquals("[10, 30, 50, +, -]", InfixToPostfix.convert("10-30+50").toString()); + + Assert.assertEquals("[20, 2, 3, *, /]", InfixToPostfix.convert("20/2*3").toString()); + + } +} diff --git a/group01/1298552064/src/week07/test/PostfixExprTest.java b/group01/1298552064/src/week07/test/PostfixExprTest.java new file mode 100644 index 0000000000..3578cded0e --- /dev/null +++ b/group01/1298552064/src/week07/test/PostfixExprTest.java @@ -0,0 +1,37 @@ +package week07.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.basic.PostfixExpr; + +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/group01/1298552064/src/week07/test/PrefixExprTest.java b/group01/1298552064/src/week07/test/PrefixExprTest.java new file mode 100644 index 0000000000..7c85c57bc4 --- /dev/null +++ b/group01/1298552064/src/week07/test/PrefixExprTest.java @@ -0,0 +1,43 @@ +package week07.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.basic.PrefixExpr; + +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/group01/1298552064/src/week08/basic/CircleQueue.java b/group01/1298552064/src/week08/basic/CircleQueue.java new file mode 100644 index 0000000000..af1eed0575 --- /dev/null +++ b/group01/1298552064/src/week08/basic/CircleQueue.java @@ -0,0 +1,53 @@ +package week08.basic; + +import java.util.Arrays; + +/** + * 用数组实现循环队列 + * @author gallenzhang + * + * @param + */ +public class CircleQueue { + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + //队列的长度 + private int size; + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + return front == rear; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + if((rear + 1) % elementData.length == front){ + int len = elementData.length + elementData.length / 2; + elementData = Arrays.copyOf(elementData, len); + } + elementData[rear] = data; + size++; + rear = (rear + 1) % elementData.length; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + if(isEmpty()){ + return null; + } + + E e = (E) elementData[front]; + front = (front + 1) % elementData.length; + size--; + return e; + } +} diff --git a/group01/1298552064/src/week08/basic/Josephus.java b/group01/1298552064/src/week08/basic/Josephus.java new file mode 100644 index 0000000000..846cc7bf59 --- /dev/null +++ b/group01/1298552064/src/week08/basic/Josephus.java @@ -0,0 +1,40 @@ +package week08.basic; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 + * + * @author gallenzhang + * + */ +public class Josephus { + + public static List execute(int n, int m) { + Queue allQueue = new Queue<>(); + Queue killQueue = new Queue<>(); + for(int i = 0; i < n; i++){ + allQueue.enQueue(i); + } + + int k = 0; + while(!allQueue.isEmpty()){ + Integer num = allQueue.deQueue(); + k++; + if(k == m){ + killQueue.enQueue(num); + k = 0; + }else{ + allQueue.enQueue(num); + } + } + List killList = new ArrayList<>(); + while(!killQueue.isEmpty()){ + killList.add(killQueue.deQueue()); + } + + return killList; + } +} diff --git a/group01/1298552064/src/week08/basic/Queue.java b/group01/1298552064/src/week08/basic/Queue.java new file mode 100644 index 0000000000..00ad554de6 --- /dev/null +++ b/group01/1298552064/src/week08/basic/Queue.java @@ -0,0 +1,54 @@ +package week08.basic; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group01/1298552064/src/week08/basic/QueueWithTwoStacks.java b/group01/1298552064/src/week08/basic/QueueWithTwoStacks.java new file mode 100644 index 0000000000..35daf8f4a9 --- /dev/null +++ b/group01/1298552064/src/week08/basic/QueueWithTwoStacks.java @@ -0,0 +1,46 @@ +package week08.basic; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * + * @author gallenzhang + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.size() == 0; + } + + public int size() { + return stack1.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(stack1.isEmpty()){ + return null; + } + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + E e = stack2.pop(); + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + return e; + } +} diff --git a/group01/1298552064/src/week08/test/CircleQueueTest.java b/group01/1298552064/src/week08/test/CircleQueueTest.java new file mode 100644 index 0000000000..2ad18c04b6 --- /dev/null +++ b/group01/1298552064/src/week08/test/CircleQueueTest.java @@ -0,0 +1,40 @@ +package week08.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.basic.CircleQueue; + +public class CircleQueueTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + CircleQueue queue = new CircleQueue(); + Assert.assertTrue(queue.isEmpty()); + + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + queue.enQueue("d"); + queue.enQueue("e"); + + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } +} diff --git a/group01/1298552064/src/week08/test/JosephusTest.java b/group01/1298552064/src/week08/test/JosephusTest.java new file mode 100644 index 0000000000..6c392438bc --- /dev/null +++ b/group01/1298552064/src/week08/test/JosephusTest.java @@ -0,0 +1,26 @@ +package week08.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.basic.Josephus; + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } +} diff --git a/group01/1298552064/src/week09/basic/Queue.java b/group01/1298552064/src/week09/basic/Queue.java new file mode 100644 index 0000000000..fc4cae727b --- /dev/null +++ b/group01/1298552064/src/week09/basic/Queue.java @@ -0,0 +1,75 @@ +package week09.basic; + +import java.util.NoSuchElementException; + +public class Queue { + private Node first; + private Node last; + private int size; + + private static class Node{ + private Node next; + private T data; + } + + public Queue(){ + first = null; + last = null; + size = 0; + } + + public boolean isEmpty(){ + return first == null; + } + + public int size(){ + return size; + } + + public void enQueue(T data){ + Node oldlast = last; + last = new Node(); + last.data = data; + last.next = null; + if(isEmpty()){ + first = last; + }else{ + oldlast.next = last; + } + size ++; + } + + public T deQueue(){ + if(isEmpty()){ + throw new NoSuchElementException("Queue is Empty"); + } + T item = first.data; + first = first.next; + size --; + if(isEmpty()){ + last = null; + } + return item; + } + + @Override + public String toString(){ + if(isEmpty()){ + return "[]"; + } + + StringBuffer sb = new StringBuffer("["); + Node node = first; + while(node != null){ + if(node.next == null){ + sb.append(node.data); + }else{ + sb.append(node.data); + sb.append(","); + } + node = node.next; + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/group01/1298552064/src/week09/basic/QuickMinStack.java b/group01/1298552064/src/week09/basic/QuickMinStack.java new file mode 100644 index 0000000000..bf4297c182 --- /dev/null +++ b/group01/1298552064/src/week09/basic/QuickMinStack.java @@ -0,0 +1,47 @@ +package week09.basic; + +import java.util.EmptyStackException; +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author gallenzhang + * + */ +public class QuickMinStack { + Stack stack = new Stack<>(); + Stack minStack = new Stack<>(); + + public void push(int data) { + stack.push(data); + if(minStack.isEmpty()){ + minStack.push(data); + return ; + } + + if(minStack.peek() > data){ + minStack.push(data); + } + } + + public int pop() { + if(stack.isEmpty()){ + throw new EmptyStackException(); + } + + int item = stack.pop(); + if(item == minStack.peek()){ + minStack.pop(); + } + return item; + } + + public int findMin() { + if(minStack.isEmpty()){ + throw new EmptyStackException(); + } + return minStack.peek(); + } + +} diff --git a/group01/1298552064/src/week09/basic/StackWithTwoQueues.java b/group01/1298552064/src/week09/basic/StackWithTwoQueues.java new file mode 100644 index 0000000000..d714c4614e --- /dev/null +++ b/group01/1298552064/src/week09/basic/StackWithTwoQueues.java @@ -0,0 +1,111 @@ +package week09.basic; + +import java.util.EmptyStackException; + +/** + * 用两个队列实现栈 + * + * @author gallenzhang + * + */ +public class StackWithTwoQueues { + private Queue firstQueue = new Queue<>(); + private Queue secondQueue = new Queue<>(); + + public void push(int data) { + + if(!firstQueue.isEmpty()){ + firstQueue.enQueue(data); + return ; + } + + if(!secondQueue.isEmpty()){ + secondQueue.enQueue(data); + return ; + } + + firstQueue.enQueue(data); + } + + public int pop() { + if(firstQueue.isEmpty() && secondQueue.isEmpty()){ + throw new EmptyStackException(); + } + + int item = -1; + int queueSize = 0; + + if(!firstQueue.isEmpty()){ + queueSize = firstQueue.size(); + for(int i = 0 ; i < queueSize; i++){ + if(i == queueSize - 1){ + item = firstQueue.deQueue(); + return item; + } + secondQueue.enQueue(firstQueue.deQueue()); + } + + } + + if(!secondQueue.isEmpty()){ + queueSize = secondQueue.size(); + for(int i = 0; i < queueSize; i++){ + if(i == queueSize -1){ + item = secondQueue.deQueue(); + return item; + } + firstQueue.enQueue(secondQueue.deQueue()); + } + } + return item; + } + + public int size(){ + return Math.max(firstQueue.size(), secondQueue.size()); + } + + public boolean isEmpty(){ + return size() == 0; + } + + public int peek(){ + int item = -1; + int queueSize = 0; + if(firstQueue.isEmpty() && secondQueue.isEmpty()){ + throw new EmptyStackException(); + } + + if(!firstQueue.isEmpty()){ + queueSize = firstQueue.size(); + for(int i = 0; i < queueSize; i++){ + if(i == queueSize - 1){ + item = firstQueue.deQueue(); + break; + } + firstQueue.enQueue(firstQueue.deQueue()); + } + firstQueue.enQueue(item); + return item; + } + + if(!secondQueue.isEmpty()){ + queueSize = secondQueue.size(); + for(int i = 0; i < queueSize; i++){ + if(i == queueSize - 1){ + item = secondQueue.deQueue(); + break; + } + secondQueue.enQueue(secondQueue.deQueue()); + } + secondQueue.enQueue(item); + return item; + } + return item; + } + + @Override + public String toString(){ + return firstQueue.isEmpty() ? secondQueue.toString() : firstQueue.toString(); + } + +} diff --git a/group01/1298552064/src/week09/basic/TwoStackInOneArray.java b/group01/1298552064/src/week09/basic/TwoStackInOneArray.java new file mode 100644 index 0000000000..ce4f57e7db --- /dev/null +++ b/group01/1298552064/src/week09/basic/TwoStackInOneArray.java @@ -0,0 +1,170 @@ +package week09.basic; + +import java.util.Arrays; +import java.util.EmptyStackException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author gallenzhang + * + */ +public class TwoStackInOneArray { + private int DEFAULT_SIZE = 10; + + Object[] data = null; + + private int size1; + + private int size2; + + public TwoStackInOneArray(int size){ + if(size <= 0){ + throw new IllegalArgumentException("size can not be negative or zero"); + } + data = new Object[size]; + } + + public TwoStackInOneArray(){ + data = new Object[DEFAULT_SIZE]; + } + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + ensureCapacity(size1 + size2 + 1); + data[size1] = o; + size1 ++; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + checkStack1Empty(); + Object obj = data[size1 - 1]; + data[size1 - 1] = null; + size1--; + return obj; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + checkStack1Empty(); + return data[size1-1]; + } + + /** + * 第一个栈是否为空 + * @return + */ + public boolean isStack1Empty(){ + return size1 == 0 ; + } + + /** + * 获取第一个栈的大小 + * @return + */ + public int size1(){ + return size1; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + ensureCapacity(size1 + size2 + 1); + data[data.length - size2 - 1] = o; + size2 ++; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + checkStack2Empty(); + Object obj = data[data.length - size2]; + data[data.length - size2] = null; + size2 --; + return obj; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + checkStack2Empty(); + if(size2 == 0){ + throw new EmptyStackException(); + } + return data[data.length - size2]; + } + + public boolean isStack2Empty(){ + return size2 == 0 ; + } + + public int size2(){ + return size2; + } + + private void ensureCapacity(int minCapacity){ + int capacity = data.length; + if (minCapacity > capacity) { + capacity += capacity / 2; + grow(capacity); + } + } + + private void checkStack1Empty(){ + if(size1 == 0){ + throw new EmptyStackException(); + } + } + + private void checkStack2Empty(){ + if(size2 == 0){ + throw new EmptyStackException(); + } + } + + private void grow(int capacity){ + data = Arrays.copyOf(data, capacity); + System.arraycopy(data, size1, data, data.length - size2, size2); + for(int i = size1; i < data.length - size2;i++){ + data[i] = null; + } + } + + @Override + public String toString(){ + StringBuffer sb = new StringBuffer("["); + for(int i=0; i < data.length; i++){ + if(i == data.length - 1){ + sb.append(data[i]); + }else{ + sb.append(data[i]); + sb.append(","); + } + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/group01/1298552064/src/week09/test/QuickMinStackTest.java b/group01/1298552064/src/week09/test/QuickMinStackTest.java new file mode 100644 index 0000000000..8078cabeef --- /dev/null +++ b/group01/1298552064/src/week09/test/QuickMinStackTest.java @@ -0,0 +1,43 @@ +package week09.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.basic.QuickMinStack; + +public class QuickMinStackTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + QuickMinStack stack = new QuickMinStack(); + stack.push(3); + stack.push(5); + stack.push(2); + stack.push(8); + stack.push(1); + stack.push(6); + + Assert.assertEquals(1, stack.findMin()); + + Assert.assertEquals(6, stack.pop()); + Assert.assertEquals(1, stack.pop()); + + Assert.assertEquals(2, stack.findMin()); + + Assert.assertEquals(8, stack.pop()); + Assert.assertEquals(2, stack.pop()); + + Assert.assertEquals(3, stack.findMin()); + } + +} diff --git a/group01/1298552064/src/week09/test/StackWithTwoQueuesTest.java b/group01/1298552064/src/week09/test/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..d582dfa7f9 --- /dev/null +++ b/group01/1298552064/src/week09/test/StackWithTwoQueuesTest.java @@ -0,0 +1,45 @@ +package week09.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.basic.StackWithTwoQueues; + +public class StackWithTwoQueuesTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + + Assert.assertEquals("[1,2,3,4]", stack.toString()); + Assert.assertEquals(4L, stack.size()); + + stack.pop(); + stack.pop(); + Assert.assertEquals("[1,2]", stack.toString()); + Assert.assertEquals(2L, stack.size()); + + int item = stack.peek(); + Assert.assertEquals("[1,2]", stack.toString()); + Assert.assertEquals(2L, stack.size()); + Assert.assertEquals(2L, item); + + stack.pop(); + stack.pop(); + Assert.assertEquals("[]", stack.toString()); + } +} diff --git a/group01/1298552064/src/week09/test/TwoStackInOneArrayTest.java b/group01/1298552064/src/week09/test/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..536630fd4d --- /dev/null +++ b/group01/1298552064/src/week09/test/TwoStackInOneArrayTest.java @@ -0,0 +1,48 @@ +package week09.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.basic.TwoStackInOneArray; + +public class TwoStackInOneArrayTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + TwoStackInOneArray ts = new TwoStackInOneArray(5); + ts.push1(1); + ts.push1(2); + + ts.push2(5); + ts.push2(6); + ts.push2(7); + + Assert.assertEquals("[1,2,7,6,5]", ts.toString()); + + Object o = ts.peek1(); + Assert.assertEquals(2, o); + + o = ts.peek2(); + Assert.assertEquals(7, o); + + Assert.assertEquals(2, ts.pop1()); + Assert.assertEquals(7, ts.pop2()); + + Assert.assertEquals("[1,null,null,6,5]", ts.toString()); + + ts.push1(2); + ts.push1(3); + + ts.push2(7); + Assert.assertEquals("[1,2,3,null,7,6,5]", ts.toString()); + } +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/InfixExpr.java b/group01/1814014897/zhouhui/src/week07/expr/InfixExpr.java new file mode 100644 index 0000000000..80bef68a98 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/InfixExpr.java @@ -0,0 +1,66 @@ +package week07.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + if (token.isOperator()) { + if (opStack.isEmpty()) { + opStack.push(token); + } else { + while (!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())) { + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1, f2); + numStack.push(result); + } + opStack.push(token); + } + } + if (token.isNumber()) { + + numStack.push(new Float(token.getIntValue())); + } + } + + while (!opStack.isEmpty()) { + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/InfixToPostfix.java b/group01/1814014897/zhouhui/src/week07/expr/InfixToPostfix.java new file mode 100644 index 0000000000..dcaaea756c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/InfixToPostfix.java @@ -0,0 +1,34 @@ +package week07.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + List inFixTokens = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList<>(); + + Stack opStack = new Stack(); + + for (Token token : inFixTokens) { + if (token.isOperator()) { + while (!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())) { + postFixTokens.add(opStack.pop()); + } + opStack.push(token); + } + if (token.isNumber()) { + postFixTokens.add(token); + } + } + + while (!opStack.isEmpty()) { + postFixTokens.add(opStack.pop()); + } + return postFixTokens; + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/PostfixExpr.java b/group01/1814014897/zhouhui/src/week07/expr/PostfixExpr.java new file mode 100644 index 0000000000..1a20114483 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/PostfixExpr.java @@ -0,0 +1,48 @@ +package week07.expr; + +import java.util.List; +import java.util.Stack; + +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 numStack = new Stack<>(); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } else if (token.isOperator()) { + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(token.toString(), f1, f2); + numStack.push(result); + } + } + + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/PrefixExpr.java b/group01/1814014897/zhouhui/src/week07/expr/PrefixExpr.java new file mode 100644 index 0000000000..b2949c9236 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/PrefixExpr.java @@ -0,0 +1,52 @@ +package week07.expr; + +import java.util.List; +import java.util.Stack; + +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); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (Token token : tokens) { + exprStack.push(token); + } + + while (!exprStack.isEmpty()) { + if (exprStack.peek().isNumber()) { + numStack.push(new Float(exprStack.pop().getIntValue())); + } else if (exprStack.peek().isOperator()) { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + Float result = calculate(exprStack.pop().toString(), f1, f2); + numStack.push(result); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + "is not supported"); + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/Token.java b/group01/1814014897/zhouhui/src/week07/expr/Token.java new file mode 100644 index 0000000000..b0767745dc --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/Token.java @@ -0,0 +1,50 @@ +package week07.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; + 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group01/1814014897/zhouhui/src/week07/expr/TokenParser.java b/group01/1814014897/zhouhui/src/week07/expr/TokenParser.java new file mode 100644 index 0000000000..57a1935d9c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/TokenParser.java @@ -0,0 +1,57 @@ +package week07.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/group01/1814014897/zhouhui/src/week07/expr/test/AllTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/AllTest.java new file mode 100644 index 0000000000..9980592a25 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/AllTest.java @@ -0,0 +1,18 @@ +package week07.expr.test; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({ + InfixExprTest.class, + InfixToPostfixTest.class, + PostfixExprTest.class, + PrefixExprTest.class, + TokenParserTest.class +}) + +public class AllTest { + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/test/InfixExprTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/InfixExprTest.java new file mode 100644 index 0000000000..36b4ab5bfd --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/InfixExprTest.java @@ -0,0 +1,54 @@ +package week07.expr.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.expr.InfixExpr; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/test/InfixToPostfixTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/InfixToPostfixTest.java new file mode 100644 index 0000000000..960116775a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/InfixToPostfixTest.java @@ -0,0 +1,32 @@ +package week07.expr.test; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import week07.expr.InfixToPostfix; +import week07.expr.Token; + +public class InfixToPostfixTest { + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/expr/test/PostfixExprTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/PostfixExprTest.java new file mode 100644 index 0000000000..0ca382ae07 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/PostfixExprTest.java @@ -0,0 +1,43 @@ +package week07.expr.test; + + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.expr.PostfixExpr; + + + +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/group01/1814014897/zhouhui/src/week07/expr/test/PrefixExprTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/PrefixExprTest.java new file mode 100644 index 0000000000..c955223e3a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/PrefixExprTest.java @@ -0,0 +1,47 @@ +package week07.expr.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.expr.PrefixExpr; + + +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/group01/1814014897/zhouhui/src/week07/expr/test/TokenParserTest.java b/group01/1814014897/zhouhui/src/week07/expr/test/TokenParserTest.java new file mode 100644 index 0000000000..0a9fa7ea50 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/expr/test/TokenParserTest.java @@ -0,0 +1,42 @@ +package week07.expr.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.expr.Token; +import week07.expr.TokenParser; + +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/group01/1814014897/zhouhui/src/week07/jvm/attr/AttributeInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..dd82595dcf --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package week07.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/group01/1814014897/zhouhui/src/week07/jvm/attr/CodeAttr.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..60d542bb4e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/CodeAttr.java @@ -0,0 +1,116 @@ +package week07.jvm.attr; + +import week07.jvm.attr.AttributeInfo; +import week07.jvm.attr.CodeAttr; +import week07.jvm.attr.LineNumberTable; +import week07.jvm.attr.LocalVariableTable; +import week07.jvm.attr.StackMapTable; +import week07.jvm.clz.ClassFile; +import week07.jvm.cmd.ByteCodeCommand; +import week07.jvm.cmd.CommandParser; +import week07.jvm.constant.ConstantPool; +import week07.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 attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code,cmds); + + int exceptionTableLen = iter.nextU2ToInt(); + + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table,just ignore it"); + } + + int subAttrCount = iter.nextU2ToInt(); + + for (int i = 1; i <= subAttrCount; i++) { + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + iter.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + } + + return codeAttr; + } + + public String toString(ConstantPool pool) { + StringBuilder buffer = new StringBuilder(); + // buffer.append("Code:").append(code).append("\n"); + for (int i = 0; i < cmds.length; i++) { + buffer.append(cmds[i].toString(pool)).append("\n"); + } + buffer.append("\n"); + buffer.append(this.lineNumTable.toString()); + buffer.append(this.localVarTable.toString(pool)); + return buffer.toString(); + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/attr/LineNumberTable.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..739b36df5b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/LineNumberTable.java @@ -0,0 +1,66 @@ +package week07.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import week07.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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(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 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/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableItem.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..89b58e9e37 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableTable.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..a46a869204 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/LocalVariableTable.java @@ -0,0 +1,55 @@ +package week07.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import week07.jvm.constant.ConstantPool; + +import week07.jvm.loader.ByteCodeIterator; + +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 index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index, len); + + int itemLen = iter.nextU2ToInt(); + + for (int i = 1; i <= itemLen; i++) { + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + 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/group01/1814014897/zhouhui/src/week07/jvm/attr/StackMapTable.java b/group01/1814014897/zhouhui/src/week07/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..ce1fbc29e1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package week07.jvm.attr; + + +import week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/clz/AccessFlag.java b/group01/1814014897/zhouhui/src/week07/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..1c35da64b1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassFile.java b/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..ef3bce8927 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassFile.java @@ -0,0 +1,117 @@ +package week07.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import week07.jvm.constant.ClassInfo; +import week07.jvm.constant.ConstantPool; +import week07.jvm.field.Field; +import week07.jvm.method.Method; + +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 m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + public Method getMainMethod(){ + for(Method m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if(name.equals("main") && desc.equals("([Ljava/lang/String;)V")){ + return m; + } + } + return null; + } +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassIndex.java b/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..4424c8b794 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package week07.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group01/1814014897/zhouhui/src/week07/jvm/cmd/BiPushCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..3ed63a3118 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ConstantInfo; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/ByteCodeCommand.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..621c63291a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package week07.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ConstantInfo; +import week07.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/cmd/CommandParser.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..68c9187f05 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/CommandParser.java @@ -0,0 +1,147 @@ +package week07.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import week07.jvm.clz.ClassFile; + +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) { + if (codes == null || codes.length() == 0) { + throw new RuntimeException("error codes"); + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + }else{ + throw new RuntimeException("the code instruction " + opCode + " has not been implemented."); + } + } + + 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/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetFieldCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..a548e7acd7 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetStaticFieldCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..8b58120066 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ClassInfo; +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.FieldRefInfo; +import week07.jvm.constant.UTF8Info; + + +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/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeSpecialCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..e8a4513467 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.MethodRefInfo; + + +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/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeVirtualCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..54f4e4eafd --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/LdcCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..3616fb71a8 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ConstantInfo; +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/cmd/NewObjectCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..862b8a31d5 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/NoOperandCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..ac15f21216 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/OneOperandCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..f90f652625 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package week07.jvm.cmd; + +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/PutFieldCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..140f5f2326 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.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/group01/1814014897/zhouhui/src/week07/jvm/cmd/TwoOperandCmd.java b/group01/1814014897/zhouhui/src/week07/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..51261db877 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package week07.jvm.cmd; + +import week07.jvm.clz.ClassFile; +import week07.jvm.constant.ClassInfo; +import week07.jvm.constant.ConstantInfo; +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.FieldRefInfo; +import week07.jvm.constant.MethodRefInfo; + +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/group01/1814014897/zhouhui/src/week07/jvm/constant/ClassInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b7a7a40ef4 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..201bfaeb49 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package week07.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantPool.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..5d039834b1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/FieldRefInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..74b5537b93 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/MethodRefInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..00b9a4cfa8 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/NameAndTypeInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..433c000fa2 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/NullConstantInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..05e75bda77 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package week07.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/constant/StringInfo.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..cdc171fbad --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package week07.jvm.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/group01/1814014897/zhouhui/src/week07/jvm/constant/UTF8Info.java b/group01/1814014897/zhouhui/src/week07/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..cc8e0e6d66 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package week07.jvm.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.visistUTF8(this); + + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/field/Field.java b/group01/1814014897/zhouhui/src/week07/jvm/field/Field.java new file mode 100644 index 0000000000..dc1819f557 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/field/Field.java @@ -0,0 +1,50 @@ +package week07.jvm.field; + +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.UTF8Info; +import week07.jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + + private ConstantPool pool; + + public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/loader/ByteCodeIterator.java b/group01/1814014897/zhouhui/src/week07/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..4585526a3c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package week07.jvm.loader; + +import java.util.Arrays; + +import week07.jvm.util.Util; + +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/group01/1814014897/zhouhui/src/week07/jvm/loader/ClassFileLoader.java b/group01/1814014897/zhouhui/src/week07/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..98e0194303 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package week07.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import week07.jvm.clz.ClassFile; + + + + + +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")){ + s3 = "//" + info.getClassName() + ".\"" + info.getMethodName() + "\":" + + info.getParamAndReturnType(); + }else{ + s3 = "//" + info.getClassName() + "." + info.getMethodName() + ":" + + info.getParamAndReturnType(); + } + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "NameAndType"; + String s2 = "#" + info.getIndex1() + ":#" + info.getIndex2(); + String s3; + if (info.getName().equals("")) { + s3 = "//" + "\"" + info.getName() + "\"" + ":" + info.getTypeInfo(); + } else { + s3 = "//" + info.getName() + ":" + info.getTypeInfo(); + } + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + } + + @Override + public void visitString(StringInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "String"; + String s2 = "#" + info.getIndex(); + String s3 = "//" + info.toString(); + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + + } + + @Override + public void visistUTF8(UTF8Info info) { + Formatter f = new Formatter(System.out); + String s1 = "Utf8"; + String s2 = info.getValue(); + f.format("%-20s %-15s\n", s1, s2); + } + }; + + for (int i = 1; i <= pool.getSize(); i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.printf("#%-2d = ", i); + constantInfo.accept(visitor); + } + + } +} diff --git a/group01/1814014897/zhouhui/src/week07/jvm/test/ClassFileloaderTest.java b/group01/1814014897/zhouhui/src/week07/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..1a15e99610 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,354 @@ +package week07.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week07.jvm.clz.ClassFile; +import week07.jvm.clz.ClassIndex; +import week07.jvm.cmd.BiPushCmd; +import week07.jvm.cmd.ByteCodeCommand; +import week07.jvm.cmd.OneOperandCmd; +import week07.jvm.cmd.TwoOperandCmd; +import week07.jvm.constant.ClassInfo; +import week07.jvm.constant.ConstantPool; +import week07.jvm.constant.MethodRefInfo; +import week07.jvm.constant.NameAndTypeInfo; +import week07.jvm.constant.UTF8Info; +import week07.jvm.field.Field; +import week07.jvm.loader.ClassFileLoader; +import week07.jvm.method.Method; + + + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "week07/jvm/test/EmployeeV1"; + + static String path1 = (""+ClassLoader.getSystemResource("")).replaceAll("file:/" , ""); + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week07.jvm.test.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 = "week07.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1040, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week07.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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/group01/1814014897/zhouhui/src/week07/jvm/test/EmployeeV1.java b/group01/1814014897/zhouhui/src/week07/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..00f90183c9 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package week07.jvm.test; + +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/group01/1814014897/zhouhui/src/week07/jvm/util/Util.java b/group01/1814014897/zhouhui/src/week07/jvm/util/Util.java new file mode 100644 index 0000000000..d2cb5d2cc5 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week07/jvm/util/Util.java @@ -0,0 +1,24 @@ +package week07.jvm.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 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table,just ignore it"); + } + + int subAttrCount = iter.nextU2ToInt(); + + for (int i = 1; i <= subAttrCount; i++) { + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + iter.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + } + + return codeAttr; + } + + public String toString(ConstantPool pool) { + StringBuilder buffer = new StringBuilder(); + // buffer.append("Code:").append(code).append("\n"); + for (int i = 0; i < cmds.length; i++) { + buffer.append(cmds[i].toString(pool)).append("\n"); + } + buffer.append("\n"); + buffer.append(this.lineNumTable.toString()); + buffer.append(this.localVarTable.toString(pool)); + return buffer.toString(); + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/attr/LineNumberTable.java b/group01/1814014897/zhouhui/src/week08/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..b9cc3de62c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/attr/LineNumberTable.java @@ -0,0 +1,71 @@ +package week08.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import week08.jvm.attr.LineNumberTable; +import week08.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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(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 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/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableItem.java b/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..5c3ea9521a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableTable.java b/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..ad4ca5a92d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/attr/LocalVariableTable.java @@ -0,0 +1,60 @@ +package week08.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import week08.jvm.attr.LocalVariableItem; +import week08.jvm.attr.LocalVariableTable; +import week08.jvm.constant.ConstantPool; + +import week08.jvm.loader.ByteCodeIterator; + +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 index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index, len); + + int itemLen = iter.nextU2ToInt(); + + for (int i = 1; i <= itemLen; i++) { + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + 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/group01/1814014897/zhouhui/src/week08/jvm/attr/StackMapTable.java b/group01/1814014897/zhouhui/src/week08/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..a95fc1cd0d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package week08.jvm.attr; + + +import week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/clz/AccessFlag.java b/group01/1814014897/zhouhui/src/week08/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..17f0c41745 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassFile.java b/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..3dd75f3649 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassFile.java @@ -0,0 +1,117 @@ +package week08.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.field.Field; +import week08.jvm.method.Method; + +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 m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + public Method getMainMethod(){ + for(Method m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if(name.equals("main") && desc.equals("([Ljava/lang/String;)V")){ + return m; + } + } + return null; + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassIndex.java b/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..1f9c49ad9d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package week08.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group01/1814014897/zhouhui/src/week08/jvm/cmd/BiPushCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..94151cfd8d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/BiPushCmd.java @@ -0,0 +1,32 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.Heap; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + + +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(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/ByteCodeCommand.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..ae5abffb22 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,129 @@ +package week08.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.StackFrame; + + +public abstract class ByteCodeCommand { + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/CommandParser.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..a73226f68b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/CommandParser.java @@ -0,0 +1,157 @@ +package week08.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import week08.jvm.cmd.BiPushCmd; +import week08.jvm.cmd.ByteCodeCommand; +import week08.jvm.cmd.GetFieldCmd; +import week08.jvm.cmd.GetStaticFieldCmd; +import week08.jvm.cmd.InvokeSpecialCmd; +import week08.jvm.cmd.InvokeVirtualCmd; +import week08.jvm.cmd.LdcCmd; +import week08.jvm.cmd.NewObjectCmd; +import week08.jvm.cmd.NoOperandCmd; +import week08.jvm.cmd.PutFieldCmd; +import week08.jvm.clz.ClassFile; + +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) { + if (codes == null || codes.length() == 0) { + throw new RuntimeException("error codes"); + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + }else{ + throw new RuntimeException("the code instruction " + opCode + " has not been implemented."); + } + } + + 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/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetFieldCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..d4a7bb172e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,33 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + + } + + + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetStaticFieldCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..a184a482fa --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,30 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.Heap; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeSpecialCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..531d9bde68 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,32 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.MethodArea; +import week08.jvm.engine.StackFrame; +import week08.jvm.method.Method; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeVirtualCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..1ad7672b77 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,34 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.MethodArea; +import week08.jvm.engine.StackFrame; +import week08.jvm.method.Method; + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/LdcCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..442f8bb147 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/LdcCmd.java @@ -0,0 +1,39 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.StringInfo; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.Heap; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + +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; + + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/NewObjectCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..c9309c713e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,30 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.Heap; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/NoOperandCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..f76d259c59 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,31 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.JavaObject; +import week08.jvm.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/OneOperandCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..9151bafd72 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package week08.jvm.cmd; + +import week08.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/group01/1814014897/zhouhui/src/week08/jvm/cmd/PutFieldCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..d387fd2ca6 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,26 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ConstantPool; +import week08.jvm.engine.ExecutionResult; +import week08.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/cmd/TwoOperandCmd.java b/group01/1814014897/zhouhui/src/week08/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..2ba1392651 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package week08.jvm.cmd; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.constant.MethodRefInfo; + +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/group01/1814014897/zhouhui/src/week08/jvm/constant/ClassInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..71ff4cfc87 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..f80b8a0890 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package week08.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantPool.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7e0cb7bcff --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/FieldRefInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..850df3010d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/MethodRefInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f3c2c0e11f --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/NameAndTypeInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..99e66e7d61 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/NullConstantInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..1b46ca4f5b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package week08.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/constant/StringInfo.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..08e2307a18 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package week08.jvm.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/group01/1814014897/zhouhui/src/week08/jvm/constant/UTF8Info.java b/group01/1814014897/zhouhui/src/week08/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..eaefa4bb3d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package week08.jvm.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.visistUTF8(this); + + } + + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutionResult.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..7334a69eb4 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutionResult.java @@ -0,0 +1,53 @@ +package week08.jvm.engine; + +import week08.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action) { + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame() { + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame() { + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd() { + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump() { + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutorEngine.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..4d094d29e7 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/ExecutorEngine.java @@ -0,0 +1,82 @@ +package week08.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import week08.jvm.attr.CodeAttr; +import week08.jvm.clz.ClassFile; +import week08.jvm.cmd.ByteCodeCommand; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod) { + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while (!stack.empty()) { + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if (result.isPauseAndRunNewFrame()) { + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + + } + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/Heap.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/Heap.java new file mode 100644 index 0000000000..ef299caa11 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package week08.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/JavaObject.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..16715063d1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package week08.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/MethodArea.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..e11d42d3a6 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/MethodArea.java @@ -0,0 +1,87 @@ +package week08.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.loader.ClassFileLoader; +import week08.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/engine/MiniJVM.java b/group01/1814014897/zhouhui/src/week08/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..6ac5c79343 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package week08.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import week08.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/field/Field.java b/group01/1814014897/zhouhui/src/week08/jvm/field/Field.java new file mode 100644 index 0000000000..e18b445be2 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/field/Field.java @@ -0,0 +1,50 @@ +package week08.jvm.field; + +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.UTF8Info; +import week08.jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + + private ConstantPool pool; + + public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/loader/ByteCodeIterator.java b/group01/1814014897/zhouhui/src/week08/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..59eb73aff2 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package week08.jvm.loader; + +import java.util.Arrays; + +import week08.jvm.util.Util; + +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/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileLoader.java b/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..ae32538e26 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileLoader.java @@ -0,0 +1,123 @@ +package week08.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import week08.jvm.clz.ClassFile; + +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 < this.clzPaths.size(); i++) { + buffer.append(this.clzPaths.get(i)); + if (i < this.clzPaths.size() - 1) { + buffer.append(";"); + } + } + return buffer.toString(); + } + + private byte[] loadClassFile_V1(String clzFileName) { + + BufferedInputStream bis = null; + + try { + + File f = new File(clzFileName); + + bis = new BufferedInputStream(new FileInputStream(f)); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + byte[] buffer = new byte[1024]; + int length = -1; + + while ((length = bis.read(buffer)) != -1) { + bos.write(buffer, 0, length); + } + + byte[] codes = bos.toByteArray(); + + return codes; + + } catch (IOException e) { + e.printStackTrace(); + + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + + } + +} \ No newline at end of file diff --git a/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileParser.java b/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..ae16323539 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/loader/ClassFileParser.java @@ -0,0 +1,176 @@ +package week08.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import week08.jvm.loader.ByteCodeIterator; +import week08.jvm.clz.AccessFlag; +import week08.jvm.clz.ClassFile; +import week08.jvm.clz.ClassIndex; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.constant.NameAndTypeInfo; +import week08.jvm.constant.NullConstantInfo; +import week08.jvm.constant.StringInfo; +import week08.jvm.constant.UTF8Info; +import week08.jvm.field.Field; +import week08.jvm.method.Method; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ClassFile clzFile = new ClassFile(); + + ByteCodeIterator iter = new ByteCodeIterator(codes); + + String magicNumber = iter.nextU4ToHexString(); + + if (!"cafebabe".equals(magicNumber)) { + return null; + } + + clzFile.setMinorVersion(iter.nextU2ToInt()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + ClassIndex clzIndex = parseClassInfex(iter); + clzFile.setClassIndex(clzIndex); + + parseInterfaces(iter); + + parseFields(clzFile, iter); + + parseMethods(clzFile, iter); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + // System.out.println("Is public class: " + flag.isPublicClass()); + // System.out.println("Is final class : " + flag.isFinalClass()); + + return flag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + + return clzIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int constPoolCount = iter.nextU2ToInt(); + + System.out.println("Constant Pool Count :" + constPoolCount); + + ConstantPool pool = new ConstantPool(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= constPoolCount - 1; i++) { + + int tag = iter.nextU1toInt(); + + if (tag == 7) { + // Class Info + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + + pool.addConstantInfo(clzInfo); + } else if (tag == 1) { + // UTF-8 String + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + } else if (tag == 8) { + // String + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == 9) { + // FieldRef + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == 10) { + // MethodRef + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == 12) { + // Name and Type Info + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setIndex1(iter.nextU2ToInt()); + nameType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); + } + } + + System.out.println("Finished reading Constant pool "); + + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + int fieldCount = iter.nextU2ToInt(); + System.out.println("Field count:" + fieldCount); + for (int i = 1; i <= fieldCount; i++) { + Field f = Field.parse(clzFile.getConstantPool(), iter); + clzFile.addField(f); + } + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + int methodCount = iter.nextU2ToInt(); + System.out.println("Method count:" + methodCount); + for (int i = 1; i <= methodCount; i++) { + Method m = Method.parse(clzFile, iter); + clzFile.addMethod(m); + } + + } + + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/method/Method.java b/group01/1814014897/zhouhui/src/week08/jvm/method/Method.java new file mode 100644 index 0000000000..0db0effd34 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/method/Method.java @@ -0,0 +1,155 @@ +package week08.jvm.method; + +import week08.jvm.clz.ClassFile; +import week08.jvm.cmd.ByteCodeCommand; +import week08.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +import week08.jvm.attr.AttributeInfo; +import week08.jvm.attr.CodeAttr; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.UTF8Info; +import week08.jvm.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for (int i = 1; i <= attribCount; i++) { + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if (AttributeInfo.CODE.equalsIgnoreCase(attrName)) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("only CODE attribute is implemented"); + } + } + return m; + + } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + + public List getParameterList() { + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + } + + private String getParamAndReturnType() { + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/print/ClassFilePrinter.java b/group01/1814014897/zhouhui/src/week08/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..063c01fd41 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/print/ClassFilePrinter.java @@ -0,0 +1,52 @@ +package week08.jvm.print; + +import week08.jvm.clz.ClassFile; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.constant.NameAndTypeInfo; + +import week08.jvm.constant.StringInfo; +import week08.jvm.constant.UTF8Info; +import week08.jvm.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 = ("" + ClassLoader.getSystemResource("")).replaceAll("file:/", ""); + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "week08.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/print/ConstantPoolPrinter.java b/group01/1814014897/zhouhui/src/week08/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..6df553a584 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,103 @@ +package week08.jvm.print; + +import java.util.Formatter; + +import week08.jvm.constant.ConstantInfo.Visitor; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.FieldRefInfo; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.constant.NameAndTypeInfo; +import week08.jvm.constant.StringInfo; +import week08.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + + ConstantPoolPrinter(ConstantPool pool) { + this.pool = pool; + } + + public void print() { + + System.out.println("Constant Pool:"); + + Visitor visitor = new Visitor() { + + @Override + public void visitClassInfo(ClassInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "Class"; + String s2 = "#" + info.getUtf8Index(); + String s3 = "//" + info.getClassName(); + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "FieldRef"; + String s2 = "#" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex(); + String s3 = "//" + info.getClassName() + "." + info.getFieldName() + ":" + info.getFieldType(); + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "MethodRef"; + String s2 = "#" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex(); + String s3; + if (info.getMethodName().equals("")) { + s3 = "//" + info.getClassName() + ".\"" + info.getMethodName() + "\":" + + info.getParamAndReturnType(); + } else { + s3 = "//" + info.getClassName() + "." + info.getMethodName() + ":" + info.getParamAndReturnType(); + } + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "NameAndType"; + String s2 = "#" + info.getIndex1() + ":#" + info.getIndex2(); + String s3; + if (info.getName().equals("")) { + s3 = "//" + "\"" + info.getName() + "\"" + ":" + info.getTypeInfo(); + } else { + s3 = "//" + info.getName() + ":" + info.getTypeInfo(); + } + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + } + + @Override + public void visitString(StringInfo info) { + Formatter f = new Formatter(System.out); + String s1 = "String"; + String s2 = "#" + info.getIndex(); + String s3 = "//" + info.toString(); + f.format("%-20s %-15s %-50s\n", s1, s2, s3); + + } + + @Override + public void visistUTF8(UTF8Info info) { + Formatter f = new Formatter(System.out); + String s1 = "Utf8"; + String s2 = info.getValue(); + f.format("%-20s %-15s\n", s1, s2); + } + }; + + for (int i = 1; i <= pool.getSize(); i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.printf("#%-2d = ", i); + constantInfo.accept(visitor); + } + + } +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/test/ClassFileloaderTest.java b/group01/1814014897/zhouhui/src/week08/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..0defc42915 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,329 @@ +package week08.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.jvm.clz.ClassFile; +import week08.jvm.clz.ClassIndex; +import week08.jvm.cmd.BiPushCmd; +import week08.jvm.cmd.ByteCodeCommand; +import week08.jvm.cmd.OneOperandCmd; +import week08.jvm.cmd.TwoOperandCmd; +import week08.jvm.constant.ClassInfo; +import week08.jvm.constant.ConstantPool; +import week08.jvm.constant.MethodRefInfo; +import week08.jvm.constant.NameAndTypeInfo; +import week08.jvm.constant.UTF8Info; +import week08.jvm.field.Field; +import week08.jvm.loader.ClassFileLoader; +import week08.jvm.method.Method; + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "week08/jvm/test/EmployeeV1"; + + static String path1 = ("" + ClassLoader.getSystemResource("")).replaceAll("file:/", ""); + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week08.jvm.test.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 = "week08.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1040, byteCodes.length); + + } + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week08.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } + + /** + * ---------------------------------------------------------------------- + */ + + @Test + public void testVersion() { + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool() { + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", 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/group01/1814014897/zhouhui/src/week08/jvm/test/EmployeeV1.java b/group01/1814014897/zhouhui/src/week08/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..a761ff5149 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package week08.jvm.test; + +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/group01/1814014897/zhouhui/src/week08/jvm/test/MiniJVMTest.java b/group01/1814014897/zhouhui/src/week08/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..024b51bf58 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package week08.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import week08.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = ("" + ClassLoader.getSystemResource("")).replaceAll("file:/", ""); + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "week08.jvm.test.EmployeeV1"); + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/jvm/util/Util.java b/group01/1814014897/zhouhui/src/week08/jvm/util/Util.java new file mode 100644 index 0000000000..f4e4afa384 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/jvm/util/Util.java @@ -0,0 +1,24 @@ +package week08.jvm.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 + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + return front == rear && elementData[front] == null; + } + + public int size() { + if (isEmpty()) { + return 0; + } + return rear > front ? rear - front : DEFAULT_SIZE - (rear - front); + } + + public void enQueue(E data) { + if (this.size() >= DEFAULT_SIZE) { + throw new RuntimeException("the queue is full."); + } + elementData[rear] = data; + rear = (rear + 1) % DEFAULT_SIZE; + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("this queue if empty."); + } + Object data = elementData[front]; + elementData[front] = null; + front = (front + 1) % DEFAULT_SIZE; + return (E) data; + } +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/Josephus.java b/group01/1814014897/zhouhui/src/week08/queue/Josephus.java new file mode 100644 index 0000000000..b03c99423b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/Josephus.java @@ -0,0 +1,32 @@ +package week08.queue; + +import java.util.ArrayList; +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) { + List killOrder = new ArrayList(); + Queue queue = new Queue(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + + while (!queue.isEmpty()) { + for (int i = 0; i < m - 1; i++) { + queue.enQueue(queue.deQueue()); + } + killOrder.add(queue.deQueue()); + } + + return killOrder; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/Queue.java b/group01/1814014897/zhouhui/src/week08/queue/Queue.java new file mode 100644 index 0000000000..debeab313e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/Queue.java @@ -0,0 +1,61 @@ +package week08.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group01/1814014897/zhouhui/src/week08/queue/QueueWithTwoStacks.java b/group01/1814014897/zhouhui/src/week08/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..35a3492b27 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/QueueWithTwoStacks.java @@ -0,0 +1,46 @@ +package week08.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * + * @author Hui Zhou + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + public int size() { + return stack1.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + int stack1Size = stack1.size(); + for (int i = 0; i < stack1Size; i++) { + stack2.push(stack1.pop()); + } + E deQueue = stack2.pop(); + int stack2Size = stack2.size(); + for (int i = 0; i < stack2Size; i++) { + stack1.push(stack2.pop()); + } + return deQueue; + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/test/CircleQueueTest.java b/group01/1814014897/zhouhui/src/week08/queue/test/CircleQueueTest.java new file mode 100644 index 0000000000..c8608097a8 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/test/CircleQueueTest.java @@ -0,0 +1,43 @@ +package week08.queue.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.queue.CircleQueue; + +public class CircleQueueTest { + + CircleQueue cq = new CircleQueue(); + + @Test + public void testenQueue() { + Assert.assertTrue(cq.isEmpty()); + Assert.assertEquals(0, cq.size()); + for (int i = 0; i < 10; i++) { + cq.enQueue(i); + } + Assert.assertFalse(cq.isEmpty()); + Assert.assertEquals(10, cq.size()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(i, cq.deQueue().intValue()); + } + Assert.assertTrue(cq.isEmpty()); + Assert.assertEquals(0, cq.size()); + } + + @Test + public void testdeQueue() { + for (int i = 0; i < 10; i++) { + cq.enQueue(i); + } + Assert.assertFalse(cq.isEmpty()); + Assert.assertEquals(10, cq.size()); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(i, cq.deQueue().intValue()); + } + Assert.assertTrue(cq.isEmpty()); + Assert.assertEquals(0, cq.size()); + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/test/JosephusTest.java b/group01/1814014897/zhouhui/src/week08/queue/test/JosephusTest.java new file mode 100644 index 0000000000..8fab3cc72a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/test/JosephusTest.java @@ -0,0 +1,29 @@ +package week08.queue.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.queue.Josephus; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/test/QueueTest.java b/group01/1814014897/zhouhui/src/week08/queue/test/QueueTest.java new file mode 100644 index 0000000000..70bfdf727a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/test/QueueTest.java @@ -0,0 +1,46 @@ +package week08.queue.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.queue.Queue; + +public class QueueTest { + + Queue queue = new Queue(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 100; i++) { + queue.enQueue(i); + } + } + + @Test + public void testEnQueue() { + Assert.assertFalse(queue.isEmpty()); + Assert.assertEquals(100, queue.size()); + for (int i = 100; i < 200; i++) { + queue.enQueue(i); + } + Assert.assertEquals(200, queue.size()); + for (int i = 0; i < 200; i++) { + Assert.assertEquals(i, queue.deQueue().intValue()); + } + Assert.assertTrue(queue.isEmpty()); + Assert.assertEquals(0, queue.size()); + } + + @Test + public void testDeQueue() { + Assert.assertFalse(queue.isEmpty()); + Assert.assertEquals(100, queue.size()); + for (int i = 0; i < 100; i++) { + Assert.assertEquals(i, queue.deQueue().intValue()); + } + Assert.assertTrue(queue.isEmpty()); + Assert.assertEquals(0, queue.size()); + } + +} diff --git a/group01/1814014897/zhouhui/src/week08/queue/test/QueueWithTwoStacksTest.java b/group01/1814014897/zhouhui/src/week08/queue/test/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..d47acfca59 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week08/queue/test/QueueWithTwoStacksTest.java @@ -0,0 +1,46 @@ +package week08.queue.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week08.queue.QueueWithTwoStacks; + +public class QueueWithTwoStacksTest { + + QueueWithTwoStacks qwts = new QueueWithTwoStacks(); + + @Before + public void setUp() throws Exception { + for (int i = 0; i < 100; i++) { + qwts.enQueue(i); + } + } + + @Test + public void testEnQueue() { + Assert.assertFalse(qwts.isEmpty()); + Assert.assertEquals(100, qwts.size()); + for (int i = 100; i < 200; i++) { + qwts.enQueue(i); + } + Assert.assertEquals(200, qwts.size()); + for (int i = 0; i < 200; i++) { + Assert.assertEquals(i, qwts.deQueue().intValue()); + } + Assert.assertTrue(qwts.isEmpty()); + Assert.assertEquals(0, qwts.size()); + } + + @Test + public void testDeQueue() { + Assert.assertFalse(qwts.isEmpty()); + Assert.assertEquals(100, qwts.size()); + for (int i = 0; i < 100; i++) { + Assert.assertEquals(i, qwts.deQueue().intValue()); + } + Assert.assertTrue(qwts.isEmpty()); + Assert.assertEquals(0, qwts.size()); + } + +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/QuickMinStack.java b/group01/1814014897/zhouhui/src/week09/stack/QuickMinStack.java new file mode 100644 index 0000000000..35ae39e4aa --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/QuickMinStack.java @@ -0,0 +1,47 @@ +package week09.stack; + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * findMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * + * @author Hui Zhou + * + */ +public class QuickMinStack { + Stack stack = new Stack(); + Stack minStack = new Stack(); + int min; + + public void push(int data) { + stack.push(data); + + if (minStack.isEmpty()) { + minStack.push(data); + min = minStack.peek(); + } else { + if (data <= min) { + min = data; + minStack.push(data); + } + } + } + + public int pop() { + if (stack.isEmpty()) { + throw new RuntimeException("the stack is empty."); + } + if (stack.peek() == minStack.peek()) { + minStack.pop(); + } + return stack.pop(); + } + + public int findMin() { + if (stack.isEmpty()) { + throw new RuntimeException("the stack is empty."); + } + return minStack.pop(); + } +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/StackWithTwoQueues.java b/group01/1814014897/zhouhui/src/week09/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..e1a8a2d3de --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/StackWithTwoQueues.java @@ -0,0 +1,36 @@ +package week09.stack; + +import week08.queue.Queue; + +public class StackWithTwoQueues { + private Queue queue1 = new Queue(); + private Queue queue2 = new Queue(); + + public boolean isEmpty() { + return queue1.isEmpty(); + } + + public int size() { + return queue1.size(); + } + + public void push(T data) { + queue1.enQueue(data); + } + + public T pop() { + if (queue1.isEmpty()) { + throw new RuntimeException("the stack is empty."); + } + int queue1Size = queue1.size(); + for (int i = 0; i < queue1Size - 1; i++) { + queue2.enQueue(queue1.deQueue()); + } + T popValue = queue1.deQueue(); + while (!queue2.isEmpty()) { + queue1.enQueue(queue2.deQueue()); + } + return popValue; + } + +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/TwoStackInOneArray.java b/group01/1814014897/zhouhui/src/week09/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..8c8fefe9c9 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/TwoStackInOneArray.java @@ -0,0 +1,100 @@ +package week09.stack; + +import java.util.Arrays; + +/** + * 用一个数组实现两个栈 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + * @author Hui Zhou + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + int i = 0; + int j = data.length - 1; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + if (i < j) { + data[i++] = o; + } else { + addCapacity(); + data[i++] = o; + } + } + + private void addCapacity() { + int oldCapacity = data.length; + int newCapacity = oldCapacity + (oldCapacity >> 2); + Object[] tempPre = Arrays.copyOfRange(data, 0, i); + Object[] tempPost = Arrays.copyOfRange(data, j + 1, data.length); + data = Arrays.copyOf(tempPre, newCapacity); + System.arraycopy(tempPost, 0, data, data.length - tempPost.length, tempPost.length); + j = data.length - tempPost.length - 1; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if (i <= 0) { + throw new RuntimeException("stack1 is empty."); + } + Object pop1Value = data[--i]; + data[i] = null; + return pop1Value; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return data[i - 1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + if (j > i) { + data[j--] = o; + } else { + addCapacity(); + data[j--] = o; + } + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (j >= data.length - 1) { + throw new RuntimeException("stack2 is empty."); + } + Object pop2Value = data[++j]; + data[j] = null; + return pop2Value; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + return data[j + 1]; + } + +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/test/QuickMinStackTest.java b/group01/1814014897/zhouhui/src/week09/stack/test/QuickMinStackTest.java new file mode 100644 index 0000000000..5d37fb78af --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/test/QuickMinStackTest.java @@ -0,0 +1,63 @@ +package week09.stack.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.stack.QuickMinStack; + +public class QuickMinStackTest { + + QuickMinStack qms = new QuickMinStack(); + + @Before + public void setUp() throws Exception { + qms.push(9); + qms.push(5); + qms.push(6); + qms.push(10); + qms.push(2); + qms.push(3); + qms.push(13); + } + + @Test + public void testPush() { + for (int i = 0; i < 10; i++) { + qms.push(i); + } + for (int i = 9; i >= 0; i--) { + Assert.assertEquals(i, qms.pop()); + } + } + + @Test + public void testPop() { + Assert.assertEquals(13, qms.pop()); + Assert.assertEquals(3, qms.pop()); + Assert.assertEquals(2, qms.pop()); + Assert.assertEquals(10, qms.pop()); + Assert.assertEquals(6, qms.pop()); + Assert.assertEquals(5, qms.pop()); + Assert.assertEquals(9, qms.pop()); + + } + + @Test + public void testFindMin() { + Assert.assertEquals(2, qms.findMin()); + qms.push(2); + qms.push(6); + qms.push(26); + Assert.assertEquals(2, qms.findMin()); + qms.pop(); + qms.pop(); + qms.pop(); + qms.pop(); + qms.pop(); + qms.pop(); + Assert.assertEquals(5, qms.findMin()); + + } + +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/test/StackWithTwoQueuesTest.java b/group01/1814014897/zhouhui/src/week09/stack/test/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..cd9f33519c --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/test/StackWithTwoQueuesTest.java @@ -0,0 +1,46 @@ +package week09.stack.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.stack.StackWithTwoQueues; + + +public class StackWithTwoQueuesTest { + + StackWithTwoQueues swtq = new StackWithTwoQueues(); + + @Before + public void setUp() throws Exception { + for(int i=0;i<100;i++){ + swtq.push(i); + } + } + + @Test + public void testPush() { + Assert.assertFalse(swtq.isEmpty()); + Assert.assertEquals(100, swtq.size()); + + for(int i=100;i<200;i++){ + swtq.push(i); + } + + Assert.assertEquals(200, swtq.size()); + for(int i=199;i>=0;i--){ + Assert.assertEquals(i, swtq.pop().intValue()); + } + Assert.assertEquals(0, swtq.size()); + } + + @Test + public void testPop() { + for(int i=99;i>=0;i--){ + Assert.assertEquals(i, swtq.pop().intValue()); + } + Assert.assertTrue(swtq.isEmpty()); + Assert.assertEquals(0, swtq.size()); + } + +} diff --git a/group01/1814014897/zhouhui/src/week09/stack/test/TwoStackInOneArrayTest.java b/group01/1814014897/zhouhui/src/week09/stack/test/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..ebbc4d6420 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week09/stack/test/TwoStackInOneArrayTest.java @@ -0,0 +1,77 @@ +package week09.stack.test; + + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week09.stack.TwoStackInOneArray; + + +public class TwoStackInOneArrayTest { + + TwoStackInOneArray tsioa = new TwoStackInOneArray(); + + @Before + public void setUp() throws Exception { + for(int i=0;i<10;i++){ + tsioa.push1(i); + } + for(int j=20;j<30;j++){ + tsioa.push2(j); + } + } + + @Test + public void testPush1() { + for(int i=10;i<20;i++){ + tsioa.push1(i); + } + for(int i=19;i>=0;i--){ + Assert.assertEquals(i, tsioa.pop1()); + } + } + + @Test + public void testPop1() { + for(int i=9;i>=0;i--){ + Assert.assertEquals(i, tsioa.pop1()); + } + } + + @Test + public void testPeek1() { + Assert.assertEquals(9, tsioa.peek1()); + tsioa.pop1(); + Assert.assertEquals(8, tsioa.peek1()); + tsioa.pop1(); + Assert.assertEquals(7, tsioa.peek1()); + } + + @Test + public void testPush2() { + for(int i=30;i<40;i++){ + tsioa.push2(i); + } + for(int i=39;i>=20;i--){ + Assert.assertEquals(i, tsioa.pop2()); + } + } + + @Test + public void testPop2() { + for(int i=29;i>=20;i--){ + Assert.assertEquals(i, tsioa.pop2()); + } + } + + @Test + public void testPeek2() { + Assert.assertEquals(29, tsioa.peek2()); + tsioa.pop2(); + Assert.assertEquals(28, tsioa.peek2()); + tsioa.pop2(); + Assert.assertEquals(27, tsioa.peek2()); + } + +} diff --git a/group01/275150374/275150374Learning/.idea/compiler.xml b/group01/275150374/275150374Learning/.idea/compiler.xml deleted file mode 100644 index 217af471a9..0000000000 --- a/group01/275150374/275150374Learning/.idea/compiler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/group01/275150374/275150374Learning/.idea/encodings.xml b/group01/275150374/275150374Learning/.idea/encodings.xml deleted file mode 100644 index e206d70d85..0000000000 --- a/group01/275150374/275150374Learning/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/group01/275150374/275150374Learning/.idea/misc.xml b/group01/275150374/275150374Learning/.idea/misc.xml deleted file mode 100644 index de8f7c75a3..0000000000 --- a/group01/275150374/275150374Learning/.idea/misc.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/group01/275150374/275150374Learning/.idea/modules.xml b/group01/275150374/275150374Learning/.idea/modules.xml deleted file mode 100644 index 5534fceb30..0000000000 --- a/group01/275150374/275150374Learning/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/group01/275150374/275150374Learning/.idea/vcs.xml b/group01/275150374/275150374Learning/.idea/vcs.xml deleted file mode 100644 index c2365ab11f..0000000000 --- a/group01/275150374/275150374Learning/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/group01/765324639/pom.xml b/group01/765324639/pom.xml index 24816f0f3f..5b30da402c 100644 --- a/group01/765324639/pom.xml +++ b/group01/765324639/pom.xml @@ -1,18 +1,37 @@ - - 4.0.0 - com.zavier - 765324639Learning - 0.0.1-SNAPSHOT - - - junit - junit - 4.12 - - - dom4j - dom4j - 1.6.1 - - + + 4.0.0 + com.zavier + 765324639Learning + 0.0.1-SNAPSHOT + + + junit + junit + 4.12 + + + dom4j + dom4j + 1.6.1 + + + org.apache.commons + commons-lang3 + 3.5 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + \ No newline at end of file diff --git a/group01/765324639/src/main/java/datastructure/Queue.java b/group01/765324639/src/main/java/datastructure/Queue.java deleted file mode 100644 index d4cfec525e..0000000000 --- a/group01/765324639/src/main/java/datastructure/Queue.java +++ /dev/null @@ -1,27 +0,0 @@ -package datastructure; - -import datastructure.linkedlist.LinkedList; - -public class Queue { - - private LinkedList list = new LinkedList(); - - public void enQueue(Object o) { - list.add(o); - } - - public Object deQueue() { - if (list.size() == 0) { - return null; - } - return list.removeFirst(); - } - - public boolean isEmpty() { - return list.size() == 0; - } - - public int size() { - return list.size(); - } -} diff --git a/group01/765324639/src/main/java/datastructure/queue/CircleQueue.java b/group01/765324639/src/main/java/datastructure/queue/CircleQueue.java new file mode 100644 index 0000000000..a0e640bb9a --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/queue/CircleQueue.java @@ -0,0 +1,53 @@ +package datastructure.queue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + private int size = 0; + + public boolean isEmpty() { + return size == 0; + + } + + public int size() { + return size; + } + + + + public void enQueue(E data) { + if (size >= DEFAULT_SIZE) { + throw new RuntimeException("队列已满"); + } + elementData[rear] = data; + rear = (rear + 1) % DEFAULT_SIZE; + size++; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + if (size <= 0) { + throw new RuntimeException("队列已空"); + } + size--; + Object object = elementData[front]; + front = (front + 1) % DEFAULT_SIZE; + return (E) object; + } +} diff --git a/group01/765324639/src/main/java/datastructure/queue/Josephus.java b/group01/765324639/src/main/java/datastructure/queue/Josephus.java new file mode 100644 index 0000000000..b927353cb4 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/queue/Josephus.java @@ -0,0 +1,56 @@ +package datastructure.queue; + +import java.util.ArrayList; +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) { + List list = new ArrayList<>(); + + Queue queue1 = new Queue(); + for (int i = 0; i < n; i++) { + queue1.enQueue(i); + } + Queue queue2 = new Queue(); + + int index = 1; + while (list.size() < n - 1) { + int queue1Size = queue1.size(); + for (int i = 0; i < queue1Size; i++) { + if (index % m != 0) { + queue2.enQueue(queue1.deQueue()); + } else { + list.add((int) queue1.deQueue()); + index = 0; + } + index++; + } + int queue2Size = queue2.size(); + for (int i = 0; i < queue2Size; i++) { + if (index % m != 0) { + queue1.enQueue(queue2.deQueue()); + } else { + list.add((int) queue2.deQueue()); + index = 0; + } + index++; + } + } + if (!queue1.isEmpty()) { + list.add((int)queue1.deQueue()); + } + if (!queue2.isEmpty()) { + list.add((int)queue2.deQueue()); + } + return list; + } + +} diff --git a/group01/765324639/src/main/java/datastructure/queue/Queue.java b/group01/765324639/src/main/java/datastructure/queue/Queue.java new file mode 100644 index 0000000000..07f6586f21 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/queue/Queue.java @@ -0,0 +1,27 @@ +package datastructure.queue; + +import datastructure.linkedlist.LinkedList; + +public class Queue { + + private LinkedList list = new LinkedList(); + + public void enQueue(Object o) { + list.add(o); + } + + public Object deQueue() { + if (list.size() == 0) { + return null; + } + return list.removeFirst(); + } + + public boolean isEmpty() { + return list.size() == 0; + } + + public int size() { + return list.size(); + } +} diff --git a/group01/765324639/src/main/java/datastructure/queue/QueueWithTwoStacks.java b/group01/765324639/src/main/java/datastructure/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..2a2ea9cb91 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/queue/QueueWithTwoStacks.java @@ -0,0 +1,60 @@ +package datastructure.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() { + if (stack1.empty() && stack2.empty()) { + return true; + } + return false; + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + return null; + } + + if (!stack2.empty()) { + return stack2.pop(); + } + while (!stack1.empty()) { + stack2.push(stack1.pop()); + } + return stack2.pop(); + } + + + + } + diff --git a/group01/765324639/src/main/java/datastructure/stack/QuickMinStack.java b/group01/765324639/src/main/java/datastructure/stack/QuickMinStack.java new file mode 100644 index 0000000000..e06a6b4e11 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/QuickMinStack.java @@ -0,0 +1,145 @@ +package datastructure.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + private int size = 0; + private int index = 0; // 目前的最早入库索引 + private Node head; + + public int findMin(){ + if (head == null) { + throw new RuntimeException("Stack is empty, don't have min!"); + } + return head.data; + } + + public void push(int data){ + if (size == 0) { + head = new Node(size++, data); + } else { + Node temp = head; + while (temp.next != null && data > temp.data) { + temp = temp.next; + } + Node newNode = new Node(size++, data); + + // 未到达最后节点,或者到达最后节点,但是要插入的数据小于最后一个节点,此时插入到temp节点之前 + if (unReachedLastNodeOrSmallThanLastNode(data, temp)) { + insertBefore(newNode, temp); + } else { // 其他情况插入到temp节点之后 + insertAfter(newNode, temp); + } + } + } + + private boolean unReachedLastNodeOrSmallThanLastNode(int data, Node temp) { + return temp.next != null || (temp.next == null && data < temp.data); + } + + /** + * 将src节点插入到dest之前 + * @param src + * @param dest + */ + private void insertBefore(Node src, Node dest) { + if (dest.prev == null) { // dest为首个元素 + head = src; + } else { + src.prev = dest.prev; + dest.prev.next = src; + } + dest.prev = src; + src.next = dest; + } + + /** + * 将src节点插入到dest之后 + * @param src + * @param dest + */ + private void insertAfter(Node src, Node dest) { + if (dest.next == null) { // temp为最后一个元素 + dest.next = src; + src.prev = dest; + } else { + dest = dest.next; + insertBefore(src, dest); + } + } + + public int pop(){ + Node temp = head; + while (temp.next != null) { + if (temp.index == this.index) { + Node dest = remove(temp); + return dest.data; + } + temp = temp.next; + } + if (temp.index == this.index) { + Node dest = remove(temp); + return dest.data; + } + throw new RuntimeException("Stack is Empty!"); + } + + private Node remove(Node node) { + if (node.prev == null && node.next == null) { // 唯一的元素,删除后将初始化size和index + this.size = 0; + this.index = 0; + return node; + } + if (node.prev == null) { // 元素在开头位置 + head = head.next; + node.next.prev = null; + node.next = null; + } else if (node.next == null) { // 元素在结尾位置 + node.prev.next = null; + node.prev = null; + } else { // 元素在中间位置 + node.prev.next = node.next; + node.next.prev = node.prev; + node.prev = null; + node.next = null; + } + this.size--; + this.index++; + return node; + } + + public int size() { + return size; + } + + // 调试输出用 +// @Override +// public String toString() { +// StringBuilder builder = new StringBuilder(size); +// builder.append("["); +// Node temp = head; +// while (temp.next != null) { +// builder.append(temp.data + ", "); +// temp = temp.next; +// } +// builder.append(temp.data + "]"); +// return builder.toString(); +// } + + private static class Node { + Node prev; + int data; + int index; // 插入的顺序 + Node next; + + Node (int index, int data) { + this.index = index; + this.data = data; + } + } +} diff --git a/group01/765324639/src/main/java/datastructure/stack/StackWithTwoQueues.java b/group01/765324639/src/main/java/datastructure/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..3efc65367c --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/StackWithTwoQueues.java @@ -0,0 +1,26 @@ +package datastructure.stack; + +import datastructure.queue.Queue; + +public class StackWithTwoQueues { + + private Queue queue1 = new Queue(); + private Queue queue2 = new Queue(); + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + int size = queue1.size(); + for (int i = 0; i < size - 1; i++) { + queue2.enQueue(queue1.deQueue()); + } + int dest = (int) queue1.deQueue(); + queue1 = queue2; + queue2 = queue1; + return dest; + } + + +} diff --git a/group01/765324639/src/main/java/datastructure/stack/TwoStackInOneArray.java b/group01/765324639/src/main/java/datastructure/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..9149218363 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/TwoStackInOneArray.java @@ -0,0 +1,83 @@ +package datastructure.stack; + +import java.util.Arrays; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2 = data.length - 1; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + ensureCapacity(); + data[index1++] = o; + } + + private void ensureCapacity() { + if (isFull()) { + grow(); + } + } + + private boolean isFull() { + return index1 + 1 == index2; + } + + private void grow() { + int stack2Length = data.length - 1 - index2; + data = Arrays.copyOf(data, data.length * 2); + int oldIndex2 = index2; + index2 = data.length - stack2Length - 1; + System.arraycopy(data, oldIndex2 + 1, data, index2 + 1, stack2Length); + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + return data[--index1]; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return data[index1 - 1]; + } + /** + * 向第二个栈压入元素 + */ + public void push2(Object o){ + ensureCapacity(); + data[index2--] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + return data[++index2]; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return data[index2 + 1]; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java index 43a02cfa48..fcef4cdb7f 100644 --- a/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java +++ b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java @@ -49,7 +49,7 @@ public String toString(ConstantPool pool){ StringBuilder buffer = new StringBuilder(); //buffer.append("Code:").append(code).append("\n"); for(int i=0;i codeMap = new HashMap(); static{ @@ -104,19 +141,6 @@ public String getOpCode() { public abstract int getLength(); - - - - @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.toUpperCase()); if(txt == null){ @@ -125,5 +149,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java b/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java index 189c208e87..6889c31d58 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java +++ b/group01/765324639/src/main/java/minijvm/cmd/CommandParser.java @@ -114,7 +114,8 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { } calcuateOffset(commandList); ByteCodeCommand[] commands = new ByteCodeCommand[commandList.size()]; - return commandList.toArray(commands); + commandList.toArray(commands); + return commands; } private static void calcuateOffset(List cmds) { diff --git a/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java index 972ae719be..962857392f 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/GetFieldCmd.java @@ -1,7 +1,10 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.FieldRefInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -10,11 +13,20 @@ public GetFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String fieldName = fieldRefInfo.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + frame.getOprandStack().push(fieldValue); + } + diff --git a/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java index 648a8940ec..fdfbb73231 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/GetStaticFieldCmd.java @@ -1,7 +1,11 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.FieldRefInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.Heap; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -11,9 +15,24 @@ public GetStaticFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if ("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)) { + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + } + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java b/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java index 460706b635..e965af081c 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/InvokeSpecialCmd.java @@ -1,7 +1,11 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.MethodRefInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.MethodArea; +import minijvm.engine.StackFrame; +import minijvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -11,11 +15,27 @@ public InvokeSpecialCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + // java.lang.Object类的init方法(构造函数)不需要实现 + if ("java/lang/Object".equals(methodRefInfo.getClassName()) + && "".equals(methodRefInfo.getMethodName())) { + return; + } + + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java b/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java index b2957bbcb6..f0e50b1eb0 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/InvokeVirtualCmd.java @@ -1,7 +1,12 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.MethodRefInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.JavaObject; +import minijvm.engine.MethodArea; +import minijvm.engine.StackFrame; +import minijvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -10,10 +15,52 @@ public InvokeVirtualCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } + + private boolean isSystemOutPrintlnMethod(String className, String methodName) { + return "java/io/PrintStream".equals(className) && "println".equals(methodName); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + if (isSystemOutPrintlnMethod(className, methodName)) { + JavaObject jo = frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("--------------------" + value + "-------------------"); + + frame.getOprandStack().pop(); + return; + } + + JavaObject jo = frame.getOprandStack().peek(); + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + String currentClassName = jo.getClassName(); + while (currentClassName != null) { + ClassFile cuClassFile = ma.findClassFile(currentClassName); + m = cuClassFile.getMethod(methodRefInfo.getMethodName(), methodRefInfo.getParamAndReturnType()); + if (m != null) { + break; + } else { + currentClassName = cuClassFile.getSuperClassName(); + } + } + + if (m == null) { + throw new RuntimeException("找不到对应的方法:" + methodRefInfo.toString()); + } + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(m); + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java b/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java index b6ca03f4ac..a864daa2f1 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import minijvm.constant.ConstantInfo; import minijvm.constant.ConstantPool; import minijvm.constant.StringInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.Heap; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -12,9 +16,9 @@ public LdcCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - ConstantInfo info = pool.getConstantInfo(this.getOperand()); + ConstantInfo info = getConstantInfo(this.getOperand()); String value = "TBD"; if(info instanceof StringInfo){ @@ -25,5 +29,20 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = pool.getConstantInfo(this.getOperand()); + + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo) info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } else { + throw new RuntimeException("暂时只支持字符串常量ldc"); + } + } } diff --git a/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java b/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java index aaff3aecef..03e6c7a02f 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/NewObjectCmd.java @@ -1,7 +1,11 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.ClassInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.Heap; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -10,10 +14,20 @@ public NewObjectCmd(ClassFile clzFile, String opCode){ } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsClassInfo(pool); + return super.getOperandAsClassInfo(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int index = this.getIndex(); + ClassInfo info = (ClassInfo) this.getConstantInfo(index); + String className = info.getClassName(); + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + + } + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java b/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java index e9a3493426..be8d9b0cfd 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/NoOperandCmd.java @@ -1,7 +1,10 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.engine.ExecutionResult; +import minijvm.engine.Heap; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -10,7 +13,7 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } @@ -21,4 +24,68 @@ public int getLength(){ return 1; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + String opCode = this.getOpCode(); + if (ByteCodeCommand.aload_0.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(0); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.aload_1.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(1); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.aload_2.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(2); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.iload_1.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(1); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.iload_2.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(2); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.iload_3.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(3); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.fload_3.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getLocalVariableValue(3); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.voidreturn.equalsIgnoreCase(opCode)) { + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + } else if (ByteCodeCommand.ireturn.equalsIgnoreCase(opCode)) { + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } else if (ByteCodeCommand.freturn.equalsIgnoreCase(opCode)) { + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } else if (ByteCodeCommand.astore_1.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getOprandStack().pop(); + frame.setLocalVariableValue(1, jo); + } else if (ByteCodeCommand.dup.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.iconst_0.equalsIgnoreCase(opCode)) { + JavaObject jo = Heap.getInstance().newInt(0); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.iconst_1.equalsIgnoreCase(opCode)) { + JavaObject jo = Heap.getInstance().newInt(1); + frame.getOprandStack().push(jo); + } else if (ByteCodeCommand.istore_1.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getOprandStack().pop(); + frame.setLocalVariableValue(1, jo); + } else if (ByteCodeCommand.istore_2.equalsIgnoreCase(opCode)) { + JavaObject jo = frame.getOprandStack().pop(); + frame.setLocalVariableValue(2, jo); + } else if (ByteCodeCommand.iadd.equalsIgnoreCase(opCode)) { + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue() + jo2.getIntValue()); + frame.getOprandStack().push(sum); + } else if (ByteCodeCommand.aconst_null.equalsIgnoreCase(opCode)) { + frame.getOprandStack().push(null); + } else { + throw new RuntimeException("未实现的指令:" + opCode); + } + } + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java b/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java index ae41b17fde..a28ed0015f 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/PutFieldCmd.java @@ -1,7 +1,12 @@ package minijvm.cmd; import minijvm.clz.ClassFile; -import minijvm.constant.ConstantPool; +import minijvm.constant.ClassInfo; +import minijvm.constant.FieldRefInfo; +import minijvm.constant.NameAndTypeInfo; +import minijvm.engine.ExecutionResult; +import minijvm.engine.JavaObject; +import minijvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -10,10 +15,23 @@ public PutFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(fieldRefInfo.getClassInfoIndex()); + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) this.getConstantInfo(fieldRefInfo.getNameAndTypeIndex()); + String fieldName = nameAndTypeInfo.getName(); + String fieldTye = nameAndTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + objectRef.setFieldValue(fieldName, fieldValue); + } + } diff --git a/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java b/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java index 262bedc338..c6f1cea081 100644 --- a/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java +++ b/group01/765324639/src/main/java/minijvm/cmd/TwoOperandCmd.java @@ -3,7 +3,6 @@ import minijvm.clz.ClassFile; import minijvm.constant.ClassInfo; import minijvm.constant.ConstantInfo; -import minijvm.constant.ConstantPool; import minijvm.constant.FieldRefInfo; import minijvm.constant.MethodRefInfo; @@ -39,14 +38,14 @@ public int getIndex(){ return index; } - protected String getOperandAsClassInfo(ConstantPool pool){ + protected String getOperandAsClassInfo(){ int index = getIndex(); String codeTxt = getReadableCodeText(); - ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + ClassInfo info = (ClassInfo)getConstantInfo(index); return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); } - protected String getOperandAsMethod(ConstantPool pool){ + protected String getOperandAsMethod(){ int index = getIndex(); String codeTxt = getReadableCodeText(); ConstantInfo constInfo = this.getConstantInfo(index); @@ -54,7 +53,7 @@ protected String getOperandAsMethod(ConstantPool pool){ return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); } - protected String getOperandAsField(ConstantPool pool){ + protected String getOperandAsField(){ int index = getIndex(); String codeTxt = getReadableCodeText(); diff --git a/group01/765324639/src/main/java/minijvm/engine/ExecutionResult.java b/group01/765324639/src/main/java/minijvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..288455261e --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/ExecutionResult.java @@ -0,0 +1,53 @@ +package minijvm.engine; + +import minijvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action){ + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/engine/ExecutorEngine.java b/group01/765324639/src/main/java/minijvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..4f15f3e775 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/ExecutorEngine.java @@ -0,0 +1,61 @@ +package minijvm.engine; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +import minijvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + StackFrame stackFrame = StackFrame.create(mainMethod); + stack.push(stackFrame); + + while (!stack.empty()) { + StackFrame frame = stack.peek(); + ExecutionResult result = frame.execute(); + + if (result.isPauseAndRunNewFrame()) { + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + // 当前栈帧将参数传递给下一个栈帧中的局部变量表 + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + } else { + stack.pop(); + } + } + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + // 主要用来获取下一个栈帧需要的参数个数 + Method nextMethod = nextFrame.getMethod(); + List parameterList = nextMethod.getParameterList(); + int paramNum = parameterList.size() + 1; // 给this参数增加空间 + + List values = new ArrayList<>(); + + // 将当前栈帧中的操作数栈(参数)传递给下一个栈帧 + for (int i = 0; i < paramNum; i++) { + values.add(currentFrame.getOprandStack().pop()); + } + // 因为弹出的参数顺序与栈帧中的相反,故逆置一下以让参数一一对应 + Collections.reverse(values); + + nextFrame.setLocalVariableTable(values); + } + +} diff --git a/group01/765324639/src/main/java/minijvm/engine/Heap.java b/group01/765324639/src/main/java/minijvm/engine/Heap.java new file mode 100644 index 0000000000..47c2c0e534 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/Heap.java @@ -0,0 +1,39 @@ +package minijvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/engine/JavaObject.java b/group01/765324639/src/main/java/minijvm/engine/JavaObject.java new file mode 100644 index 0000000000..118cb6bdb5 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/JavaObject.java @@ -0,0 +1,72 @@ +package minijvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + @Override + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/engine/MethodArea.java b/group01/765324639/src/main/java/minijvm/engine/MethodArea.java new file mode 100644 index 0000000000..e426c1ea1d --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/MethodArea.java @@ -0,0 +1,77 @@ +package minijvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import minijvm.clz.ClassFile; +import minijvm.constant.MethodRefInfo; +import minijvm.loader.ClassFileLoader; +import minijvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) throws ClassNotFoundException{ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className) { + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = null; + try { + clzFile = this.clzLoader.loadClass(className); + } catch (ClassNotFoundException e) { + throw new RuntimeException("没有找到对应类文件"); + } + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef) { + ClassFile clz = this.findClassFile(methodRef.getClassName()); + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + if (m == null) { + throw new RuntimeException("找不到方法:" + methodRef.getMethodName()); + } + return m; + + } +} diff --git a/group01/765324639/src/main/java/minijvm/engine/MiniJVM.java b/group01/765324639/src/main/java/minijvm/engine/MiniJVM.java new file mode 100644 index 0000000000..c204e1c1fa --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package minijvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import minijvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException, ClassNotFoundException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + // 操作数栈 + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + private StackFrame(Method m) { + this.m = m; + + } + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做??---如果局部变量表的size小于index,则必须填充之间的值,否则会出错 + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group01/765324639/src/main/java/minijvm/method/Method.java b/group01/765324639/src/main/java/minijvm/method/Method.java index 248c3e79f1..114f154afd 100644 --- a/group01/765324639/src/main/java/minijvm/method/Method.java +++ b/group01/765324639/src/main/java/minijvm/method/Method.java @@ -1,5 +1,10 @@ package minijvm.method; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + import minijvm.attr.CodeAttr; import minijvm.clz.ClassFile; import minijvm.cmd.ByteCodeCommand; @@ -75,4 +80,46 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + private String getParamAndReturnType() { + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile().getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList() { + String paramAndType = getParamAndReturnType(); + + // 获取参数和返回类型中的参数部分 + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + String param = paramAndType.substring(first + 1, last); + + List paramList = new ArrayList<>(); + if (StringUtils.isEmpty(param)) { + return paramList; + } + + while (!"".equals(param)) { + int pos = 0; + // 对象类型(以'L'开头,以';'结尾) + if (param.charAt(pos) == 'L') { + int end = param.indexOf(";"); + if (end == -1) { + throw new RuntimeException("对象类型没有以;结尾"); + } + paramList.add(param.substring(pos + 1, end)); + pos = end + 1; + } else if (param.charAt(pos) == 'I') { // int类型 + paramList.add("I"); + pos++; + } else if (param.charAt(pos) == 'F') { // float类型 + paramList.add("F"); + pos++; + } else { + throw new RuntimeException("这个参数类型还没有实现" + param.charAt(pos)); + } + param = param.substring(pos); + } + return paramList; + } } diff --git a/group01/765324639/src/test/java/datastructure/QueueTest.java b/group01/765324639/src/test/java/datastructure/QueueTest.java deleted file mode 100644 index b24f75ed53..0000000000 --- a/group01/765324639/src/test/java/datastructure/QueueTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package datastructure; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class QueueTest { - - private Queue queue = new Queue(); - - @Before - public void setUp() { - for (int i = 0; i < 500; i++) { - queue.enQueue(i); - } - } - - @Test - public void testEnQueue() { - for (int i = 0; i < 100; i++) { - queue.enQueue(i); - } - Assert.assertEquals(600, queue.size()); - } - - @Test - public void testDeQueue() { - for (int i = 0; i < 500; i++) { - Assert.assertEquals(i, queue.deQueue()); - } - Assert.assertNull(queue.deQueue()); - Assert.assertNull(queue.deQueue()); - } - - @Test - public void testIsEmpty() { - Assert.assertFalse(queue.isEmpty()); - Queue q = new Queue(); - Assert.assertTrue(q.isEmpty()); - } - - @Test - public void testSize() { - Assert.assertEquals(500, queue.size()); - } - -} diff --git a/group01/765324639/src/test/java/datastructure/queue/CircleQueueTest.java b/group01/765324639/src/test/java/datastructure/queue/CircleQueueTest.java new file mode 100644 index 0000000000..3ee6ac6bbf --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/queue/CircleQueueTest.java @@ -0,0 +1,38 @@ +package datastructure.queue; + +import org.junit.Assert; +import org.junit.Test; + +public class CircleQueueTest { + + @Test + public void test() { + CircleQueue circleQueue = new CircleQueue<>(); + for (int i = 0; i < 10; i++) { + circleQueue.enQueue("circleQueue" + i); + } + Assert.assertEquals(10, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 0; i < 5; i++) { + Assert.assertEquals("circleQueue" + i, circleQueue.deQueue()); + } + Assert.assertEquals(5, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 5; i< 10; i++) { + Assert.assertEquals("circleQueue" + i, circleQueue.deQueue()); + } + Assert.assertEquals(0, circleQueue.size()); + Assert.assertTrue(circleQueue.isEmpty()); + + for (int i = 0; i < 6; i++) { + circleQueue.enQueue("item" + i); + } + Assert.assertEquals(6, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 0; i < 6; i++) { + Assert.assertEquals("item" + i, circleQueue.deQueue()); + } + Assert.assertEquals(0, circleQueue.size()); + Assert.assertTrue(circleQueue.isEmpty()); + } +} diff --git a/group01/765324639/src/test/java/datastructure/queue/JosephusTest.java b/group01/765324639/src/test/java/datastructure/queue/JosephusTest.java new file mode 100644 index 0000000000..bc079b54f2 --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/queue/JosephusTest.java @@ -0,0 +1,31 @@ +package datastructure.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[0, 1, 2, 3, 4, 5, 6]", Josephus.execute(7, 1).toString()); + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + Assert.assertEquals("[2, 5, 1, 6, 4, 0, 3]", Josephus.execute(7, 3).toString()); + Assert.assertEquals("[3, 0, 5, 4, 6, 2, 1]", Josephus.execute(7, 4).toString()); + Assert.assertEquals("[6, 0, 2, 5, 1, 3, 4]", Josephus.execute(7, 7).toString()); + + } + +} diff --git a/group01/765324639/src/test/java/datastructure/queue/QueueTest.java b/group01/765324639/src/test/java/datastructure/queue/QueueTest.java new file mode 100644 index 0000000000..ee9e169d8d --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/queue/QueueTest.java @@ -0,0 +1,49 @@ +package datastructure.queue; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import datastructure.queue.Queue; + +public class QueueTest { + + private Queue queue = new Queue(); + + @Before + public void setUp() { + for (int i = 0; i < 500; i++) { + queue.enQueue(i); + } + } + + @Test + public void testEnQueue() { + for (int i = 0; i < 100; i++) { + queue.enQueue(i); + } + Assert.assertEquals(600, queue.size()); + } + + @Test + public void testDeQueue() { + for (int i = 0; i < 500; i++) { + Assert.assertEquals(i, queue.deQueue()); + } + Assert.assertNull(queue.deQueue()); + Assert.assertNull(queue.deQueue()); + } + + @Test + public void testIsEmpty() { + Assert.assertFalse(queue.isEmpty()); + Queue q = new Queue(); + Assert.assertTrue(q.isEmpty()); + } + + @Test + public void testSize() { + Assert.assertEquals(500, queue.size()); + } + +} diff --git a/group01/765324639/src/test/java/datastructure/queue/QueueWithTwoStacksTest.java b/group01/765324639/src/test/java/datastructure/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..50024c010c --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,27 @@ +package datastructure.queue; + +import org.junit.Assert; +import org.junit.Test; + +public class QueueWithTwoStacksTest { + + @Test + public void test() { + QueueWithTwoStacks queue = new QueueWithTwoStacks<>(); + Assert.assertNull(queue.deQueue()); + Assert.assertTrue(queue.isEmpty()); + for (int i = 0; i < 100; i++) { + queue.enQueue("item" + i); + } + for (int i = 0; i < 50; i++) { + Assert.assertEquals("item" + i, queue.deQueue()); + } + queue.enQueue("item100"); + queue.enQueue("item101"); + Assert.assertEquals(52, queue.size()); + int i = 50; + while (!queue.isEmpty()) { + Assert.assertEquals("item" + i++, queue.deQueue()); + } + } +} diff --git a/group01/765324639/src/test/java/datastructure/stack/QuickMinStackTest.java b/group01/765324639/src/test/java/datastructure/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..852488a3c0 --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/QuickMinStackTest.java @@ -0,0 +1,42 @@ +package datastructure.stack; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class QuickMinStackTest { + + @Test + public void test() { + QuickMinStack stack = new QuickMinStack(); + stack.push(5); + stack.push(-5); + stack.push(50); + stack.push(23); + stack.push(0); + stack.push(100); + + assertEquals(-5, stack.findMin()); + assertEquals(6, stack.size()); + + assertEquals(5, stack.pop()); + assertEquals(-5, stack.findMin()); + + assertEquals(-5, stack.pop()); + assertEquals(0, stack.findMin()); + + assertEquals(50, stack.pop()); + assertEquals(0, stack.findMin()); + + assertEquals(23, stack.pop()); + assertEquals(0, stack.findMin()); + + assertEquals(0, stack.pop()); + assertEquals(100, stack.findMin()); + + assertEquals(100, stack.pop()); + + assertEquals(0, stack.size()); + + } +} diff --git a/group01/765324639/src/test/java/datastructure/stack/StackWithTwoQueuesTest.java b/group01/765324639/src/test/java/datastructure/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..cf2b3482ce --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,26 @@ +package datastructure.stack; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class StackWithTwoQueuesTest { + + @Test + public void test() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + for (int i = 0; i < 500; i++) { + stack.push(i); + } + for (int i = 0; i < 500; i++) { + assertEquals(500 - i - 1, stack.pop()); + } + + stack.push(50); + stack.push(60); + assertEquals(60, stack.pop()); + stack.push(70); + assertEquals(70, stack.pop()); + assertEquals(50, stack.pop()); + } +} diff --git a/group01/765324639/src/test/java/datastructure/stack/TwoStackInOneArrayTest.java b/group01/765324639/src/test/java/datastructure/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..2407f7ce15 --- /dev/null +++ b/group01/765324639/src/test/java/datastructure/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,42 @@ +package datastructure.stack; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class TwoStackInOneArrayTest { + + @Test + public void test() { + TwoStackInOneArray stack = new TwoStackInOneArray(); + for (int i = 0; i < 500; i++) { + stack.push1("stack1:" + i); + } + for (int i = 0; i < 500; i++) { + stack.push2("stack2:" + i); + } + + for (int i = 0; i < 500; i++) { + assertEquals("stack1:" + (500 - i - 1), stack.peek1()); + assertEquals("stack1:" + (500 - i - 1), stack.pop1()); + } + for (int i = 0; i < 500; i++) { + assertEquals("stack2:" + (500 - i - 1), stack.peek2()); + assertEquals("stack2:" + (500 - i - 1), stack.pop2()); + } + + stack.push1(50); + stack.push1(60); + assertEquals(60, stack.pop1()); + stack.push1(70); + assertEquals(70, stack.pop1()); + assertEquals(50, stack.pop1()); + + stack.push2(50); + stack.push2(60); + assertEquals(60, stack.pop2()); + stack.push2(70); + assertEquals(70, stack.pop2()); + assertEquals(50, stack.pop2()); + } +} diff --git a/group01/765324639/src/test/java/minijvm/loader/MiniJVMTest.java b/group01/765324639/src/test/java/minijvm/loader/MiniJVMTest.java new file mode 100644 index 0000000000..2811c90a53 --- /dev/null +++ b/group01/765324639/src/test/java/minijvm/loader/MiniJVMTest.java @@ -0,0 +1,30 @@ +package minijvm.loader; + +import java.io.File; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import minijvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = new File(".", "target\\test-classes").getAbsolutePath(); + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "minijvm.loader.EmployeeV1"); + + } + +} diff --git a/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java b/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java index 6614d0ec7d..3928b3ba08 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/PostfixExpr.java @@ -10,7 +10,7 @@ public class PostfixExpr { private String expr; private String splitRegex; private Stack stack = new Stack(); - + public PostfixExpr(String expr) { this.expr = expr; this.splitRegex = " "; diff --git a/group01/895457260/code/src/main/java/algorithm/expression/Token.java b/group01/895457260/code/src/main/java/algorithm/expression/Token.java index cb95b43f66..6391216505 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/Token.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/Token.java @@ -1,125 +1,133 @@ package algorithm.expression; class Token { - public static final String OP_ADD = "+"; - public static final String OP_SUB = "-"; - public static final String OP_MUL = "*"; - public static final String OP_DIV = "/"; - public static final String OP_L_BRACKET = "("; - public static final String OP_R_BRACKET = ")"; - public static final String OP_SCOPE = "#"; - - public static final int OPERATOR = 1; - public static final int NUMBER = 2; - - public static final Token ADD = new Token(OPERATOR, OP_ADD); - public static final Token SUB = new Token(OPERATOR, OP_SUB); - public static final Token MUL = new Token(OPERATOR, OP_MUL); - public static final Token DIV = new Token(OPERATOR, OP_DIV); - public static final Token L_BRACKET = new Token(OPERATOR, OP_L_BRACKET); - public static final Token R_BRACKET = new Token(OPERATOR, OP_R_BRACKET); - public static final Token SCOPE = new Token(OPERATOR, OP_SCOPE); - - //优先级表 - private static int[][] priorities = { - // + - * / ( ) # - {-1, -1, -1, -1, 1, -1, 1}, // + - {-1, -1, -1, -1, 1, -1, 1}, // - - { 1, 1, -1, -1, 1, -1, 1}, // * - { 1, 1, -1, -1, 1, -1, 1}, // / - { 1, 1, 1, 1, 1, -1, 1}, // ( - {-1, -1, -1, -1, -1, 0, 1}, // ) - {-1, -1, -1, -1, -1, -1, 0} // # - }; - - 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.valueOf(value); - } - - public String toString(){ - return value; - } - - private static int indexOf(String op) { - switch (op) { - case OP_ADD: - return 0; - case OP_SUB: - return 1; - case OP_MUL: - return 2; - case OP_DIV: - return 3; - case OP_L_BRACKET: - return 4; - case OP_R_BRACKET: - return 5; - case OP_SCOPE: - return 6; - } - return 0; - } - - public static int compare(Token op, Token peek) { - int opIndex = indexOf(op.toString()); - int peekIndex = indexOf(peek.toString()); - return priorities[opIndex][peekIndex]; - } - - public static Token calculate(Token num1, Token op, Token num2) { - float result = 0.0f; - float n1 = num1.getFloatValue(); - float n2 = num2.getFloatValue(); - switch (op.toString()) { - case "+": - result = n1 + n2; + public static final String OP_ADD = "+"; + public static final String OP_SUB = "-"; + public static final String OP_MUL = "*"; + public static final String OP_DIV = "/"; + public static final String OP_POWER= "^"; + public static final String OP_L_BRACKET = "("; + public static final String OP_R_BRACKET = ")"; + public static final String OP_SCOPE = "#"; + + public static final int OPERATOR = 1; + public static final int NUMBER = 2; + + public static final Token ADD = new Token(OPERATOR, OP_ADD); + public static final Token SUB = new Token(OPERATOR, OP_SUB); + public static final Token MUL = new Token(OPERATOR, OP_MUL); + public static final Token DIV = new Token(OPERATOR, OP_DIV); + public static final Token POWER = new Token(OPERATOR, OP_DIV); + public static final Token L_BRACKET = new Token(OPERATOR, OP_L_BRACKET); + public static final Token R_BRACKET = new Token(OPERATOR, OP_R_BRACKET); + public static final Token SCOPE = new Token(OPERATOR, OP_SCOPE); + + //优先级表 + private static int[][] priorities = { + //+ - * / ^ ( ) # + {-1, -1, -1, -1, -1, 1, -1, 1}, // + + {-1, -1, -1, -1, -1, 1, -1, 1}, // - + { 1, 1, -1, -1, -1, 1, -1, 1}, // * + { 1, 1, -1, -1, -1, 1, -1, 1}, // / + { 1, 1, 1, 1, -1, 1, -1, 1}, // ^ + { 1, 1, 1, 1, 1, 1, -1, 1}, // ( + {-1, -1, -1, -1, -1, -1, 0, 1}, // ) + {-1, -1, -1, -1, -1, -1, -1, 0} // # + }; + + 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.valueOf(value); + } + + public String toString(){ + return value; + } + + private static int indexOf(String op) { + switch (op) { + case OP_ADD: + return 0; + case OP_SUB: + return 1; + case OP_MUL: + return 2; + case OP_DIV: + return 3; + case OP_POWER: + return 4; + case OP_L_BRACKET: + return 5; + case OP_R_BRACKET: + return 6; + case OP_SCOPE: + return 7; + } + return 0; + } + + public static int compare(Token op, Token peek) { + int opIndex = indexOf(op.toString()); + int peekIndex = indexOf(peek.toString()); + return priorities[opIndex][peekIndex]; + } + + public static Token calculate(Token num1, Token op, Token num2) { + float result = 0.0f; + float n1 = num1.getFloatValue(); + float n2 = num2.getFloatValue(); + switch (op.toString()) { + case OP_ADD: + result = n1 + n2; + break; + case OP_SUB: + result = n1 - n2; + break; + case OP_MUL: + result = n1 * n2; + break; + case OP_DIV: + if (n2 == 0) { + throw new RuntimeException("Divide by 0"); + } + result = n1 / n2; + break; + case OP_POWER: + result = (float) Math.pow(n1, n2); break; - case "-": - result = n1 - n2; - break; - case "*": - result = n1 * n2; - break; - case "/": - if (n2 == 0) { - throw new RuntimeException("Divide by 0"); - } - result = n1 / n2; - break; - } - return new Token(NUMBER, result + ""); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Token token = (Token) o; - - return type == token.type && (value != null ? value.equals(token.value) : token.value == null); - } - - @Override - public int hashCode() { - int result = value != null ? value.hashCode() : 0; - result = 31 * result + type; - return result; - } + } + return new Token(NUMBER, result + ""); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Token token = (Token) o; + + return type == token.type && (value != null ? value.equals(token.value) : token.value == null); + } + + @Override + public int hashCode() { + int result = value != null ? value.hashCode() : 0; + result = 31 * result + type; + return result; + } } \ No newline at end of file diff --git a/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java index ca8619c94b..ec083b10f1 100644 --- a/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java +++ b/group01/895457260/code/src/main/java/algorithm/expression/TokenParser.java @@ -7,7 +7,7 @@ public class TokenParser { public static final List OPERATORS = Arrays.asList(Token.OP_ADD, Token.OP_SUB, Token.OP_MUL, - Token.OP_DIV, Token.OP_L_BRACKET, Token.OP_R_BRACKET); + Token.OP_DIV, Token.OP_POWER, Token.OP_L_BRACKET, Token.OP_R_BRACKET); public static List parse(String expression) { return parse(expression, null); diff --git a/group01/895457260/code/src/main/java/algorithm/queue/CircleQueue.java b/group01/895457260/code/src/main/java/algorithm/queue/CircleQueue.java new file mode 100644 index 0000000000..e44d187bc7 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/queue/CircleQueue.java @@ -0,0 +1,75 @@ +package algorithm.queue; + +import datastructure.exception.EmptyQueueException; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + private final static int DEFAULT_SIZE = 10; + + //数组实现自增长的循环队列 + private Object[] array = new Object[DEFAULT_SIZE]; + private int head = 0; + private int rear = 0; + + public CircleQueue() {} + + public CircleQueue(int initCapacity) { + this.array = new Object[initCapacity]; + } + + public void enQueue(E o) { + int target = mapIndex(rear); + autoGrow(); + array[target] = o; + rear++; + } + + public E deQueue() { + if (isEmpty()) { + throw new EmptyQueueException(); + } + Object obj = array[mapIndex(head)]; + head++; + @SuppressWarnings("unchecked") E e = (E) obj; + return e; + } + + public boolean isEmpty() { + return head == rear; + } + + public int size() { + return rear - head; + } + + private int capacity() { + return array.length; + } + + private void autoGrow() { + if (size() >= capacity()) { + Object[] newArray = new Object[nextCapacity()]; + System.arraycopy(array, 0, newArray, 0, capacity()); + + int increase = nextCapacity() - capacity(); + int moveCount = size() - mapIndex(rear); + System.arraycopy(newArray, mapIndex(head), newArray, mapIndex(head) + increase, moveCount); + array = newArray; + head += increase; + rear += increase; + } + } + + private int nextCapacity() { + return capacity() * 2; + } + + private int mapIndex(int index) { + return index % capacity(); + } +} diff --git a/group01/895457260/code/src/main/java/algorithm/queue/Josephus.java b/group01/895457260/code/src/main/java/algorithm/queue/Josephus.java new file mode 100644 index 0000000000..979823bcd0 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/queue/Josephus.java @@ -0,0 +1,31 @@ +package algorithm.queue; + +import java.util.ArrayList; +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 queue = new CircleQueue<>(); + for (int i = 0; i < n; ++i) { + queue.enQueue(i); + } + + List result = new ArrayList<>(); + while (!queue.isEmpty()) { + for (int i = 0; i < m - 1; ++i) { + queue.enQueue(queue.deQueue()); + } + result.add(queue.deQueue()); + } + return result; + } + +} diff --git a/group01/895457260/code/src/main/java/algorithm/queue/Queue.java b/group01/895457260/code/src/main/java/algorithm/queue/Queue.java new file mode 100644 index 0000000000..3fb735a3a7 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/queue/Queue.java @@ -0,0 +1,55 @@ +package algorithm.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group01/895457260/code/src/main/java/algorithm/queue/QueueWithTwoStacks.java b/group01/895457260/code/src/main/java/algorithm/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..78a198f903 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/queue/QueueWithTwoStacks.java @@ -0,0 +1,52 @@ +package algorithm.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * + * @param + * @author liuxin + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack<>(); + stack2 = new Stack<>(); + } + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + public int size() { + return Math.max(stack1.size(), stack2.size()); + } + + public void enQueue(E item) { + int size = stack2.size(); + while (!stack2.isEmpty()) { + stack1.push(stack2.pop()); + } + stack2.push(item); + for (int i = 0; i < size; ++i) { + stack2.push(stack1.pop()); + } + stack1.push(item); + } + + public E deQueue() { + E e = stack2.pop(); + int size = stack2.size(); + for (int i = 0; i < size; ++i) { + stack2.push(stack1.pop()); + } + stack1.pop(); + for (int i = 0; i < size; ++i) { + stack1.push(stack2.pop()); + } + return e; + } +} diff --git a/group01/895457260/code/src/main/java/algorithm/stack/QuickMinStack.java b/group01/895457260/code/src/main/java/algorithm/stack/QuickMinStack.java new file mode 100644 index 0000000000..2340f36c7f --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/stack/QuickMinStack.java @@ -0,0 +1,48 @@ +package algorithm.stack; + +import datastructure.basic.Iterator; +import datastructure.basic.LinkedList; + +import java.util.EmptyStackException; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * + * @author liuxin + */ +public class QuickMinStack { + private LinkedList elements = new LinkedList(); + private LinkedList sorted = new LinkedList(); + + public void push(int data) { + elements.addFirst(data); + insert(sorted, data); + } + + private void insert(LinkedList sorted, int data) { + Iterator iterator = sorted.iterator(); + + int insertPos = 0; + while (iterator.hasNext()) { + if ((int) iterator.next() >= data) { + break; + } + insertPos++; + } + sorted.add(insertPos, data); + } + + public int pop() { + if (elements.isEmpty()) { + throw new EmptyStackException(); + } + int peek = (int) elements.removeFirst(); + sorted.remove(sorted.indexOf(peek)); + return peek; + } + + public int findMin() { + return (int) sorted.get(0); + } +} diff --git a/group01/895457260/code/src/main/java/algorithm/stack/StackWithTwoQueues.java b/group01/895457260/code/src/main/java/algorithm/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..a069f3c87f --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/stack/StackWithTwoQueues.java @@ -0,0 +1,21 @@ +package algorithm.stack; + + +import datastructure.basic.Queue; + +public class StackWithTwoQueues { + + private Queue queue1 = new Queue(); + private Queue queue2 = new Queue(); + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + for (int i = 0; i < queue1.size() - 1; ++i) { + queue1.enQueue(queue1.deQueue()); + } + return (int) queue1.deQueue(); + } +} diff --git a/group01/895457260/code/src/main/java/algorithm/stack/TwoStackInOneArray.java b/group01/895457260/code/src/main/java/algorithm/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..099d2b424d --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/stack/TwoStackInOneArray.java @@ -0,0 +1,114 @@ +package algorithm.stack; + +import java.util.Arrays; +import java.util.EmptyStackException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + * @author liuxin + */ +public class TwoStackInOneArray { + private Object[] data = new Object[10]; + + private int top1 = 0; + private int top2 = data.length - 1; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + ensureCapacity(); + data[top1++] = o; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if (top1 <= 0) { + throw new EmptyStackException(); + } + return data[--top1]; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + public Object peek1() { + if (top1 <= 0) { + throw new EmptyStackException(); + } + return data[top1 - 1]; + } + + public int size1() { + return top1 - 1; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + ensureCapacity(); + data[top2--] = o; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (top2 >= data.length - 1) { + throw new EmptyStackException(); + } + return data[++top2]; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + public Object peek2() { + if (top2 >= data.length - 1) { + throw new EmptyStackException(); + } + return data[top2 + 1]; + } + + public int size2() { + return data.length - top2 - 1; + } + + private void ensureCapacity() { + if (top1 > top2) { + int nextCapacity = nextCapacity(data.length); + Object[] newArray = new Object[nextCapacity]; + + System.arraycopy(data, 0, newArray, 0, size1()); + + int size2 = size2(); + int srcPos = data.length - size2; + int destPos = nextCapacity - size2; + System.arraycopy(data, srcPos, newArray, destPos, size2); + top2 = destPos - 1; + + Arrays.fill(data, null); + data = newArray; + } + } + + private int nextCapacity(int currentCapacity) { + return currentCapacity * 2; + } + +} diff --git a/group01/895457260/code/src/main/java/datastructure/basic/ArrayList.java b/group01/895457260/code/src/main/java/datastructure/basic/ArrayList.java index 82c6ac6b1c..badc19af2d 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/ArrayList.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/ArrayList.java @@ -40,10 +40,25 @@ public Object remove(int index) { return removed; } - public int size() { + @Override + public int indexOf(Object o) { + for (int i = 0; i < size(); ++i) { + if (elementData[i] == null ? o == null : elementData[i].equals(o)) { + return i; + } + } + return -1; + } + + public int size() { return size; } + @Override + public boolean isEmpty() { + return size() == 0; + } + public Iterator iterator() { return new Iterator() { int index = -1; diff --git a/group01/895457260/code/src/main/java/datastructure/basic/LinkedList.java b/group01/895457260/code/src/main/java/datastructure/basic/LinkedList.java index 5dfa11fcb4..6510bd9d38 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/LinkedList.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/LinkedList.java @@ -5,107 +5,124 @@ import java.util.Objects; public class LinkedList implements List { - - private Node head; - private int size; - public LinkedList() { - head = new Node(); + private Node head; + private int size; + + public LinkedList() { + head = new Node(); } @Override - public void add(Object o) { + public void add(Object o) { addLast(o); - } - - @Override - public void add(int index , Object o) { - Node pre = findNode(index - 1); - Node node = new Node(); - node.data = o; - addNode(node, pre); - } - - @Override - public Object get(int index) { - checkIndex(index); - return findNode(index).data; - } - - @Override - public Object remove(int index) { - checkIndex(index); - Node pre = findNode(index - 1); - Node removed = pre.next; - removeNode(removed, pre); - return removed.data; - } - - @Override - public int size() { - return size; - } - - public void addFirst(Object o) { - Node node = new Node(); - node.data = o; - addNode(node, head); - } - - public void addLast(Object o) { + } + + @Override + public void add(int index, Object o) { + Node pre = findNode(index - 1); + Node node = new Node(); + node.data = o; + addNode(node, pre); + } + + @Override + public Object get(int index) { + checkIndex(index); + return findNode(index).data; + } + + @Override + public Object remove(int index) { + checkIndex(index); + Node pre = findNode(index - 1); + Node removed = pre.next; + removeNode(removed, pre); + return removed.data; + } + + @Override + public int indexOf(Object o) { + int i = 0; + for (Node node = head.next; node != null; node = node.next, ++i) { + if (node.data == null ? o == null : node.data.equals(o)) { + return i; + } + } + return -1; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + public void addFirst(Object o) { + Node node = new Node(); + node.data = o; + addNode(node, head); + } + + public void addLast(Object o) { Node node = new Node(); node.data = o; Node pre = findNode(size() - 1); addNode(node, pre); - } - - public Object removeFirst() { - if (size() == 0) { - throw new EmptyListException(); - } - Node removed = head.next; - removeNode(head.next, head); - return removed.data; - } - - public Object removeLast() { - if (size() == 0) { - throw new EmptyListException(); - } - return remove(size() - 1); - } - - @Override - public Iterator iterator() { - return new Iterator() { - Node node = head; - @Override - public boolean hasNext() { - return node.next != null; - } - - @Override - public Object next() { - node = node.next; - return node.data; - } - }; - } - - private static class Node{ - Object data; - Node next; - } - - private Node findNode(int index) { - if (index == -1) { - return head; + } + + public Object removeFirst() { + if (size() == 0) { + throw new EmptyListException(); + } + Node removed = head.next; + removeNode(head.next, head); + return removed.data; + } + + public Object removeLast() { + if (size() == 0) { + throw new EmptyListException(); + } + return remove(size() - 1); + } + + @Override + public Iterator iterator() { + return new Iterator() { + Node node = head; + + @Override + public boolean hasNext() { + return node.next != null; + } + + @Override + public Object next() { + node = node.next; + return node.data; + } + }; + } + + private static class Node { + Object data; + Node next; + } + + private Node findNode(int index) { + if (index == -1) { + return head; } else { - checkIndex(index); + checkIndex(index); } Node node = head.next; for (int i = 0; i < index; ++i) { - node = node.next; + node = node.next; } return node; } @@ -121,197 +138,201 @@ private String indexOutOfBoundMessage(int index) { } private void addNode(Node node, Node pre) { - node.next = pre.next; - pre.next = node; - size++; + node.next = pre.next; + pre.next = node; + size++; } private void removeNode(Node node, Node pre) { - pre.next = node.next; - node.next = null; - size--; + pre.next = node.next; + node.next = null; + size--; + } + + //清空整条链,返回链中结点数量 + private int clearLink(Node start) { + int count = 0; + while (start != null) { + Node node = start; + start = start.next; + node.data = null; + node.next = null; + count++; + } + return count; + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Stack stack = new Stack(); + for (Node node = head.next; node != null; node = node.next) { + stack.push(node); + } + head.next = (Node) stack.peek(); + while (stack.size() > 1) { + Node top = (Node) stack.pop(); + top.next = (Node) stack.peek(); + } + ((Node) stack.peek()).next = null; } - //清空整条链,返回链中结点数量 - private int clearLink(Node start) { - int count = 0; - while (start != null) { - Node node = start; - start = start.next; - node.data = null; - node.next = null; - count++; - } - return count; - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - Stack stack = new Stack(); - for (Node node = head.next; node != null; node = node.next) { - stack.push(node); - } - head.next = (Node) stack.peek(); - while (stack.size() > 1) { - Node top = (Node) stack.pop(); - top.next = (Node) stack.peek(); - } - ((Node) stack.peek()).next = null; - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - int half = size() / 2; - if (half > 1) { - Node first = head.next; - - Node preHalf = findNode(half - 1); - head.next = preHalf.next; - preHalf.next = null; - size -= clearLink(first); - } - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * @param i - * @param length - */ - public void remove(int i, int length) { - if (length <= 0) { - return; - } - Node preI = findNode(i - 1); - Node removeTo = findNode(i + length - 1); - Node removeFrom = preI.next; - preI.next = removeTo.next; - removeTo.next = null; - size -= clearLink(removeFrom); - } - /** - * 假定当前链表和list均包含已升序排列的整数 - * 从当前链表中取出那些list所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public Object[] getElements(LinkedList list){ - Object[] result = new Object[list.size()]; - int count = 0; - - Node nodeI = head.next; - Node nodeJ = list.head.next; - for (int i = 0; nodeI != null && nodeJ != null; ++i) { - int compare = i - (int) nodeJ.data; - if (compare == 0) { - result[count] = nodeI.data; - count++; - nodeI = nodeI.next; - nodeJ = nodeJ.next; - } else if (compare < 0) { - nodeI = nodeI.next; - } else { - nodeJ = nodeJ.next; - i--; - } - } - Object[] trueResult = new Object[count]; - System.arraycopy(result, 0, trueResult, 0, count); - return trueResult; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在list中出现的元素 - - * @param list - */ - - public void subtract(LinkedList list){ - Node pre = head; - Node node = list.head.next; - while (pre.next != null && node != null) { - if ((int) pre.next.data < (int) node.data) { - pre = pre.next; - } else if ((int) pre.next.data > (int) node.data) { - node = node.next; - } else { - removeNode(pre.next, pre); - } - } - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - Node node = head; - while (node.next != null) { - if (Objects.equals(node.data, node.next.data)) { - removeNode(node.next, node); - } else { - node = node.next; - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max){ - Node node = head; - while (node.next != null) { - int value = (int) node.next.data; - if (value <= min) { // 还未进入范围 - node = node.next; - } else if (value >= max) { // 超出范围,停止遍历 - break; - } else { // 在范围内,删除之 - removeNode(node.next, node); - } - } - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList intersection(LinkedList list){ - LinkedList result = new LinkedList(); - Node inThis = head.next; - Node node = list.head.next; - int[] temp = new int[Math.min(size(), list.size())]; - int count = 0; - while (inThis != null && node != null) { - int compare = (int) inThis.data - (int) node.data; - if (compare < 0) { - inThis = inThis.next; - } else if (compare > 0) { - node = node.next; - } else { - temp[count] = (int) node.data; - count++; - inThis = inThis.next; - node = node.next; - } - } - for (int i = count - 1; i >= 0; --i) { - result.addFirst(temp[i]); - } - return result; - } + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int half = size() / 2; + if (half > 1) { + Node first = head.next; + + Node preHalf = findNode(half - 1); + head.next = preHalf.next; + preHalf.next = null; + size -= clearLink(first); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (length <= 0) { + return; + } + Node preI = findNode(i - 1); + Node removeTo = findNode(i + length - 1); + Node removeFrom = preI.next; + preI.next = removeTo.next; + removeTo.next = null; + size -= clearLink(removeFrom); + } + + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + */ + public Object[] getElements(LinkedList list) { + Object[] result = new Object[list.size()]; + int count = 0; + + Node nodeI = head.next; + Node nodeJ = list.head.next; + for (int i = 0; nodeI != null && nodeJ != null; ++i) { + int compare = i - (int) nodeJ.data; + if (compare == 0) { + result[count] = nodeI.data; + count++; + nodeI = nodeI.next; + nodeJ = nodeJ.next; + } else if (compare < 0) { + nodeI = nodeI.next; + } else { + nodeJ = nodeJ.next; + i--; + } + } + Object[] trueResult = new Object[count]; + System.arraycopy(result, 0, trueResult, 0, count); + return trueResult; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + Node pre = head; + Node node = list.head.next; + while (pre.next != null && node != null) { + if ((int) pre.next.data < (int) node.data) { + pre = pre.next; + } else if ((int) pre.next.data > (int) node.data) { + node = node.next; + } else { + removeNode(pre.next, pre); + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + Node node = head; + while (node.next != null) { + if (Objects.equals(node.data, node.next.data)) { + removeNode(node.next, node); + } else { + node = node.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + Node node = head; + while (node.next != null) { + int value = (int) node.next.data; + if (value <= min) { // 还未进入范围 + node = node.next; + } else if (value >= max) { // 超出范围,停止遍历 + break; + } else { // 在范围内,删除之 + removeNode(node.next, node); + } + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList result = new LinkedList(); + Node inThis = head.next; + Node node = list.head.next; + int[] temp = new int[Math.min(size(), list.size())]; + int count = 0; + while (inThis != null && node != null) { + int compare = (int) inThis.data - (int) node.data; + if (compare < 0) { + inThis = inThis.next; + } else if (compare > 0) { + node = node.next; + } else { + temp[count] = (int) node.data; + count++; + inThis = inThis.next; + node = node.next; + } + } + for (int i = count - 1; i >= 0; --i) { + result.addFirst(temp[i]); + } + return result; + } } diff --git a/group01/895457260/code/src/main/java/datastructure/basic/List.java b/group01/895457260/code/src/main/java/datastructure/basic/List.java index 2f085701c5..a586c93982 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/List.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/List.java @@ -1,10 +1,19 @@ package datastructure.basic; public interface List { - void add(Object o); - void add(int index, Object o); - Object get(int index); - Object remove(int index); - int size(); - Iterator iterator(); + void add(Object o); + + void add(int index, Object o); + + Object get(int index); + + Object remove(int index); + + int indexOf(Object o); + + int size(); + + boolean isEmpty(); + + Iterator iterator(); } diff --git a/group01/895457260/code/src/main/java/datastructure/basic/Queue.java b/group01/895457260/code/src/main/java/datastructure/basic/Queue.java index edd0a6a29e..c46f47461f 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/Queue.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/Queue.java @@ -3,66 +3,24 @@ import datastructure.exception.EmptyQueueException; public class Queue { - //数组实现自增长的循环队列 - private Object[] array; - private int head = 0; - private int rear = 0; - - public Queue() { - this.array = new Object[10]; - } - - public Queue(int initCapacity) { - this.array = new Object[initCapacity]; - } + private LinkedList list = new LinkedList(); public void enQueue(Object o) { - int target = mapIndex(rear); - autoGrow(); - array[target] = o; - rear++; + list.addLast(o); } - + public Object deQueue() { if (isEmpty()) { throw new EmptyQueueException(); } - Object obj = array[mapIndex(head)]; - head++; - return obj; + return list.removeFirst(); } public boolean isEmpty() { - return head == rear; - } - - public int size() { - return rear - head; - } - - private int capacity() { - return array.length; + return list.isEmpty(); } - private void autoGrow() { - if (size() >= capacity()) { - Object[] newArray = new Object[nextCapacity()]; - System.arraycopy(array, 0, newArray, 0, capacity()); - - int increase = nextCapacity() - capacity(); - int moveCount = size() - mapIndex(rear); - System.arraycopy(newArray, mapIndex(head), newArray, mapIndex(head) + increase, moveCount); - array = newArray; - head += increase; - rear += increase; - } - } - - private int nextCapacity() { - return capacity() * 2; - } - - private int mapIndex(int index) { - return index >= capacity() ? index % capacity() : index; + public int size() { + return list.size(); } } diff --git a/group01/895457260/code/src/main/java/datastructure/basic/Stack.java b/group01/895457260/code/src/main/java/datastructure/basic/Stack.java index eeb9c7afba..985d6bbf42 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/Stack.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/Stack.java @@ -23,7 +23,7 @@ public Object peek() { } public boolean isEmpty() { - return size() == 0; + return elementData.isEmpty(); } public int size() { diff --git a/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java b/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java index ade626ad83..943b5b43ef 100644 --- a/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java +++ b/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java @@ -43,15 +43,14 @@ public byte[] readBinaryCode(String className) throws ReadClassException { private File getClassFile(String className) throws ClassDuplicateException { int split = className.lastIndexOf('.'); + if (split == -1) { + split = className.lastIndexOf('/'); + } String fileName = className.substring(split + 1) + ".class"; - String subPath = className.substring(0, split).replaceAll("[.]", "/"); + List files = new ArrayList<>(); for (String path : classPaths) { - File dir = new File(path + '/' + subPath); - File[] listFile = dir.listFiles((dir1, name) -> name.equals(fileName)); - if (listFile != null) { - Arrays.stream(listFile).forEach(files::add); - } + files.addAll(getFiles(new File(path), fileName)); } if (files.size() > 1) { throw new ClassDuplicateException(); @@ -59,6 +58,23 @@ private File getClassFile(String className) throws ClassDuplicateException { return files.size() == 1 ? files.get(0) : null; } + private List getFiles(File path, String fileName) { + List files = new ArrayList<>(); + File[] listFile = path.listFiles(); + if (listFile == null) { + return files; + } + + for (File f : listFile) { + if (f.isDirectory()) { + files.addAll(getFiles(f, fileName)); + } else if (f.getName().equals(fileName)) { + files.add(f); + } + } + return files; + } + public void addClassPath(String path) { if (path != null && !"".equals(path)) { classPaths.add(path); diff --git a/group01/895457260/code/src/main/java/jvm/LiteJvm.java b/group01/895457260/code/src/main/java/jvm/LiteJvm.java deleted file mode 100644 index d642654d5f..0000000000 --- a/group01/895457260/code/src/main/java/jvm/LiteJvm.java +++ /dev/null @@ -1,25 +0,0 @@ -package jvm; - -import jvm.exception.MagicNumberException; -import jvm.exception.ReadClassException; - -/** - * Created by Haochen on 2017/3/26. - * TODO: - */ -public enum LiteJvm { - INSTANCE; - - private ClassFileLoader classFileLoader = new ClassFileLoader(); - - public void launch(String className) throws MagicNumberException, ReadClassException { - byte[] bytes = getBytes(className); - if (!classFileLoader.checkMagicNumber(bytes)) { - throw new MagicNumberException(); - } - } - - private byte[] getBytes(String className) throws ReadClassException { - return classFileLoader.readBinaryCode(className); - } -} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java b/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java index 18c327fb0d..6b2e98201a 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java @@ -21,10 +21,19 @@ public void setFlagValue(int flag) { this.flagValue = flag; } - public boolean isPublicClass(){ + public boolean isPublic(){ return (this.flagValue & 0x0001) != 0; } - public boolean isFinalClass(){ + public boolean isPrivate(){ + return (this.flagValue & 0x0002) != 0; + } + public boolean isProtected(){ + return (this.flagValue & 0x0004) != 0; + } + public boolean isStatic(){ + return (this.flagValue & 0x0008) != 0; + } + public boolean isFinal(){ return (this.flagValue & 0x0010) != 0; } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java index 377b198035..a3317974b9 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java @@ -4,9 +4,10 @@ import jvm.classfile.constant.item.impl.ClassInfo; import jvm.classfile.field.Field; import jvm.classfile.method.Method; +import jvm.engine.JavaObject; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * Created by Haochen on 2017/4/9. @@ -23,6 +24,8 @@ public class ClassFile { List methods = new ArrayList<>(); List attributes = new ArrayList<>(); + Map staticFieldValues = new HashMap<>(); + public AccessFlag getAccessFlag() { return accessFlag; @@ -41,7 +44,7 @@ public List getAttributes() { } public void print() { - if(this.accessFlag.isPublicClass()){ + if(this.accessFlag.isPublic()){ System.out.println("Access flag : public "); } System.out.println("Class Name:"+ getClassName()); @@ -85,4 +88,33 @@ public Method getMethod(String methodName, String paramAndReturnType) { public Method getMainMethod() { return getMethod("main", "([Ljava/lang/String;)V"); } + + public Field getField(String name) { + return fields.stream() + .filter(f -> f.getName().equals(name)) + .findFirst() + .orElse(null); + } + + public JavaObject getStaticFieldValue(String name) { + return staticFieldValues.get(name); + } + + public void putStaticFieldValue(String name, JavaObject object) { + java.lang.reflect.Field field; + try { + Class clazz = Class.forName(this.getClassName().replace('/', '.')); + field = clazz.getDeclaredField(name); + field.setAccessible(true); + if (object == null) { + staticFieldValues.remove(name); + field.set(null, null); + } else { + staticFieldValues.put(name, object); + field.set(null, object); + } + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("Static field " + getClassName() + "." + name + "not found"); + } + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java index 398bbaa4f2..e46b25dce6 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java @@ -10,6 +10,7 @@ import jvm.classfile.field.Field; import jvm.classfile.method.Method; import jvm.util.ByteCodeIterator; +import jvm.util.TypeUtils; /** * Created by Haochen on 2017/4/9. @@ -27,11 +28,11 @@ public static ClassFile parse(byte[] bytes) { classFile.constantPool = parseConstantPool(iterator); classFile.accessFlag = parseAccessFlag(iterator); classFile.classIndex = parseClassIndex(iterator); + linkConstantReferences(classFile); parseInterfaces(classFile, iterator); parseFields(classFile, iterator); parseMethods(classFile, iterator); parseAttributes(classFile, iterator); - linkConstantReferences(classFile); return classFile; } @@ -91,7 +92,11 @@ private static void parseInterfaces(ClassFile classFile, ByteCodeIterator iterat private static void parseFields(ClassFile classFile, ByteCodeIterator iterator) { int count = iterator.nextU2ToInt(); for (int i = 0; i < count; ++i) { - classFile.fields.add(Field.parse(iterator, classFile.constantPool)); + Field field = Field.parse(iterator, classFile.constantPool); + classFile.fields.add(field); + if (field.getAccessFlag().isStatic()) { + classFile.putStaticFieldValue(field.getName(), TypeUtils.getDefaultValue(field)); + } } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SignatureAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SignatureAttr.java new file mode 100644 index 0000000000..aa0a01938e --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SignatureAttr.java @@ -0,0 +1,16 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +/** + * Created by Haochen on 2017/4/30. + * TODO: + */ +public class SignatureAttr extends AttributeInfo { + private int signatureIndex; + + public SignatureAttr(int attrNameIndex, int attrLen, int signatureIndex) { + super(attrNameIndex, attrLen); + this.signatureIndex = signatureIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SignatureParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SignatureParser.java new file mode 100644 index 0000000000..74a6c67211 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SignatureParser.java @@ -0,0 +1,19 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.ConstantPool; +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.SignatureAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/30. + * TODO: + */ +public class SignatureParser implements AttributeInfoParser { + @Override + public AttributeInfo parse(int attrNameIndex, int attrLen, ByteCodeIterator iterator, ConstantPool constantPool) { + int signatureIndex = iterator.nextU2ToInt(); + return new SignatureAttr(attrNameIndex, attrLen, signatureIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/StackMapTableParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/StackMapTableParser.java index 087edcffcf..5405d7a2ab 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/StackMapTableParser.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/StackMapTableParser.java @@ -14,12 +14,9 @@ public class StackMapTableParser implements AttributeInfoParser { @Override public AttributeInfo parse(int attrNameIndex, int attrLen, ByteCodeIterator iterator, ConstantPool constantPool) { - int index = iterator.nextU2ToInt(); - int len = iterator.nextU4ToInt(); //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 - String code = iterator.nextHexString(len); - - return new StackMapTableAttr(index, len, code); + String code = iterator.nextHexString(attrLen); + return new StackMapTableAttr(attrNameIndex, attrLen, code); } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java index 9bb866713b..5ede5965f0 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java @@ -49,4 +49,12 @@ public void linkReference(ConstantPool constantPool) { className = ((ClassInfo) constantPool.getConstantInfo(classIndex)).getClassName(); nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); } + + public String getClassName() { + return className; + } + + public String getNameAndType() { + return nameAndType; + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java index a24ea332be..d4cc1763cc 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java @@ -34,4 +34,8 @@ public Map printableMap() { public byte[] getBytes() { return bytes; } + + public float getValue() { + return ByteUtils.toFloat(bytes); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java index b929c36a97..d74352bdb3 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java @@ -34,4 +34,8 @@ public Map printableMap() { public byte[] getBytes() { return bytes; } + + public int getValue() { + return ByteUtils.toUnsignedInt(getBytes()); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java index 9af83bca59..3332040c33 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java @@ -49,4 +49,16 @@ public void linkReference(ConstantPool constantPool) { className = ((ClassInfo) constantPool.getConstantInfo(classIndex)).getClassName(); nameAndType = ((NameAndTypeInfo) constantPool.getConstantInfo(nameAndTypeIndex)).getNameAndType(); } + + public String getClassName() { + return className; + } + + public String getName() { + return nameAndType.substring(0, nameAndType.indexOf(':')); + } + + public String getParamAndReturnType() { + return nameAndType.substring(nameAndType.indexOf(':') + 1); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/field/Field.java b/group01/895457260/code/src/main/java/jvm/classfile/field/Field.java index dcf6975543..1505533cb5 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/field/Field.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/field/Field.java @@ -1,5 +1,6 @@ package jvm.classfile.field; +import jvm.classfile.AccessFlag; import jvm.classfile.attribute.item.AttributeInfo; import jvm.classfile.attribute.parser.AttributeParser; import jvm.classfile.ConstantPool; @@ -10,14 +11,14 @@ import java.util.List; public class Field { - private int accessFlag; + private AccessFlag accessFlag; private int nameIndex; private int descriptorIndex; private ConstantPool constantPool; private List attributes = new ArrayList<>(); public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { - this.accessFlag = accessFlag; + this.accessFlag = new AccessFlag(accessFlag); this.nameIndex = nameIndex; this.descriptorIndex = descriptorIndex; this.constantPool = constantPool; @@ -38,12 +39,10 @@ public static Field parse(ByteCodeIterator iterator, ConstantPool constantPool) @Override public String toString() { - String name = ((UTF8Info) constantPool.getConstantInfo(nameIndex)).getValue(); - String desc = ((UTF8Info) constantPool.getConstantInfo(descriptorIndex)).getValue(); - return name + ":" + desc; + return getName() + ":" + getDescriptor(); } - public int getAccessFlag() { + public AccessFlag getAccessFlag() { return accessFlag; } @@ -62,4 +61,12 @@ public ConstantPool getConstantPool() { public List getAttributes() { return attributes; } + + public String getName() { + return ((UTF8Info) constantPool.getConstantInfo(nameIndex)).getValue(); + } + + public String getDescriptor() { + return ((UTF8Info) constantPool.getConstantInfo(descriptorIndex)).getValue(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java b/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java index 916a4aa32b..4336fca184 100644 --- a/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java +++ b/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java @@ -1,5 +1,6 @@ package jvm.classfile.method; +import jvm.classfile.AccessFlag; import jvm.classfile.ClassFile; import jvm.classfile.attribute.item.AttributeInfo; import jvm.classfile.attribute.item.impl.CodeAttr; @@ -9,71 +10,97 @@ import jvm.command.CommandParser; import jvm.command.item.ByteCodeCommand; import jvm.util.ByteCodeIterator; +import jvm.util.TypeUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class Method { - private int accessFlag; - private int nameIndex; - private int descriptorIndex; - private ConstantPool constantPool; - private List attributes = new ArrayList<>(); - private ByteCodeCommand[] commands; - - public Method(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { - this.accessFlag = accessFlag; - this.nameIndex = nameIndex; - this.descriptorIndex = descriptorIndex; - this.constantPool = constantPool; - } - - public static Method parse(ByteCodeIterator iterator, ClassFile classFile) { - int access = iterator.nextU2ToInt(); - int name = iterator.nextU2ToInt(); - int descriptor = iterator.nextU2ToInt(); - int attrCount = iterator.nextU2ToInt(); - Method result = new Method(access, name, descriptor, classFile.getConstantPool()); - for (int i = 0; i < attrCount; ++i) { - result.attributes.add(AttributeParser.parse(iterator, classFile.getConstantPool())); - } - CodeAttr codeAttr = (CodeAttr) result.attributes.stream() - .filter(a -> a instanceof CodeAttr).findFirst().orElse(null); - if (codeAttr != null) { - result.commands = CommandParser.parse(classFile, codeAttr.getCode()); - } - return result; - } - - public int getAccessFlag() { - return accessFlag; - } - - public ConstantPool getConstantPool() { - return constantPool; - } - - public int getNameIndex() { - return nameIndex; - } - - public List getAttributes() { - return attributes; - } - - public int getDescriptorIndex() { - return descriptorIndex; - } - - public ByteCodeCommand[] getCommands() { - return commands; - } - - public String getName() { - return ((UTF8Info) getConstantPool().getConstantInfo(getNameIndex())).getValue(); - } - - public String getParamAndReturnType() { - return ((UTF8Info) getConstantPool().getConstantInfo(getDescriptorIndex())).getValue(); - } + private AccessFlag accessFlag; + private int nameIndex; + private int descriptorIndex; + private ConstantPool constantPool; + private List attributes = new ArrayList<>(); + private ByteCodeCommand[] commands; + + public Method(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { + this.accessFlag = new AccessFlag(accessFlag); + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.constantPool = constantPool; + } + + public static Method parse(ByteCodeIterator iterator, ClassFile classFile) { + int access = iterator.nextU2ToInt(); + int name = iterator.nextU2ToInt(); + int descriptor = iterator.nextU2ToInt(); + int attrCount = iterator.nextU2ToInt(); + Method result = new Method(access, name, descriptor, classFile.getConstantPool()); + for (int i = 0; i < attrCount; ++i) { + result.attributes.add(AttributeParser.parse(iterator, classFile.getConstantPool())); + } + CodeAttr codeAttr = (CodeAttr) result.attributes.stream() + .filter(a -> a instanceof CodeAttr).findFirst().orElse(null); + if (codeAttr != null) { + result.commands = CommandParser.parse(classFile, codeAttr.getCode()); + } + return result; + } + + public String[] getParamTypes() { + String str = getParamAndReturnType(); + str = str.substring(str.indexOf('(') + 1, str.lastIndexOf(')')); + String[] split = Arrays.stream(str.split("[L;]")) + .filter(s -> !"".equals(s)) + .toArray(String[]::new); + + List result = new ArrayList<>(); + Arrays.stream(split).forEach(s -> + result.add(s.length() == 1 ? + TypeUtils.parse(s) : s)); + + return result.toArray(new String[result.size()]); + } + + public int getParamCount() { + return getParamTypes().length; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public int getNameIndex() { + return nameIndex; + } + + public List getAttributes() { + return attributes; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public ByteCodeCommand[] getCommands() { + return commands; + } + + public String getName() { + return ((UTF8Info) getConstantPool().getConstantInfo(getNameIndex())).getValue(); + } + + public String getParamAndReturnType() { + return ((UTF8Info) getConstantPool().getConstantInfo(getDescriptorIndex())).getValue(); + } + + @Override + public String toString() { + return getName() + ':' + getParamAndReturnType(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/CommandParser.java b/group01/895457260/code/src/main/java/jvm/command/CommandParser.java index be794b07ed..7227d5e6d5 100644 --- a/group01/895457260/code/src/main/java/jvm/command/CommandParser.java +++ b/group01/895457260/code/src/main/java/jvm/command/CommandParser.java @@ -9,41 +9,6 @@ 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) { String packageName = CommandParser.class.getPackage().getName() + ".item.impl."; CommandIterator iterator = new CommandIterator(codes); @@ -51,9 +16,9 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { try { while (iterator.hasNext()) { String opCode = iterator.next2CharAsString().toUpperCase(); - String cmdClassName = packageName - + ByteCodeCommand.codeMap.get(opCode).replaceAll("_", "") - + "Cmd"; + String cmdName = ByteCodeCommand.codeMap.get(opCode); + String cmdClassName = packageName + cmdName.replaceAll("_", "") + "Cmd"; + Class clazz = Class.forName(cmdClassName); Constructor constructor = clazz.getConstructor( ClassFile.class, String.class, CommandIterator.class); diff --git a/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java b/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java index b5276f526c..95fc736b47 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/ByteCodeCommand.java @@ -4,6 +4,9 @@ import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; import jvm.command.CommandIterator; +import jvm.engine.ExecutionResult; +import jvm.engine.StackFrame; +import jvm.exception.ReadClassException; import java.util.HashMap; import java.util.Map; @@ -21,15 +24,19 @@ public abstract class ByteCodeCommand { codeMap.put("BB", "New"); codeMap.put("37", "LStore"); + codeMap.put("B9", "InvokeInterface"); + codeMap.put("B8", "InvokeStatic"); codeMap.put("B7", "InvokeSpecial"); codeMap.put("B6", "InvokeVirtual"); - codeMap.put("B4", "GetField"); codeMap.put("B5", "PutField"); + codeMap.put("B4", "GetField"); + codeMap.put("B3", "PutStatic"); codeMap.put("B2", "GetStatic"); codeMap.put("2A", "ALoad_0"); codeMap.put("2B", "ALoad_1"); codeMap.put("2C", "ALoad_2"); + codeMap.put("2D", "ALoad_3"); codeMap.put("10", "BiPush"); codeMap.put("15", "ILoad"); @@ -43,7 +50,11 @@ public abstract class ByteCodeCommand { codeMap.put("1E", "LLoad_0"); codeMap.put("24", "FLoad_2"); + + codeMap.put("4B", "AStore_0"); codeMap.put("4C", "AStore_1"); + codeMap.put("4D", "AStore_2"); + codeMap.put("4E", "AStore_3"); codeMap.put("A2", "If_Icmp_Ge"); codeMap.put("A4", "If_Icmple"); @@ -57,15 +68,20 @@ public abstract class ByteCodeCommand { codeMap.put("03", "IConst_0"); codeMap.put("04", "IConst_1"); + codeMap.put("3B", "IStore_0"); codeMap.put("3C", "IStore_1"); codeMap.put("3D", "IStore_2"); + codeMap.put("3E", "IStore_3"); codeMap.put("59", "Dup"); + codeMap.put("57", "Pop"); codeMap.put("60", "IAdd"); codeMap.put("84", "IInc"); codeMap.put("12", "Ldc"); + + codeMap.put("C7", "IfNonNull"); } ByteCodeCommand(ClassFile clzFile, String opCode, CommandIterator iterator) { @@ -113,5 +129,5 @@ public String getReadableCodeText() { return txt == null ? opCode : txt.toLowerCase(); } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame, ExecutionResult result) throws ReadClassException; } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java index 8ae6926cc6..b7cb7943e0 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/OneOperandCmd.java @@ -20,8 +20,8 @@ public int getOperand() { return this.operand; } - public void setOperand(int oprand1) { - this.operand = oprand1; + public void setOperand(int operand) { + this.operand = operand; } public int getLength() { diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AConstNullCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AConstNullCmd.java new file mode 100644 index 0000000000..216ef3cdba --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AConstNullCmd.java @@ -0,0 +1,28 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class AConstNullCmd extends NoOperandCmd { + public AConstNullCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + frame.getOperandStack().push(null); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java index 9673b3f441..e50e3cf836 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad0Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ALoad0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(0); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java index 549602b291..5b5e095532 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad1Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ALoad1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(1); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java index 12dc0c6088..e3716e566c 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad2Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ALoad2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(2); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java index 2c151b2de2..e0118311dc 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ALoad3Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ALoad3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(3); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java index 71909a5a22..86c671ae2a 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore0Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public AStore0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getOperandStack().pop(); + frame.setLocalVariableValue(0, object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java index 379da9077c..54e5331790 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore1Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public AStore1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getOperandStack().pop(); + frame.setLocalVariableValue(1, object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java index b11cf64bac..b911f8b5ba 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore2Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public AStore2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getOperandStack().pop(); + frame.setLocalVariableValue(2, object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java index eedd211522..9d8ab29f5e 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/AStore3Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public AStore3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getOperandStack().pop(); + frame.setLocalVariableValue(3, object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java index da2b176cb4..1296e4c0b9 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/BiPushCmd.java @@ -4,6 +4,10 @@ import jvm.classfile.ConstantPool; import jvm.command.CommandIterator; import jvm.command.item.OneOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.Heap; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { public BiPushCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { @@ -14,4 +18,11 @@ public BiPushCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString(ConstantPool pool) { return this.getOffset() + ": " + this.getOpCode() + " " + this.getReadableCodeText() + " " + this.getOperand(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int op = getOperand(); + JavaObject object = Heap.getInstance().newInt(op); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java index d9d02922fb..3543bc4f37 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/DupCmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public DupCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getOperandStack().peek(); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java index e0e4701bc3..1aba8f7604 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetFieldCmd.java @@ -2,8 +2,13 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.FieldRefInfo; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.Heap; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -16,5 +21,13 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject obj = frame.getOperandStack().pop(); + int fieldIndex = (getOperand1() << 8) | getOperand2(); + FieldRefInfo fieldRefInfo = (FieldRefInfo) getConstantInfo(fieldIndex); + String fieldName = fieldRefInfo.getNameAndType().split(":")[0]; + JavaObject value = obj.getFieldValue(fieldName); + frame.getOperandStack().push(value); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java index 16959b04e0..38da187aae 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/GetStaticCmd.java @@ -2,8 +2,12 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.field.Field; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.*; +import jvm.exception.ReadClassException; public class GetStaticCmd extends TwoOperandCmd { @@ -16,4 +20,14 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) throws ReadClassException { + int index = (getOperand1() << 8) | getOperand2(); + FieldRefInfo fieldRefInfo = (FieldRefInfo) getConstantInfo(index); + ClassFile classFile = MethodArea.getInstance().findClassFile(fieldRefInfo.getClassName()); + String fieldName = fieldRefInfo.getNameAndType().split(":")[0]; + Field field = classFile.getField(fieldName); + JavaObject object = classFile.getStaticFieldValue(field.getName()); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/GoToCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/GoToCmd.java new file mode 100644 index 0000000000..15ae39dfa4 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/GoToCmd.java @@ -0,0 +1,31 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; +import jvm.util.NumberUtils; + +public class GoToCmd extends TwoOperandCmd { + + public GoToCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int nextCmdOffset = (getOperand1() << 8) | getOperand2(); + nextCmdOffset = NumberUtils.toSignedInt(nextCmdOffset, 16); + nextCmdOffset += getOffset(); + result.setNextCmdOffset(nextCmdOffset); + result.setNextAction(ExecutionResult.JUMP); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java index c02449abb8..5b3ff1e7e1 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad0Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ILoad0Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(0); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java index ee35698dce..ca858b90bb 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad1Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ILoad1Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(1); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java index 1f0962b1a8..a88a976e59 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad2Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ILoad2Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(2); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java index dd64684d1a..08e4920be8 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ILoad3Cmd.java @@ -3,6 +3,9 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +20,10 @@ public ILoad3Cmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject object = frame.getLocalVariableValue(3); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/IfNonNullCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/IfNonNullCmd.java new file mode 100644 index 0000000000..290477e4fd --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/IfNonNullCmd.java @@ -0,0 +1,35 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; +import jvm.util.NumberUtils; + +public class IfNonNullCmd extends TwoOperandCmd { + + public IfNonNullCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject obj = frame.getOperandStack().pop(); + if (obj != null) { + int nextCmdOffset = (getOperand1() << 8) | getOperand2(); + nextCmdOffset = NumberUtils.toSignedInt(nextCmdOffset, 16); + nextCmdOffset += getOffset(); + result.setNextCmdOffset(nextCmdOffset); + result.setNextAction(ExecutionResult.JUMP); + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java index 3bc0281582..1b068b95a7 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeSpecialCmd.java @@ -2,8 +2,14 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.method.Method; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.MethodArea; +import jvm.engine.StackFrame; +import jvm.exception.ReadClassException; public class InvokeSpecialCmd extends TwoOperandCmd { public InvokeSpecialCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { @@ -14,4 +20,20 @@ public InvokeSpecialCmd(ClassFile clzFile, String opCode, CommandIterator iterat public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) throws ReadClassException { + int methodIndex = (getOperand1() << 8) | getOperand2(); + MethodRefInfo methodRefInfo = (MethodRefInfo) getConstantInfo(methodIndex); + + // 不调用Object的构造器 + if (methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getName().equals("")) { + frame.getOperandStack().pop(); // 弹出不需要的this + return; + } + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + Method method = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextMethod(method); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeStaticCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeStaticCmd.java new file mode 100644 index 0000000000..9a5c9f3e88 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeStaticCmd.java @@ -0,0 +1,32 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.method.Method; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.MethodArea; +import jvm.engine.StackFrame; +import jvm.exception.ReadClassException; + +public class InvokeStaticCmd extends TwoOperandCmd { + public InvokeStaticCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) throws ReadClassException { + int methodIndex = (getOperand1() << 8) | getOperand2(); + MethodRefInfo methodRefInfo = (MethodRefInfo) getConstantInfo(methodIndex); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + Method method = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextMethod(method); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java index c5809c1ea8..7066c224b0 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/InvokeVirtualCmd.java @@ -2,8 +2,14 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.method.Method; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.MethodArea; +import jvm.engine.StackFrame; +import jvm.exception.ReadClassException; public class InvokeVirtualCmd extends TwoOperandCmd { public InvokeVirtualCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { @@ -14,4 +20,13 @@ public InvokeVirtualCmd(ClassFile clzFile, String opCode, CommandIterator iterat public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) throws ReadClassException { + int methodIndex = (getOperand1() << 8) | getOperand2(); + MethodRefInfo methodRefInfo = (MethodRefInfo) getConstantInfo(methodIndex); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + Method method = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextMethod(method); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java index 73e7aa8f8e..faccb414c3 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/LdcCmd.java @@ -3,9 +3,16 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.item.impl.FloatInfo; +import jvm.classfile.constant.item.impl.IntegerInfo; import jvm.classfile.constant.item.impl.StringInfo; import jvm.command.CommandIterator; import jvm.command.item.OneOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.Heap; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -24,4 +31,11 @@ public String toString(ConstantPool pool) { return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " " + value; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int op = getOperand(); + Constant constant = getConstantInfo(op); + JavaObject object = Heap.getInstance().createObject(constant); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java index 67a598a624..58b5cdc919 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/NewCmd.java @@ -2,8 +2,13 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.Heap; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; public class NewCmd extends TwoOperandCmd { @@ -13,7 +18,14 @@ public NewCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { @Override public String toString(ConstantPool pool) { - return super.getOperandAsClassInfo(pool); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int index = (getOperand1() << 8) | getOperand2(); + Constant constant = getConstantInfo(index); + JavaObject object = Heap.getInstance().createObject(constant); + frame.getOperandStack().push(object); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/PopCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/PopCmd.java new file mode 100644 index 0000000000..503f40ae92 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/PopCmd.java @@ -0,0 +1,28 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.command.CommandIterator; +import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; + +/** + * Created by Haochen on 2017/4/20. + * TODO: + */ +public class PopCmd extends NoOperandCmd { + public PopCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString() { + return this.getOffset() + ": " + this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + frame.getOperandStack().pop(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java index 58628d8dff..480a042736 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutFieldCmd.java @@ -2,8 +2,12 @@ import jvm.classfile.ClassFile; import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.FieldRefInfo; import jvm.command.CommandIterator; import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -15,4 +19,14 @@ public PutFieldCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + JavaObject value = frame.getOperandStack().pop(); + JavaObject obj = frame.getOperandStack().pop(); + int fieldIndex = (getOperand1() << 8) | getOperand2(); + FieldRefInfo fieldRefInfo = (FieldRefInfo) getConstantInfo(fieldIndex); + String fieldName = fieldRefInfo.getNameAndType().split(":")[0]; + obj.setFieldValue(fieldName, value); + } } diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/PutStaticCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutStaticCmd.java new file mode 100644 index 0000000000..cb1a16a098 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/PutStaticCmd.java @@ -0,0 +1,36 @@ +package jvm.command.item.impl; + +import jvm.classfile.ClassFile; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.field.Field; +import jvm.command.CommandIterator; +import jvm.command.item.TwoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.JavaObject; +import jvm.engine.MethodArea; +import jvm.engine.StackFrame; +import jvm.exception.ReadClassException; + +public class PutStaticCmd extends TwoOperandCmd { + + public PutStaticCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { + super(clzFile, opCode, iterator); + } + + @Override + public String toString(ConstantPool pool) { + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) throws ReadClassException { + int index = (getOperand1() << 8) | getOperand2(); + FieldRefInfo fieldRefInfo = (FieldRefInfo) getConstantInfo(index); + ClassFile classFile = MethodArea.getInstance().findClassFile(fieldRefInfo.getClassName()); + String fieldName = fieldRefInfo.getNameAndType().split(":")[0]; + Field field = classFile.getField(fieldName); + JavaObject object = frame.getOperandStack().pop(); + classFile.putStaticFieldValue(field.getName(), object); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java b/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java index cc46fe4caa..5897ff5f8b 100644 --- a/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java +++ b/group01/895457260/code/src/main/java/jvm/command/item/impl/ReturnCmd.java @@ -3,6 +3,8 @@ import jvm.classfile.ClassFile; import jvm.command.CommandIterator; import jvm.command.item.NoOperandCmd; +import jvm.engine.ExecutionResult; +import jvm.engine.StackFrame; /** * Created by Haochen on 2017/4/20. @@ -17,4 +19,9 @@ public ReturnCmd(ClassFile clzFile, String opCode, CommandIterator iterator) { public String toString() { return this.getOffset() + ": " + this.getReadableCodeText(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + } } diff --git a/group01/895457260/code/src/main/java/jvm/engine/ConsolePrinter.java b/group01/895457260/code/src/main/java/jvm/engine/ConsolePrinter.java new file mode 100644 index 0000000000..88e72bdc21 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/ConsolePrinter.java @@ -0,0 +1,18 @@ +package jvm.engine; + +/** + * Created by Haochen on 2017/4/30. + * TODO: + */ +public class ConsolePrinter { + volatile static Object printingBuf = null; + + public static void println(Object o) { + while (true) { + if (printingBuf == null) { + printingBuf = o; + break; + } + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/ExecutionResult.java b/group01/895457260/code/src/main/java/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..9a9de30255 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/ExecutionResult.java @@ -0,0 +1,50 @@ +package jvm.engine; + +import jvm.classfile.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + private int nextCmdOffset = 0; + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action) { + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame() { + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame() { + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd() { + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump() { + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/ExecutorEngine.java b/group01/895457260/code/src/main/java/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..e984426689 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/ExecutorEngine.java @@ -0,0 +1,55 @@ +package jvm.engine; + +import jvm.classfile.method.Method; +import jvm.exception.ReadClassException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class ExecutorEngine { + private Stack stack = new Stack<>(); + + public void execute(Method main) throws ReadClassException { + StackFrame mainFrame = StackFrame.create(main); + stack.push(mainFrame); + + while (!stack.isEmpty()) { + StackFrame top = stack.peek(); + ExecutionResult result = top.execute(); + if (result.isExitCurrentFrame()) { + stack.pop(); + } else if (result.isPauseAndRunNewFrame()) { + Method next = result.getNextMethod(); + StackFrame newFrame = StackFrame.create(next); + setupFunctionCallParams(top, newFrame); + stack.push(newFrame); + } + } + } + + private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) { + List local = createLocalVariableTable(currentFrame, nextFrame.getMethod()); + nextFrame.setLocalVariableTable(local); + nextFrame.setCallerFrame(currentFrame); + } + + private List createLocalVariableTable(StackFrame top, Method next) { + int paramCount = next.getParamCount(); + Stack params = new Stack<>(); + for (int i = 0; i < paramCount; ++i) { + JavaObject param = top.getOperandStack().pop(); + params.push(param); + } + if (!next.getAccessFlag().isStatic()) { + JavaObject param = top.getOperandStack().pop(); + params.push(param); + } + + List local = new ArrayList<>(); + while (!params.isEmpty()) { + local.add(params.pop()); + } + return local; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/Heap.java b/group01/895457260/code/src/main/java/jvm/engine/Heap.java new file mode 100644 index 0000000000..bc06cf7a15 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/Heap.java @@ -0,0 +1,63 @@ +package jvm.engine; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.item.impl.FloatInfo; +import jvm.classfile.constant.item.impl.IntegerInfo; +import jvm.classfile.constant.item.impl.StringInfo; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + private static Heap instance = new Heap(); + + private Heap() { + } + + public static Heap getInstance() { + return instance; + } + + public JavaObject createObject(Constant constant) { + if (constant instanceof IntegerInfo) { + int value = ((IntegerInfo) constant).getValue(); + return Heap.getInstance().newInt(value); + } else if (constant instanceof FloatInfo) { + float value = ((FloatInfo) constant).getValue(); + return Heap.getInstance().newFloat(value); + } else if (constant instanceof StringInfo) { + String value = ((StringInfo) constant).getValue(); + return Heap.getInstance().newString(value); + } else if (constant instanceof ClassInfo) { + String className = ((ClassInfo) constant).getClassName(); + return Heap.getInstance().newClassReference(className); + } + return null; + } + + public JavaObject newClassReference(String clzName) { + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value) { + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value) { + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + + public JavaObject newInt(int value) { + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/JavaObject.java b/group01/895457260/code/src/main/java/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..6d1379ad89 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/JavaObject.java @@ -0,0 +1,89 @@ +package jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + private int type; + private String className; + private Map fieldValues = new HashMap<>(); + private String stringValue; + private int intValue; + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue) { + fieldValues.put(fieldName, fieldValue); + } + + public JavaObject(int type) { + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setStringValue(String value) { + stringValue = value; + } + + public String getStringValue() { + return this.stringValue; + } + + public void setIntValue(int value) { + this.intValue = value; + } + + public int getIntValue() { + return this.intValue; + } + + public int getType() { + return type; + } + + public JavaObject getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public String toString() { + switch (this.getType()) { + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className + ":" + this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default: + return null; + } + } + + public String getClassName() { + return this.className; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } + + public JavaObject(JavaObject object) { + type = object.type; + className = object.className; + stringValue = object.stringValue; + intValue = object.intValue; + floatValue = object.floatValue; + fieldValues = new HashMap<>(); + for (Map.Entry entry : fieldValues.entrySet()) { + fieldValues.put(entry.getKey(), new JavaObject(entry.getValue())); + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/MethodArea.java b/group01/895457260/code/src/main/java/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..20f3e3c310 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/MethodArea.java @@ -0,0 +1,59 @@ +package jvm.engine; + +import jvm.ClassFileLoader; +import jvm.classfile.ClassFile; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.method.Method; +import jvm.exception.ReadClassException; + +import java.util.HashMap; +import java.util.Map; + +public class MethodArea { + + private static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + private Map map = new HashMap<>(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) throws ReadClassException { + ClassFile clzFile = this.findClassFile(className); + return clzFile.getMainMethod(); + } + + public ClassFile findClassFile(String className) throws ReadClassException { + if (map.get(className) != null) { + return map.get(className); + } + // 看来该class文件还没有load过 + ClassFile clzFile = this.clzLoader.load(className); + map.put(className, clzFile); + return clzFile; + } + + public Method getMethod(String className, String methodName, String paramAndReturnType) + throws ReadClassException { + ClassFile classFile = findClassFile(className); + return classFile.getMethod(methodName, paramAndReturnType); + } + + public Method getMethod(MethodRefInfo methodRef) throws ReadClassException { + return getMethod(methodRef.getClassName(), methodRef.getName(), methodRef.getParamAndReturnType()); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/MiniJVM.java b/group01/895457260/code/src/main/java/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..8eb36f033e --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/MiniJVM.java @@ -0,0 +1,51 @@ +package jvm.engine; + +import jvm.ClassFileLoader; +import jvm.exception.ReadClassException; + +import java.util.ArrayList; +import java.util.List; + +public class MiniJVM { + private boolean enablePrint = true; + + private static final List defaultClassPaths = new ArrayList<>(); + + public MiniJVM() { + defaultClassPaths.add("target/classes"); + } + + public void run(String[] classPaths, String className) throws ReadClassException { + ClassFileLoader loader = new ClassFileLoader(); + for (String classPath : defaultClassPaths) { + loader.addClassPath(classPath); + } + for (String classPath : classPaths) { + loader.addClassPath(classPath); + } + + MethodArea methodArea = MethodArea.getInstance(); + methodArea.setClassFileLoader(loader); + ExecutorEngine engine = new ExecutorEngine(); + className = className.replace(".", "/"); + + initConsolePrinting(); + + engine.execute(methodArea.getMainMethod(className)); + + while (enablePrint && ConsolePrinter.printingBuf == null) { + enablePrint = false; + } + } + + private void initConsolePrinting() { + new Thread(() -> { + while (enablePrint) { + if (ConsolePrinter.printingBuf != null) { + System.out.println(ConsolePrinter.printingBuf); + ConsolePrinter.printingBuf = null; + } + } + }).start(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/engine/StackFrame.java b/group01/895457260/code/src/main/java/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..f360f8dc30 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/engine/StackFrame.java @@ -0,0 +1,100 @@ +package jvm.engine; + +import jvm.classfile.method.Method; +import jvm.command.item.ByteCodeCommand; +import jvm.command.item.TwoOperandCmd; +import jvm.exception.ReadClassException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class StackFrame { + private List localVariableTable = new ArrayList<>(); + private Stack operandStack = new Stack<>(); + + private int index = 0; + private Method method = null; + private StackFrame callerFrame = null; + + private StackFrame(Method method) { + this.method = method; + } + + public ExecutionResult execute() throws ReadClassException { + ByteCodeCommand[] commands = getMethod().getCommands(); + + while (index < commands.length) { + ByteCodeCommand cmd = commands[index]; + ExecutionResult result = new ExecutionResult(); + cmd.execute(this, result); + + if (result.isExitCurrentFrame()) { + return result; + } else if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } else if (result.isJump()) { + int offset = result.getNextCmdOffset(); + index = getNextCommandIndex(offset); + } else { + index++; + } + } + ExecutionResult frameResult = new ExecutionResult(); + frameResult.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return frameResult; + } + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m) { + return new StackFrame(m); + } + + public JavaObject getLocalVariableValue(int index) { + return this.localVariableTable.get(index); + } + + public Stack getOperandStack() { + return this.operandStack; + } + + public int getNextCommandIndex(int offset) { + ByteCodeCommand[] commands = method.getCommands(); + for (int i = 0; i < commands.length; i++) { + if (commands[i].getOffset() == offset) { + return i; + } + } + throw new RuntimeException("Can't find next command"); + } + + public void setLocalVariableTable(List values) { + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo) { + if (this.localVariableTable.size() - 1 < index) { + for (int i = this.localVariableTable.size(); i <= index; i++) { + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + } + + public Method getMethod() { + return method; + } + + @Override + public String toString() { + return getMethod().toString(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java index 1d2ca39d46..a53017333d 100644 --- a/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java +++ b/group01/895457260/code/src/main/java/jvm/print/ClassFilePrinter.java @@ -4,9 +4,6 @@ import jvm.classfile.ClassFile; import jvm.exception.ReadClassException; -import java.util.ArrayList; -import java.util.List; - public class ClassFilePrinter { ClassFile clzFile; @@ -15,7 +12,7 @@ public ClassFilePrinter(ClassFile clzFile) { } public void print() { - if (clzFile.getAccessFlag().isPublicClass()) { + if (clzFile.getAccessFlag().isPublic()) { System.out.println("Access flag : public "); } System.out.println("Class Name: " + clzFile.getClassName()); diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java b/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java index a385aee580..535688e408 100644 --- a/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java +++ b/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java @@ -47,7 +47,7 @@ public String nextHexString(int byteCount) { } public int nextInt(int byteCount) { - int result = ByteUtils.toInt(codes, pos, byteCount); + int result = ByteUtils.toUnsignedInt(codes, pos, byteCount); pos += byteCount; return result; } diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java index 5a82776eef..829ff20d10 100644 --- a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java +++ b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java @@ -1,5 +1,8 @@ package jvm.util; +import jvm.util.code.Code; +import jvm.util.code.CompCode; + /** * Created by Haochen on 2017/4/9. * TODO: @@ -19,7 +22,19 @@ public static String toHexString(byte[] bytes, int off, int len) { return builder.toString(); } - public static int toInt(byte[] bytes, int off, int len) { + public static int toUnsignedInt(byte[] bytes) { + return toUnsignedInt(bytes, 0, bytes.length); + } + + public static int toUnsignedInt(byte[] bytes, int off, int len) { return Integer.parseInt(toHexString(bytes, off, len), 16); } + + public static float toFloat(byte[] bytes) { + return toFloat(bytes, 0, bytes.length); + } + + public static float toFloat(byte[] bytes, int off, int len) { + return Float.intBitsToFloat(toUnsignedInt(bytes, off, len)); + } } diff --git a/group01/895457260/code/src/main/java/jvm/util/NumberUtils.java b/group01/895457260/code/src/main/java/jvm/util/NumberUtils.java new file mode 100644 index 0000000000..9115303775 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/NumberUtils.java @@ -0,0 +1,22 @@ +package jvm.util; + +import jvm.util.code.Code; +import jvm.util.code.CompCode; + +/** + * Created by Haochen on 2017/4/30. + * TODO: + */ +public class NumberUtils { + public static int toSignedInt(int unsigned, int bitCount) { + String bin = Integer.toBinaryString(unsigned); + int leader0Count = bitCount - bin.length(); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < leader0Count; ++i) { + builder.append('0'); + } + builder.append(bin); + Code trueCode = new CompCode(Code.PURE_INTEGER, builder.toString()).trueCode(); + return Integer.parseInt(trueCode.getCode(), 2); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/TypeUtils.java b/group01/895457260/code/src/main/java/jvm/util/TypeUtils.java new file mode 100644 index 0000000000..7861806581 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/TypeUtils.java @@ -0,0 +1,54 @@ +package jvm.util; + +import jvm.classfile.field.Field; +import jvm.engine.Heap; +import jvm.engine.JavaObject; + +/** + * Created by Haochen on 2017/4/30. + * TODO: + */ +public class TypeUtils { + private static final String INT = "I"; + private static final String FLOAT = "F"; + private static final String LONG = "J"; + private static final String DOUBLE = "D"; + private static final String CHAR = "C"; + private static final String BYTE = "B"; + private static final String BOOLEAN = "Z"; + private static final String SHORT = "S"; + + private static final String REFERENCE = "ref"; + + public static String parse(String inClassFile) { + switch (inClassFile) { + case INT: + return "int"; + case FLOAT: + return "float"; + case LONG: + return "long"; + case DOUBLE: + return "double"; + case CHAR: + return "char"; + case BYTE: + return "byte"; + case BOOLEAN: + return "boolean"; + case SHORT: + return "short"; + } + return REFERENCE; + } + + public static JavaObject getDefaultValue(Field field) { + switch (field.getDescriptor()) { + case INT: + return Heap.getInstance().newInt(0); + case FLOAT: + return Heap.getInstance().newFloat(0); + } + return null; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/Code.java b/group01/895457260/code/src/main/java/jvm/util/code/Code.java new file mode 100644 index 0000000000..75f0838b52 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/Code.java @@ -0,0 +1,100 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public abstract class Code { + public static final int PURE_DECIMAL = 1; + public static final int PURE_INTEGER = 2; + + protected String code; + protected int type; + protected Getter getter; + + public Code(int type, String code) { + this.type = type; + this.code = code.replaceAll("[+]", ""); + init(); + } + + protected final void init() { + if (type == PURE_DECIMAL) { + getter = new PureDecimal(); + } else { + getter = new PureInteger(); + } + } + + public String getCode() { + return code; + } + + public int getType() { + return type; + } + + public String bitwiseNOTAddOne() { + int[] array = intArray(); + int last1 = code.lastIndexOf('1'); + for (int i = 1; i < last1; ++i) { + array[i] = 1 - array[i]; + } + return intArrayToString(array); + } + + public String compString() { + if (isNegative()) { + return bitwiseNOTAddOne(); + } else { + return code; + } + } + + public static String intArrayToString(int[] array) { + String str = ""; + for (int i : array) { + str += i; + } + return str; + } + + public int[] intArray() { + int[] array = new int[code.length()]; + char[] chars = code.toCharArray(); + for (int i = 0; i < array.length; ++i) { + array[i] = Integer.parseInt("" + chars[i]); + } + return array; + } + + public int length() { + return code.length(); + } + + public boolean isNegative() { + return code.startsWith("1"); + } + + public final double value() { + return getter.value(trueCode()); + } + + public Code valueCode() { + return getter.valueCode(trueCode()); + } + + public Code compCode() { + return trueCode().compCode(); + } + + public void expand(int bit) { + getter.expand(this, bit, 0); + } + + public void expand(int bit, int fill) { + getter.expand(this, bit, fill); + } + + public abstract Code trueCode(); + public abstract Code inverseSign(); +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/CompCode.java b/group01/895457260/code/src/main/java/jvm/util/code/CompCode.java new file mode 100644 index 0000000000..a7e1fb426a --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/CompCode.java @@ -0,0 +1,27 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public class CompCode extends Code { + public CompCode(int type, String code) { + super(type, code); + } + + @Override + public Code compCode() { + return this; + } + + @Override + public Code trueCode() { + return new TrueCode(type, compString()); + } + + @Override + public Code inverseSign() { + String str = bitwiseNOTAddOne().substring(1); + Code code = new CompCode(type, isNegative() ? "0" + str : "1" + str); + return code; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/Getter.java b/group01/895457260/code/src/main/java/jvm/util/code/Getter.java new file mode 100644 index 0000000000..235cbae969 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/Getter.java @@ -0,0 +1,18 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public abstract class Getter { + public final double value(Code trueCode) { + return value(trueCode.getCode()); + } + + public final Code valueCode(Code trueCode) { + return valueCode(trueCode.getCode()); + } + + public abstract double value(String trueCode); + public abstract Code valueCode(String trueCode); + public abstract void expand(Code code, int bit, int fill); +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/PureDecimal.java b/group01/895457260/code/src/main/java/jvm/util/code/PureDecimal.java new file mode 100644 index 0000000000..82f2dbd0fe --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/PureDecimal.java @@ -0,0 +1,35 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public class PureDecimal extends Getter { + @Override + public double value(String trueCode) { + char[] array = trueCode.toCharArray(); + + double result = 0; + double r = 0.5; + for (int i = 1; i < array.length; ++i, r /= 2) { + result += Integer.parseInt("" + array[i]) * r; + } + + if (trueCode.startsWith("1")) { + result *= -1; + } + return result; + } + + @Override + public Code valueCode(String trueCode) { + return new ValueCode(trueCode.startsWith("1") ? + trueCode.replaceFirst("1", "-0.") : trueCode.replaceFirst("0", "0.")); + } + + @Override + public void expand(Code code, int bit, int fill) { + for (int i = code.code.length(); i < bit; ++i) { + code.code += fill; + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/PureInteger.java b/group01/895457260/code/src/main/java/jvm/util/code/PureInteger.java new file mode 100644 index 0000000000..2a5d36f603 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/PureInteger.java @@ -0,0 +1,36 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public class PureInteger extends Getter { + @Override + public double value(String trueCode) { + char[] array = trueCode.toCharArray(); + + int result = 0; + for (int i = array.length - 1, r = 1; i > 0; --i, r *= 2) { + result += Integer.parseInt("" + array[i]) * r; + } + + if (trueCode.startsWith("1")) { + result *= -1; + } + return result; + } + + @Override + public Code valueCode(String trueCode) { + return new ValueCode(trueCode.startsWith("1") ? + trueCode.replaceFirst("1", "-") : trueCode.replaceFirst("0", "")); + } + + @Override + public void expand(Code code, int bit, int fill) { + StringBuilder builder = new StringBuilder(code.code); + for (int i = code.code.length(); i < bit; ++i) { + builder.insert(1, fill); + } + code.code = builder.toString(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/TrueCode.java b/group01/895457260/code/src/main/java/jvm/util/code/TrueCode.java new file mode 100644 index 0000000000..10f872e56d --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/TrueCode.java @@ -0,0 +1,27 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public class TrueCode extends Code { + public TrueCode(int type, String code) { + super(type, code); + } + + @Override + public Code compCode() { + return new CompCode(type, compString()); + } + + @Override + public Code trueCode() { + return this; + } + + @Override + public Code inverseSign() { + String str = code.substring(1); + Code code = new TrueCode(type, isNegative() ? "0" + str : "1" + str); + return code; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/code/ValueCode.java b/group01/895457260/code/src/main/java/jvm/util/code/ValueCode.java new file mode 100644 index 0000000000..5f42be3b44 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/code/ValueCode.java @@ -0,0 +1,48 @@ +package jvm.util.code; + +/** + * Created by Haochen on 2017/1/5. + */ +public class ValueCode extends Code { + public ValueCode(String code) { + super(code.contains(".") ? PURE_DECIMAL : PURE_INTEGER, code); + } + + @Override + public String compString() { + return ""; + } + + @Override + public boolean isNegative() { + return code.startsWith("-"); + } + + @Override + public int[] intArray() { + return new int[0]; + } + + @Override + public Code valueCode() { + return this; + } + + @Override + public void expand(int bit, int fill) { + super.expand(bit); + } + + @Override + public Code trueCode() { + String str = isNegative() ? "1" + code.substring(1) : "0" + code; + return new TrueCode(type, str.replaceAll("0[.]", "")); + } + + @Override + public Code inverseSign() { + String str = code; + Code code = new ValueCode(isNegative() ? str.substring(1) : "-" + str); + return code; + } +} diff --git a/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java b/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java index d57f19fcda..e1a4cb2268 100644 --- a/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java +++ b/group01/895457260/code/src/test/java/algorithm/expression/PostfixExprTest.java @@ -32,6 +32,12 @@ public void testEvaluate() { PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); Assert.assertEquals(54, expr.evaluate(),0.0f); } + + { + //10-2^3+50 + PostfixExpr expr = new PostfixExpr("10 2 3 ^ - 50 +"); + Assert.assertEquals(52, expr.evaluate(),0.0f); + } } } diff --git a/group01/895457260/code/src/test/java/algorithm/queue/JosephusTest.java b/group01/895457260/code/src/test/java/algorithm/queue/JosephusTest.java new file mode 100644 index 0000000000..beec8cbee0 --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package algorithm.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group01/895457260/code/src/test/java/datastructure/QueueTest.java b/group01/895457260/code/src/test/java/datastructure/QueueTest.java index f2a9495484..cb0383d441 100644 --- a/group01/895457260/code/src/test/java/datastructure/QueueTest.java +++ b/group01/895457260/code/src/test/java/datastructure/QueueTest.java @@ -1,5 +1,6 @@ package datastructure; +import datastructure.basic.LinkedList; import datastructure.exception.EmptyQueueException; import datastructure.basic.Queue; import org.junit.Assert; @@ -29,7 +30,7 @@ public void after() throws Exception { } private Queue getQueue() { - Queue queue = new Queue(5); + Queue queue = new Queue(); for (int i = 1; i <= 5; ++i) { queue.enQueue(i); } @@ -38,35 +39,19 @@ private Queue getQueue() { private void assertQueue(Queue queue, Object[] actual) { Class clazz = Queue.class; - Object[] array = null; - int head = 0; - int rear = 0; - Method mapIndex = null; + LinkedList list = null; try { - Field arrayField = clazz.getDeclaredField("array"); - Field headField = clazz.getDeclaredField("head"); - Field rearField = clazz.getDeclaredField("rear"); - mapIndex = clazz.getDeclaredMethod("mapIndex", int.class); - arrayField.setAccessible(true); - headField.setAccessible(true); - rearField.setAccessible(true); - mapIndex.setAccessible(true); - array = (Object[]) arrayField.get(queue); - head = (int) headField.get(queue); - rear = (int) rearField.get(queue); - } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { + Field listField = clazz.getDeclaredField("list"); + listField.setAccessible(true); + list = (LinkedList) listField.get(queue); + } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); + Assert.fail(); } int size = queue.size(); Object[] excepted = new Object[size]; - int pos = 0; - try { - while (head < rear) { - excepted[pos++] = array[(int) mapIndex.invoke(queue, head)]; - head++; - } - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); + for (int i = 0; i < size; ++i) { + excepted[i] = list.get(i); } Assert.assertArrayEquals(excepted, actual); } diff --git a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java index daaa65a680..7f7b57b69e 100644 --- a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java +++ b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java @@ -56,7 +56,7 @@ public void testClassPath() { public void testClassFileLength() throws ReadClassException { byte[] byteCodes = loader.readBinaryCode(LOAD_CLASS_NAME); // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1016, byteCodes.length); + Assert.assertEquals(981, byteCodes.length); } @Test @@ -79,65 +79,65 @@ public void testConstantPool() { ConstantPool pool = clzFile.getConstantPool(); - Assert.assertEquals(53, pool.getSize()); + Assert.assertEquals(48, pool.getSize()); { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(7); - Assert.assertEquals(44, clzInfo.getUtf8Index()); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(6); + Assert.assertEquals(41, clzInfo.getUtf8Index()); - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(44); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(41); Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); } { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(11); - Assert.assertEquals(48, clzInfo.getUtf8Index()); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(10); + Assert.assertEquals(45, clzInfo.getUtf8Index()); - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(48); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(45); Assert.assertEquals("java/lang/Object", utf8Info.getValue()); } { - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(12); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(11); Assert.assertEquals("name", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(13); + utf8Info = (UTF8Info) pool.getConstantInfo(12); Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(14); + utf8Info = (UTF8Info) pool.getConstantInfo(13); Assert.assertEquals("age", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(15); + utf8Info = (UTF8Info) pool.getConstantInfo(14); Assert.assertEquals("I", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(16); + utf8Info = (UTF8Info) pool.getConstantInfo(15); Assert.assertEquals("", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(17); + utf8Info = (UTF8Info) pool.getConstantInfo(16); Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); - utf8Info = (UTF8Info) pool.getConstantInfo(18); + utf8Info = (UTF8Info) pool.getConstantInfo(17); Assert.assertEquals("Code", utf8Info.getValue()); } { MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(1); - Assert.assertEquals(11, methodRef.getClassInfoIndex()); - Assert.assertEquals(36, methodRef.getNameAndTypeIndex()); + Assert.assertEquals(10, methodRef.getClassInfoIndex()); + Assert.assertEquals(35, methodRef.getNameAndTypeIndex()); } { - NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(36); - Assert.assertEquals(16, nameAndType.getIndex1()); - Assert.assertEquals(28, nameAndType.getIndex2()); + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(35); + Assert.assertEquals(15, nameAndType.getIndex1()); + Assert.assertEquals(27, nameAndType.getIndex2()); } //抽查几个吧 { MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(9); - Assert.assertEquals(7, methodRef.getClassInfoIndex()); - Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + Assert.assertEquals(6, methodRef.getClassInfoIndex()); + Assert.assertEquals(44, methodRef.getNameAndTypeIndex()); } { - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(35); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(34); Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); } } @@ -204,7 +204,7 @@ public void testMethods() { assertMethodEquals(pool,m, "sayHello", "()V", - "b200041205b60006b1"); + "1204b80005b1"); } { @@ -212,7 +212,7 @@ public void testMethods() { assertMethodEquals(pool,m, "main", "([Ljava/lang/String;)V", - "bb0007591208101db700094c2bb6000ab1"); + "bb0006591207101db700084c2bb60009b1"); } } @@ -260,10 +260,9 @@ public void testByteCodeCommand(){ "()V"); ByteCodeCommand [] cmds = sayHelloMethod.getCommands(); - assertOpCodeEquals("0: getstatic #4", cmds[0]); - assertOpCodeEquals("3: ldc #5", cmds[1]); - assertOpCodeEquals("5: invokevirtual #6", cmds[2]); - assertOpCodeEquals("8: return", cmds[3]); + assertOpCodeEquals("0: ldc #4", cmds[0]); + assertOpCodeEquals("2: invokestatic #5", cmds[1]); + assertOpCodeEquals("5: return", cmds[2]); } @@ -272,14 +271,14 @@ public void testByteCodeCommand(){ ByteCodeCommand [] cmds = mainMethod.getCommands(); - assertOpCodeEquals("0: new #7", cmds[0]); + assertOpCodeEquals("0: new #6", cmds[0]); assertOpCodeEquals("3: dup", cmds[1]); - assertOpCodeEquals("4: ldc #8", cmds[2]); + assertOpCodeEquals("4: ldc #7", cmds[2]); assertOpCodeEquals("6: bipush 29", cmds[3]); - assertOpCodeEquals("8: invokespecial #9", cmds[4]); + assertOpCodeEquals("8: invokespecial #8", cmds[4]); assertOpCodeEquals("11: astore_1", cmds[5]); assertOpCodeEquals("12: aload_1", cmds[6]); - assertOpCodeEquals("13: invokevirtual #10", cmds[7]); + assertOpCodeEquals("13: invokevirtual #9", cmds[7]); assertOpCodeEquals("16: return", cmds[8]); } diff --git a/group01/895457260/code/src/test/java/jvm/E.java b/group01/895457260/code/src/test/java/jvm/E.java new file mode 100644 index 0000000000..691defee19 --- /dev/null +++ b/group01/895457260/code/src/test/java/jvm/E.java @@ -0,0 +1,34 @@ +package jvm; + +public class E { + + private String name; + private int age; + + public E(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 int test(int a, int b, int c, int d, int e) { + int f = a + b; + int g = c + d + e; + System.out.println(f + g); + return 666; + } + public static void main(String[] args){ + E p = new E("Andy",29); + p.sayHello(); + int r = p.test(1, 2, 3, 4, 5); + System.out.println(r); + } +} diff --git a/group01/895457260/code/src/test/java/jvm/EmployeeV1.java b/group01/895457260/code/src/test/java/jvm/EmployeeV1.java index 84cdf0d4e6..f2f7faccc8 100644 --- a/group01/895457260/code/src/test/java/jvm/EmployeeV1.java +++ b/group01/895457260/code/src/test/java/jvm/EmployeeV1.java @@ -1,28 +1,31 @@ package jvm; +import jvm.engine.ConsolePrinter; + public class EmployeeV1 { - - - private String name; + + private String name; private int age; - + public EmployeeV1(String name, int age) { this.name = name; - this.age = age; - } + this.age = age; + } public void setName(String name) { this.name = name; } - public void setAge(int age){ - this.age = age; + + public void setAge(int age) { + this.age = age; } - public void sayHello() { - System.out.println("Hello , this is class Employee "); + + public void sayHello() { + ConsolePrinter.println("Hello , this is class Employee "); } - public static void main(String[] args){ - EmployeeV1 p = new EmployeeV1("Andy",29); - p.sayHello(); - + + public static void main(String[] args) { + EmployeeV1 p = new EmployeeV1("Andy", 29); + p.sayHello(); } } \ No newline at end of file diff --git a/group01/895457260/code/src/test/java/jvm/LiteJvmTest.java b/group01/895457260/code/src/test/java/jvm/LiteJvmTest.java deleted file mode 100644 index a6f36bb3ca..0000000000 --- a/group01/895457260/code/src/test/java/jvm/LiteJvmTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package jvm; - -import jvm.exception.MagicNumberException; -import jvm.exception.ReadClassException; -import org.junit.Assert; -import org.junit.Test; -import org.junit.Before; -import org.junit.After; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * LiteJvm Tester. - * - * @author - * @version 1.0 - * @since
三月 26, 2017
- */ -public class LiteJvmTest { - - private LiteJvm jvm = LiteJvm.INSTANCE; - private String fileName; - - @Before - public void before() throws Exception { - fileName = "target/classes/algorithm/ArrayUtil.class"; - } - - @After - public void after() throws Exception { - } - - /** - * Method: launch(File fileName) - */ - @Test - public void testLaunch() { -//TODO: Test goes here... - try { - jvm.launch(fileName); - } catch (MagicNumberException | ReadClassException e) { - e.printStackTrace(); - Assert.fail(e.getMessage()); - } - } - - - /** - * Method: checkMagicNumber(byte[] bytes) - */ - @Test - public void testCheckMagicNumber() throws Exception { -//TODO: Test goes here... -// try { -// Method method = LiteJvm.class.getDeclaredMethod("checkMagicNumber", byte[].class); -// method.setAccessible(true); -// method.invoke(jvm, ???); -// } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { -// e.printStackTrace(); -// } - } - - /** - * Method: getBytes(File fileName) - */ - @Test - public void testGetBytes() throws Exception { -//TODO: Test goes here... - try { - Method method = LiteJvm.class.getDeclaredMethod("getBytes", File.class); - method.setAccessible(true); - byte[] bytes = (byte[]) method.invoke(jvm, fileName); - Assert.assertEquals(3851, bytes.length); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - Assert.fail(e.getMessage()); - } - } - -} diff --git a/group01/895457260/code/src/test/java/jvm/engine/MiniJVMTest.java b/group01/895457260/code/src/test/java/jvm/engine/MiniJVMTest.java new file mode 100644 index 0000000000..a43af32454 --- /dev/null +++ b/group01/895457260/code/src/test/java/jvm/engine/MiniJVMTest.java @@ -0,0 +1,25 @@ +package jvm.engine; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class MiniJVMTest { + + private static final String PATH = "target/test-classes"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testRun() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "jvm.EmployeeV1"); + } + +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/FileList.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/FileList.java new file mode 100644 index 0000000000..99e4077372 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/FileList.java @@ -0,0 +1,23 @@ +package com.aaront.exercise.basic; + +import java.io.File; + +public class FileList { + public void list(File f, int deep) { + if(f == null) return; + System.out.println(_leftPad(deep) + f.getName()); + if(f.isFile()) return; + File[] files = f.listFiles(); + for (int i = 0, len = files.length; i < len; i++) { + list(files[i], deep + 1); + } + } + + private String _leftPad(int deep) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < deep; i++) { + sb.append("----"); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/Josephus.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/Josephus.java new file mode 100644 index 0000000000..8e25ad86c2 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/Josephus.java @@ -0,0 +1,31 @@ +package com.aaront.exercise.basic; + +import com.aaront.exercise.generic.GenericQueue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * + */ +public class Josephus { + + public static List execute(int n, int m) { + List manKilled = new ArrayList<>(); + GenericQueue queue = new GenericQueue<>(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + + while (queue.size() != 0) { + for (int i = 1; i < m; i++) { + queue.enQueue(queue.deQueue()); + } + manKilled.add(queue.deQueue()); + } + return manKilled; + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/QuickMinStack.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/QuickMinStack.java new file mode 100644 index 0000000000..95140bf777 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/QuickMinStack.java @@ -0,0 +1,56 @@ +package com.aaront.exercise.basic; + +import java.util.Arrays; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回该数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + */ +public class QuickMinStack { + + private static final int DEFAULT_LENGTH = 20; + private Node[] nodes = new Node[DEFAULT_LENGTH]; + + private int size = 0; + + public void push(int data) { + _ensureCapacityEnough(); + if (size == 0) { + Node node = new Node(data, data); + nodes[size++] = node; + } else { + int min = nodes[size - 1].min; + Node node = new Node(data, data > min ? min : data); + nodes[size++] = node; + } + } + + public int pop() { + if (size <= 0) throw new RuntimeException("栈为空"); + return nodes[--size].data; + } + + public int findMin() { + return nodes[size - 1].min; + } + + public int size() { + return this.size; + } + + private void _ensureCapacityEnough() { + if (size >= nodes.length) { + nodes = Arrays.copyOf(nodes, DEFAULT_LENGTH * 2); + } + } +} + +class Node { + int data; + int min; + + public Node(int data, int min) { + this.data = data; + this.min = min; + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackUtil.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackUtil.java new file mode 100644 index 0000000000..fde0d047a3 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackUtil.java @@ -0,0 +1,102 @@ +package com.aaront.exercise.basic; + +import java.util.Arrays; +import java.util.Stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if (s == null) return; + Integer[] temp = new Integer[s.size()]; + int i = 0; + while (!s.isEmpty()) { + temp[i++] = s.pop(); + } + for(i = 0;i < temp.length;i++) { + s.push(temp[i]); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + if (s == null) return; + Stack temp = new Stack(); + while (!s.isEmpty()) { + Object element = s.pop(); + if (element.equals(o)) break; + temp.push(element); + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if (s == null) return null; + int index = 0; + Object[] elements = new Object[len]; + while (!s.isEmpty() && index < len) { + elements[index] = s.pop(); + index++; + } + for (int i = index - 1; i >= 0; i--) { + s.push(elements[i]); + } + return Arrays.copyOf(elements, index); + } + + /** + * 字符串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) { + if (s.isEmpty()) return true; + Stack stack = new Stack<>(); + for (int i = 0, len = s.length(); i < len; i++) { + char c = s.charAt(i); + switch (c) { + case '(': + case '[': + case '{': + stack.push(c); + break; + case ')': + if(stack.peek().equals('(')) stack.pop(); + else return false; + break; + case ']': + if(stack.peek().equals('[')) stack.pop(); + else return false; + break; + case '}': + if (stack.peek().equals('{')) stack.pop(); + else return false; + break; + } + } + return stack.isEmpty(); + } +} + + diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackWithTwoQueues.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackWithTwoQueues.java new file mode 100644 index 0000000000..54c7db6d87 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/StackWithTwoQueues.java @@ -0,0 +1,24 @@ +package com.aaront.exercise.basic; + +import com.aaront.exercise.generic.GenericQueue; + +public class StackWithTwoQueues { + + private GenericQueue queue1 = new GenericQueue<>(); + private GenericQueue queue2 = new GenericQueue<>(); + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + while (queue1.size() != 1) { + queue2.enQueue(queue1.deQueue()); + } + int element = queue1.deQueue(); + while (!queue2.isEmpty()) { + queue1.enQueue(queue2.deQueue()); + } + return element; + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/TwoStackInOneArray.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/TwoStackInOneArray.java new file mode 100644 index 0000000000..1d2e1edb3e --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/TwoStackInOneArray.java @@ -0,0 +1,91 @@ +package com.aaront.exercise.basic; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + */ +public class TwoStackInOneArray { + private Object[] data = new Object[10]; + private int pos1 = -1; + private int pos2 = data.length; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + _ensureCapacityEnough(); + data[++pos1] = o; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if (pos1 < 0) return null; + return data[pos1--]; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + if (pos1 < 0) return null; + return data[pos1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + _ensureCapacityEnough(); + data[--pos2] = o; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (pos2 >= data.length) return null; + return data[pos2++]; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + if (pos2 >= data.length) return null; + return data[pos2]; + } + + private void _ensureCapacityEnough() { + if (pos1 + 1 == pos2) { + _dilatancy(); + } + } + + private void _dilatancy() { + Object[] temp = new Object[data.length * 2]; + for (int i = 0; i <= pos1; i++) { + temp[i] = data[i]; + } + + for (int i = pos2; i < data.length; i++) { + temp[temp.length - (data.length - i)] = data[i]; + } + + pos2 = temp.length - (data.length - pos2); + data = temp; + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixExpr.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixExpr.java new file mode 100644 index 0000000000..01240f90d0 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixExpr.java @@ -0,0 +1,73 @@ +package com.aaront.exercise.basic.expr; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +public class InfixExpr { + private String expr = null; + private Map map = new HashMap<>(4); + + public InfixExpr(String expr) { + this.expr = expr; + this.map.put('+', 1); + this.map.put('-', 1); + this.map.put('*', 2); + this.map.put('/', 2); + this.map.put('#', 0); + } + + public float evaluate() { + Stack operands = new Stack<>(); + // 要保证操作符栈中的操作符是按照操作符优先级递增的(不能相等) + Stack operators = new Stack<>(); + operators.push('#'); + for (int i = 0, len = expr.length(); i < len; i++) { + char c = expr.charAt(i); + Integer level = map.get(c); + if (c == '+' || c == '-' || c == '*' || c == '/') { + Character operator = operators.peek(); + Integer value = map.get(operator); + while (level <= value) { + Double operand2 = operands.pop(); + Double operand1 = operands.pop(); + Double result = calc(operators.pop(), operand1, operand2); + operands.push(result); + operator = operators.peek(); + value = map.get(operator); + } + + operators.push(c); + } else { + int j = i; + for (; j < len && expr.charAt(j) >= '0' && expr.charAt(j) <= '9'; j++) ; + operands.push(Double.parseDouble(expr.substring(i, j))); + i = j - 1; + } + } + + while (operators.size() != 1) { + Double operand2 = operands.pop(); + Double operand1 = operands.pop(); + Double result = calc(operators.pop(), operand1, operand2); + operands.push(result); + } + + return operands.pop().floatValue(); + } + + private Double calc(Character operator, Double operand1, Double operand2) { + switch (operator) { + case '+': + return operand1 + operand2; + case '-': + return operand1 - operand2; + case '*': + return operand1 * operand2; + case '/': + return operand1 / operand2; + default: + throw new IllegalArgumentException("不支持的运算符"); + } + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixToPostfix.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixToPostfix.java new file mode 100644 index 0000000000..f42212fddc --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/InfixToPostfix.java @@ -0,0 +1,35 @@ +package com.aaront.exercise.basic.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + List reversePolish = new ArrayList<>(); + Stack stack = new Stack<>(); + for (int i = 0; i < tokens.size(); i++) { + Token token = tokens.get(i); + if (token.isNumber()) reversePolish.add(token); + else { + if(stack.isEmpty()) stack.push(token); + else { + Token topToken = stack.peek(); + while (!token.hasHigherPriority(topToken)) { + reversePolish.add(stack.pop()); + if(stack.isEmpty()) break; + topToken = stack.peek(); + } + stack.push(token); + } + } + } + while (!stack.isEmpty()) { + reversePolish.add(stack.pop()); + } + return reversePolish; + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PostfixExpr.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PostfixExpr.java new file mode 100644 index 0000000000..7c51086b98 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PostfixExpr.java @@ -0,0 +1,51 @@ +package com.aaront.exercise.basic.expr; + +import java.util.ArrayList; +import java.util.List; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List elements = toList(expr.split(" ")); + for (int i = 0; i < elements.size(); i++) { + String element = elements.get(i); + if (element.equals("+") || element.equals("-") || element.equals("*") || element.equals("/")) { + Double result = calc(element, Double.valueOf(elements.get(i - 2)), Double.valueOf(elements.get(i - 1))); + elements.add(i - 2, result.toString()); + for (int j = 0; j < 3; j++) { + elements.remove(i - 1); + } + i = -1; + } + } + return Float.valueOf(elements.get(0)); + } + + private List toList(String[] elements) { + List list = new ArrayList<>(elements.length); + for (int i = 0; i < elements.length; i++) { + list.add(elements[i]); + } + return list; + } + + private Double calc(String operator, Double operand1, Double operand2) { + switch (operator) { + case "+": + return operand1 + operand2; + case "-": + return operand1 - operand2; + case "*": + return operand1 * operand2; + case "/": + return operand1 / operand2; + default: + throw new IllegalArgumentException("不支持的运算符"); + } + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PrefixExpr.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PrefixExpr.java new file mode 100644 index 0000000000..137fdb9c4f --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/PrefixExpr.java @@ -0,0 +1,53 @@ +package com.aaront.exercise.basic.expr; + +import java.util.ArrayList; +import java.util.List; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List elements = toList(expr.split(" ")); + for (int i = elements.size() - 1; i >= 0; i++) { + String element = elements.get(i); + if (element.equals("+") || element.equals("-") || element.equals("*") || element.equals("/")) { + Double result = calc(element, Double.valueOf(elements.get(i + 1)), Double.valueOf(elements.get(i + 2))); + elements.add(i, result.toString()); + for (int j = 0; j < 3; j++) { + elements.remove(i + 1); + } + i = elements.size() - 2; + } + } + return Float.valueOf(elements.get(0)); + } + + private List toList(String[] elements) { + List list = new ArrayList<>(elements.length); + for (int i = 0; i < elements.length; i++) { + list.add(elements[i]); + } + return list; + } + + private Double calc(String operator, Double operand1, Double operand2) { + switch (operator) { + case "+": + return operand1 + operand2; + case "-": + return operand1 - operand2; + case "*": + return operand1 * operand2; + case "/": + return operand1 / operand2; + default: + throw new IllegalArgumentException("不支持的运算符"); + } + } + + +} diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/Token.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/Token.java new file mode 100644 index 0000000000..4e7fc095d0 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/Token.java @@ -0,0 +1,47 @@ +package com.aaront.exercise.basic.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; + 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/TokenParser.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/TokenParser.java new file mode 100644 index 0000000000..f03ecbe19f --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/basic/expr/TokenParser.java @@ -0,0 +1,55 @@ +package com.aaront.exercise.basic.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/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/BinaryTreeUtil.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/BinaryTreeUtil.java new file mode 100644 index 0000000000..b46b122dbd --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/BinaryTreeUtil.java @@ -0,0 +1,66 @@ +package com.aaront.exercise.generic; + +import java.util.Arrays; +import java.util.List; + +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static > List preOrderVisit(GenericBinaryTree root) { + T[] result = root.traversal(GenericBinaryTree.PREORDER, (T[]) new Integer[0]); + return Arrays.asList(result); + } + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static > List inOrderVisit(GenericBinaryTree root) { + T[] result = root.traversal(GenericBinaryTree.INORDER, (T[]) new Integer[0]); + return Arrays.asList(result); + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static > List postOrderVisit(GenericBinaryTree root) { + T[] result = root.traversal(GenericBinaryTree.POSTORDER, (T[]) new Integer[0]); + return Arrays.asList(result); + } + + /** + * 用非递归的方式实现对二叉树的前序遍历 + * + * @param root + * @return + */ + public static > List preOrderWithoutRecursion(GenericBinaryTree root) { + + List result = root.traversalWithoutRecursion(GenericBinaryTree.PREORDER); + + return result; + } + + /** + * 用非递归的方式实现对二叉树的中序遍历 + * + * @param root + * @return + */ + public static > List inOrderWithoutRecursion(GenericBinaryTree root) { + + List result = root.traversalWithoutRecursion(GenericBinaryTree.INORDER); + + return result; + } + +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/CircleQueue.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/CircleQueue.java new file mode 100644 index 0000000000..13d3470b62 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/CircleQueue.java @@ -0,0 +1,41 @@ +package com.aaront.exercise.generic; + +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return front == rear; + } + + public boolean isFull() { + if(rear == elementData.length && front == 0) return true; + return front == rear + 1; + } + + public int size() { + if(rear < front) return elementData.length - front + rear; + return rear - front; + } + + public void enQueue(E data) { + if (isFull()) return; + if(rear == elementData.length) rear = 0; + elementData[rear++] = data; + } + + public E deQueue() { + if (isEmpty()) return null; + if(front == elementData.length) front = 0; + Object element = elementData[front++]; + return (E) element; + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/GenericBinaryTree.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/GenericBinaryTree.java index e5cf3b439a..ef689f1c54 100644 --- a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/GenericBinaryTree.java +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/GenericBinaryTree.java @@ -1,6 +1,9 @@ package com.aaront.exercise.generic; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.Stack; public class GenericBinaryTree> { @@ -176,6 +179,77 @@ public Object[] traversal(int order) { return datas; } + public List traversalWithoutRecursion(int order) { + if (order == PREORDER) { + return preorderWithoutRecursion(root); + } else if (order == INORDER) { + return inorderWithoutRecursion(root); + } else if (order == POSTORDER) { + return postorderWithoutRecursion(root); + } else { + return hierarchicalTraversalWithoutRecursion(root); + } + } + + private List preorderWithoutRecursion(BinaryTreeNode root) { + List nodes = new ArrayList<>(); + Stack> stack = new Stack<>(); + while (root != null) { + nodes.add(root.getData()); + if (root.getRight() != null) { + stack.push(root.getRight()); + } + if (root.getLeft() != null) { + root = root.getLeft(); + } else { + if (stack.isEmpty()) break; + root = stack.pop(); + } + } + + return nodes; + } + + private List inorderWithoutRecursion(BinaryTreeNode root) { + List nodes = new ArrayList<>(); + Stack> stack = new Stack<>(); + while (root != null || !stack.isEmpty()) { + while (root != null) { + stack.push(root); + root = root.getLeft(); + } + BinaryTreeNode node = stack.pop(); + nodes.add(node.getData()); + root = node.getRight(); + } + return nodes; + } + + private List postorderWithoutRecursion(BinaryTreeNode root) { + List nodes = new ArrayList<>(); + Stack> stack = new Stack<>(); + stack.push(root); + BinaryTreeNode pre = null; + BinaryTreeNode cur = null; + while (!stack.isEmpty()) { + cur = stack.peek(); + // 如果当前节点是叶子节点 || 当前节点的左右节点都已经被访问过了, 则可以直接访问当前节点 + if (cur.getLeft() == null && cur.getRight() == null || pre != null && (cur.getLeft() == pre || cur.getRight() == pre)) { + nodes.add(cur.getData()); + stack.pop(); + pre = cur; + } else { + if (cur.getRight() != null) stack.push(cur.getRight()); + if (cur.getLeft() != null) stack.push(cur.getLeft()); + } + } + return nodes; + } + + private List hierarchicalTraversalWithoutRecursion(BinaryTreeNode root) { + return new ArrayList<>(); + } + private void preorderTraversal(BinaryTreeNode node, Object[] datas) { if (node == null) { return; @@ -211,7 +285,7 @@ private void hierarchicalTraversal(BinaryTreeNode node, Object[] datas) { GenericQueue> queue = new GenericQueue<>(); queue.enQueue(node); while (!queue.isEmpty()) { - BinaryTreeNode tmp = queue.deQueue(); + BinaryTreeNode tmp = queue.deQueue(); datas[index++] = tmp.getData(); if (tmp.getLeft() != null) queue.enQueue(tmp.getLeft()); if (tmp.getRight() != null) queue.enQueue(tmp.getRight()); diff --git a/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/QueueWithTwoStacks.java b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/QueueWithTwoStacks.java new file mode 100644 index 0000000000..b07bb5dc3e --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/main/java/com/aaront/exercise/generic/QueueWithTwoStacks.java @@ -0,0 +1,42 @@ +package com.aaront.exercise.generic; + +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.empty(); + } + + + public int size() { + return stack1.size() + stack2.size(); + } + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) return null; + if (stack2.isEmpty()) _copy(); + return stack2.pop(); + } + + private void _copy() { + while (!stack1.isEmpty()) { + E element = stack1.pop(); + stack2.push(element); + } + } + +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/FileListTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/FileListTest.java new file mode 100644 index 0000000000..0743437140 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/FileListTest.java @@ -0,0 +1,20 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.FileList; +import org.junit.Test; + +import java.io.File; + +/** + * @author tonyhui + * @since 17/5/8 + */ +public class FileListTest { + + @Test + public void testList() { + FileList list = new FileList(); + File file = new File("/Users/tonyhui/Code/coding2017/group01/954958168"); + list.list(file, 0); + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/JosephusTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/JosephusTest.java new file mode 100644 index 0000000000..92cc66e7d3 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/JosephusTest.java @@ -0,0 +1,24 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.Josephus; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + } + +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/QuickMinStackTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/QuickMinStackTest.java new file mode 100644 index 0000000000..f0f2dc5621 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/QuickMinStackTest.java @@ -0,0 +1,48 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.QuickMinStack; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class QuickMinStackTest { + + @Test + public void test() { + QuickMinStack stack = new QuickMinStack(); + stack.push(5); + stack.push(-5); + stack.push(50); + stack.push(23); + stack.push(0); + stack.push(100); + + assertEquals(-5, stack.findMin()); + assertEquals(6, stack.size()); + + assertEquals(100, stack.pop()); + assertEquals(-5, stack.findMin()); + + stack.push(-4); + assertEquals(-5, stack.findMin()); + + assertEquals(-4, stack.pop()); + assertEquals(-5, stack.findMin()); + + assertEquals(0, stack.pop()); + assertEquals(-5, stack.findMin()); + + assertEquals(23, stack.pop()); + assertEquals(-5, stack.findMin()); + + assertEquals(50, stack.pop()); + assertEquals(-5, stack.findMin()); + + assertEquals(-5, stack.pop()); + assertEquals(5, stack.findMin()); + + assertEquals(5, stack.pop()); + + assertEquals(0, stack.size()); + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackUtilTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackUtilTest.java new file mode 100644 index 0000000000..ab055f2b22 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackUtilTest.java @@ -0,0 +1,66 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.StackUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Stack; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackWithTwoQueuesTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..5ca48c0fbb --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/StackWithTwoQueuesTest.java @@ -0,0 +1,27 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.StackWithTwoQueues; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class StackWithTwoQueuesTest { + + @Test + public void test() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + for (int i = 0; i < 500; i++) { + stack.push(i); + } + for (int i = 0; i < 500; i++) { + assertEquals(500 - i - 1, stack.pop()); + } + + stack.push(50); + stack.push(60); + assertEquals(60, stack.pop()); + stack.push(70); + assertEquals(70, stack.pop()); + assertEquals(50, stack.pop()); + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/TwoStackInOneArrayTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..7d50c53bd8 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/TwoStackInOneArrayTest.java @@ -0,0 +1,43 @@ +package com.aaront.execrise.basic; + +import com.aaront.exercise.basic.TwoStackInOneArray; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class TwoStackInOneArrayTest { + + @Test + public void test() { + TwoStackInOneArray stack = new TwoStackInOneArray(); + for (int i = 0; i < 50; i++) { + stack.push1("stack1:" + i); + } + for (int i = 0; i < 50; i++) { + stack.push2("stack2:" + i); + } + + for (int i = 0; i < 50; i++) { + assertEquals("stack1:" + (50 - i - 1), stack.peek1()); + assertEquals("stack1:" + (50 - i - 1), stack.pop1()); + } + for (int i = 0; i < 50; i++) { + assertEquals("stack2:" + (50 - i - 1), stack.peek2()); + assertEquals("stack2:" + (50 - i - 1), stack.pop2()); + } + + stack.push1(50); + stack.push1(60); + assertEquals(60, stack.pop1()); + stack.push1(70); + assertEquals(70, stack.pop1()); + assertEquals(50, stack.pop1()); + + stack.push2(50); + stack.push2(60); + assertEquals(60, stack.pop2()); + stack.push2(70); + assertEquals(70, stack.pop2()); + assertEquals(50, stack.pop2()); + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixExprTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixExprTest.java new file mode 100644 index 0000000000..ed30a0e82a --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixExprTest.java @@ -0,0 +1,53 @@ +package com.aaront.execrise.basic.expr; + +import com.aaront.exercise.basic.expr.InfixExpr; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixToPostfixTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..94e1aec62d --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/InfixToPostfixTest.java @@ -0,0 +1,38 @@ +package com.aaront.execrise.basic.expr; + +import com.aaront.exercise.basic.expr.InfixToPostfix; +import com.aaront.exercise.basic.expr.PostfixExpr; +import com.aaront.exercise.basic.expr.Token; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class InfixToPostfixTest { + + @Test + public void testConvert() { + { + String expr = "10-2*3+50"; + + List postFix = InfixToPostfix.convert(expr); + String postFixExpr = tokenListToString(postFix); + float postFixExprResult = calculatePostFixExpr(postFixExpr); + + Assert.assertEquals(54, postFixExprResult, 0.001); + } + } + + private String tokenListToString(List tokenList) { + StringBuilder builder = new StringBuilder(); + for (Token token : tokenList) { + builder.append(token + " "); + } + return builder.toString(); + } + + private float calculatePostFixExpr(String expr) { + PostfixExpr postfixExpr = new PostfixExpr(expr); + return postfixExpr.evaluate(); + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PostfixExprTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PostfixExprTest.java new file mode 100644 index 0000000000..0d4ecb3052 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PostfixExprTest.java @@ -0,0 +1,42 @@ +package com.aaront.execrise.basic.expr; + + + +import com.aaront.exercise.basic.expr.PostfixExpr; +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/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PrefixExprTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PrefixExprTest.java new file mode 100644 index 0000000000..502ea71a64 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/PrefixExprTest.java @@ -0,0 +1,46 @@ +package com.aaront.execrise.basic.expr; + +import com.aaront.exercise.basic.expr.PrefixExpr; +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/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/TokenParserTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/TokenParserTest.java new file mode 100644 index 0000000000..11cd06d370 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/basic/expr/TokenParserTest.java @@ -0,0 +1,40 @@ +package com.aaront.execrise.basic.expr; + +import com.aaront.exercise.basic.expr.Token; +import com.aaront.exercise.basic.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/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/BinaryTreeUtilTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..2b0271f229 --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/BinaryTreeUtilTest.java @@ -0,0 +1,68 @@ +package com.aaront.execrise.generic; + +import com.aaront.exercise.generic.BinaryTreeUtil; +import com.aaront.exercise.generic.GenericBinaryTree; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + + +public class BinaryTreeUtilTest { + + GenericBinaryTree root = null; + + @Before + public void setUp() throws Exception { + root = new GenericBinaryTree<>(); + root.add(1); + root.add(2); + root.add(5); + root.add(3); + root.add(4); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 5, 3, 4]", result.toString()); + } + + @Test + public void testInOrderVisit() { + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + } + + @Test + public void testPostOrderVisit() { + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[4, 3, 5, 2, 1]", result.toString()); + } + + + @Test + public void testInOrderVisitWithoutRecursion() { + root.add(6); + root.add(7); + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 5, 6, 7]", result.toString()); + + } + + @Test + public void testPreOrderVisitWithoutRecursion() { + root.add(6); + root.add(7); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 5, 3, 4, 6, 7]", result.toString()); + + } +} \ No newline at end of file diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/CircleQueueTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/CircleQueueTest.java new file mode 100644 index 0000000000..66ff17ed3b --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/CircleQueueTest.java @@ -0,0 +1,43 @@ +package com.aaront.execrise.generic; + +import com.aaront.exercise.generic.CircleQueue; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author tonyhui + * @since 17/5/6 + */ +public class CircleQueueTest { + + @Test + public void test() { + CircleQueue circleQueue = new CircleQueue<>(); + for (int i = 0; i < 10; i++) { + circleQueue.enQueue("circleQueue" + i); + } + Assert.assertEquals(10, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 0; i < 5; i++) { + Assert.assertEquals("circleQueue" + i, circleQueue.deQueue()); + } + Assert.assertEquals(5, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 5; i < 10; i++) { + Assert.assertEquals("circleQueue" + i, circleQueue.deQueue()); + } + Assert.assertEquals(0, circleQueue.size()); + Assert.assertTrue(circleQueue.isEmpty()); + + for (int i = 0; i < 6; i++) { + circleQueue.enQueue("item" + i); + } + Assert.assertEquals(6, circleQueue.size()); + Assert.assertFalse(circleQueue.isEmpty()); + for (int i = 0; i < 6; i++) { + Assert.assertEquals("item" + i, circleQueue.deQueue()); + } + Assert.assertEquals(0, circleQueue.size()); + Assert.assertTrue(circleQueue.isEmpty()); + } +} diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/GenericBinaryTreeTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/GenericBinaryTreeTest.java index 6c39ab07e7..97947a385c 100644 --- a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/GenericBinaryTreeTest.java +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/GenericBinaryTreeTest.java @@ -5,6 +5,9 @@ import org.junit.Before; import org.junit.Test; +import java.util.Arrays; +import java.util.List; + /** * @author tonyhui * @since 17/2/20 @@ -27,6 +30,12 @@ public void testAdd() { for (String data : datas) { binaryTree.add(data); } + List preorderWithoutRecursionDatas = binaryTree.traversalWithoutRecursion(GenericBinaryTree.PREORDER); + Assert.assertEquals(Arrays.asList(new String[]{"9", "4", "1", "2", "10", "17", "3", "5", "7", "9" }), preorderWithoutRecursionDatas); + List inorderWithoutRecursionDatas = binaryTree.traversalWithoutRecursion(GenericBinaryTree.INORDER); + Assert.assertEquals(Arrays.asList(new String[]{"1", "10", "17", "2", "3", "4", "5", "7", "9", "9" }), inorderWithoutRecursionDatas); + List postorderWithoutRecursionDatas = binaryTree.traversalWithoutRecursion(GenericBinaryTree.POSTORDER); + Assert.assertEquals(Arrays.asList(new String[]{"17", "10", "3", "2", "1", "7", "5", "4", "9", "9" }), postorderWithoutRecursionDatas); String[] preorderDatas = binaryTree.traversal(GenericBinaryTree.PREORDER, new String[0]); Assert.assertArrayEquals(new String[]{"9", "4", "1", "2", "10", "17", "3", "5", "7", "9" }, preorderDatas); String[] inorderDatas = binaryTree.traversal(GenericBinaryTree.INORDER, new String[0]); diff --git a/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/QueueWithTwoStacksTest.java b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..f3154fd56f --- /dev/null +++ b/group01/954958168/class01/BasicDataStructure/src/test/java/com/aaront/execrise/generic/QueueWithTwoStacksTest.java @@ -0,0 +1,28 @@ +package com.aaront.execrise.generic; + +import com.aaront.exercise.generic.QueueWithTwoStacks; +import org.junit.Assert; +import org.junit.Test; + +public class QueueWithTwoStacksTest { + + @Test + public void test() { + QueueWithTwoStacks queue = new QueueWithTwoStacks<>(); + Assert.assertNull(queue.deQueue()); + Assert.assertTrue(queue.isEmpty()); + for (int i = 0; i < 100; i++) { + queue.enQueue("item" + i); + } + for (int i = 0; i < 50; i++) { + Assert.assertEquals("item" + i, queue.deQueue()); + } + queue.enQueue("item100"); + queue.enQueue("item101"); + Assert.assertEquals(52, queue.size()); + int i = 50; + while (!queue.isEmpty()) { + Assert.assertEquals("item" + i++, queue.deQueue()); + } + } +} \ No newline at end of file diff --git a/group03/345943980/download-0335/pom.xml b/group03/345943980/download-0335/pom.xml index b62ba3fec1..5193da926b 100644 --- a/group03/345943980/download-0335/pom.xml +++ b/group03/345943980/download-0335/pom.xml @@ -28,8 +28,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/group03/345943980/mini-jvm-0330/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group03/345943980/mini-jvm-0330/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..17abd10b7e --- /dev/null +++ b/group03/345943980/mini-jvm-0330/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,68 @@ +package com.coderising.jvm.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + className = className.replace(".", File.separator) + ".class"; + for (String path : clzPaths) { + String clzFileName = path + File.separator + className; + byte[] codes = this.loadClassFile(clzFileName); + if (codes != null) { + return codes; + } + } + return null; + } + + private byte[] loadClassFile(String clzFileName){ + try { + return IOUtils.toByteArray(new FileInputStream(clzFileName)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + public void addClassPath(String path) { + clzPaths.add(path); + } + + public String getClassPath() { + return StringUtils.join(clzPaths, ";"); + } + + public String getClassPath_V1() { + StringBuffer sb = new StringBuffer(); + /* + * for (int i = 0; i < clzPaths.size(); i++) + { + if (i == clzPaths.size() - 1) { + sb.append(clzPaths.get(i)); + break; + } + sb.append(clzPaths.get(i)); + sb.append(";"); + * + * } + */ + for (int i = 0; i < clzPaths.size(); i++) { + sb.append(clzPaths.get(i)); + if (i < clzPaths.size() - 1) { + sb.append(";"); + } + } + return sb.toString(); + } + +} diff --git a/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/CmLRUPageFrame.java b/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/CmLRUPageFrame.java new file mode 100644 index 0000000000..890db81fb5 --- /dev/null +++ b/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/CmLRUPageFrame.java @@ -0,0 +1,69 @@ +package com.coding.basic.linklist; + +/** + * + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年4月10日 上午12:35:03 + */ +public class CmLRUPageFrame { + + private static class Node { + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private Node first;// 链表头 + private Node last;// 链表尾 + + public CmLRUPageFrame(int capacity) { + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param pageNum + */ + public void access(int pageNum) { + Node node = first; + Node foundNode = null; + while(node!=null){ + if(node.pageNum==pageNum){ + foundNode = node; + } + node = node.next; + } + + //在该队列中存在, 则提到队列头 + if(foundNode!=null){ + + }else{ + + } + + + + } + + @Override + 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/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/LRUPageFrame.java b/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..3dba1b554b --- /dev/null +++ b/group03/345943980/mini-jvm-0330/src/main/java/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,163 @@ +package com.coding.basic.linklist; + + +/** + * 实现一个简单的LRU算法,即是 Least Recently Used 近期最少使用算法 + * 作用:需要维护一个页面中的栈,并且需要把某一个页面从栈中提到栈顶,用硬件实现的话,开销比较大,注意:实际上并不是一个真正的栈 + * @author Administrator + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + Node node = find(pageNum); + //在该队列中存在, 则提到队列头 + if (node != null) { + + moveExistingNodeToHead(node); + + } else{ + + node = new Node(); + node.pageNum = pageNum; + + // 缓存容器是否已经超过大小. + if (currentSize >= capacity) { + removeLast(); + + } + + addNewNodetoHead(node); + + + + + } + } + + private void addNewNodetoHead(Node node) { + + if(isEmpty()){ + + node.prev = null; + node.next = null; + first = node; + last = node; + + } else{ + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + this.currentSize ++; + } + + private Node find(int data){ + + Node node = first; + while(node != null){ + if(node.pageNum == data){ + return node; + } + node = node.next; + } + return null; + + } + + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize --; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + * + * @param node + */ + private void moveExistingNodeToHead(Node node) { + + if (node == first) { + + return; + } + else if(node == last){ + //当前节点是链表尾, 需要放到链表头 + Node prevNode = node.prev; + prevNode.next = null; + last.prev = null; + last = prevNode; + + } else{ + //node 在链表的中间, 把node 的前后节点连接起来 + Node prevNode = node.prev; + prevNode.next = node.next; + + Node nextNode = node.next; + nextNode.prev = prevNode; + + + } + + node.prev = null; + node.next = first; + first.prev = node; + first = node; + + } + private boolean isEmpty(){ + return (first == null) && (last == null); + } + + 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/group03/345943980/mini-jvm-0330/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java b/group03/345943980/mini-jvm-0330/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..cf4108c0d9 --- /dev/null +++ b/group03/345943980/mini-jvm-0330/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,87 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class ClassFileloaderTest { + + + static String path1 = "E:\\github\\coding2017\\group03\\345943980\\mini-jvm-0330\\target\\test-classes"; + static String path2 = "D:\\wordtest"; + + @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 = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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 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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ff9d5fb77 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..0feffa65b5 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..dcac7f97c4 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fa90d110fe --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/StringInfo.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d01065fd53 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/UTF8Info.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..b7407d146f --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..2dff6746da --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + +} diff --git a/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..b9d2a3ba0c --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,131 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + +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 s) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack<>(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + /** + * QQ号为:247565311的解法 + * @param s + */ + public static void reverse_247565311(Stack s){ + if(s == null || s.isEmpty()) { + return; + } + + int size = s.size(); + Stack tmpStack = new Stack(); + + for(int i=0;ii){ + tmpStack.push(s.pop()); + } + s.push(top); + while(tmpStack.size()>0){ + s.push(tmpStack.pop()); + } + } + } + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + + Stack tmp = new Stack(); + while(!s.isEmpty()){ + tmp.push(s.pop()); + } + while(!tmp.isEmpty()){ + Integer top = tmp.pop(); + addToBottom(s,top); + } + + + } + public static void addToBottom(Stack s, Integer value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Integer top = s.pop(); + addToBottom(s,value); + s.push(top); + } + + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + + while(!s.isEmpty()){ + Object value = s.pop(); + if(!value.equals(o)){ + tmpStack.push(value); + } + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static Object[] getTop(Stack s,int len) { + + if(s == null || s.isEmpty() || s.size() tmpStack = new Stack<>(); + int i = 0; + Object[] result = new Object[len]; + while(!s.isEmpty()){ + Object value = s.pop(); + tmpStack.push(value); + result[i++] = value; + if(i == len){ + break; + } + } + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + return result; + } + /** + * 字符串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 stack = new Stack<>(); + 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()); + } + + + +} diff --git a/group03/345943980/mini-jvm-0405/src/test/java/com/coderising/jvm/test/EmployeeV1.java b/group03/345943980/mini-jvm-0405/src/test/java/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..9a36573dd3 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/test/java/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group03/345943980/mini-jvm-0405/src/test/java/com/coding/basic/stack/StackUtilTest.java b/group03/345943980/mini-jvm-0405/src/test/java/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..6c8db075d0 --- /dev/null +++ b/group03/345943980/mini-jvm-0405/src/test/java/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,77 @@ +package com.coding.basic.stack; + +import java.util.Stack; + +import org.junit.Assert; +import org.junit.Test; +public class StackUtilTest { + + @Test + public void testAddToBottom() { + + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.addToBottom(s, 0); + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + + @Test + public void testReverse() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testReverse_247565311() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + + Assert.assertEquals("[1, 2, 3]", s.toString()); + StackUtil.reverse_247565311(s); + Assert.assertEquals("[3, 2, 1]", s.toString()); + } + @Test + public void testRemove() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/InfixExpr.java b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..498aeb3e59 --- /dev/null +++ b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,74 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 用两个栈实现中序表达式求值 + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年5月7日 下午4:17:24 + */ +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + + } + opStack.push(token); + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); + } + + + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/Token.java b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..72720b0da1 --- /dev/null +++ b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,48 @@ +package com.coding.basic.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; + 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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; + } +} diff --git a/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/TokenParser.java b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d1b586bce0 --- /dev/null +++ b/group03/345943980/mini-jvm-0409/src/main/java/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,45 @@ +package com.coding.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/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java b/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..1d1913e0ad --- /dev/null +++ b/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,38 @@ +package com.coding.basic.stack.expr; + +import org.junit.Assert; +import org.junit.Test; + +public class InfixExprTest { + @Test + public void testEvaluate() { + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } +} diff --git a/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/TokenParserTest.java b/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..b8bbd6bb5f --- /dev/null +++ b/group03/345943980/mini-jvm-0409/src/test/java/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class TokenParserTest { + @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/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/InfixToPostfix.java b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..ca21f19849 --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,35 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * 中序表达式转后缀表达式 + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年5月7日 下午4:29:06 + */ +public class InfixToPostfix { + + public static List convert(String expr) { + List inFixTokens = new TokenParser().parse(expr); + List postFixTokens = new ArrayList<>(); + Stack opStack = new Stack(); + for(Token token : inFixTokens){ + if(token.isOperator()){ + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + postFixTokens.add(opStack.pop()); + } + opStack.push(token); + } + if(token.isNumber()){ + postFixTokens.add(token); + } + } + while(!opStack.isEmpty()){ + postFixTokens.add(opStack.pop()); + } + return postFixTokens; + } +} diff --git a/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PostfixExpr.java b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..f656ee91bc --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,49 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 用栈实现后缀表达式 + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年5月7日 下午4:42:26 + */ +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack numStack = new Stack<>(); + for(Token token : tokens){ + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } else{ + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(),f1,f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PrefixExpr.java b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..a9541c9006 --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,58 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +/** + * 用两个栈实现前缀表达式 + * + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年5月7日 下午4:46:49 + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (Token token : tokens) { + exprStack.push(token); + } + + while (!exprStack.isEmpty()) { + Token t = exprStack.pop(); + if (t.isNumber()) { + numStack.push(new Float(t.getIntValue())); + } else { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(), f1, f2)); + + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/Token.java b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..72720b0da1 --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,48 @@ +package com.coding.basic.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; + 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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; + } +} diff --git a/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/TokenParser.java b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d1b586bce0 --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/main/java/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,45 @@ +package com.coding.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/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/InfixToPostfixTest.java b/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..b3e2f97837 --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,26 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class InfixToPostfixTest { + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } +} diff --git a/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/PostfixExprTest.java b/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..3f1729b16e --- /dev/null +++ b/group03/345943980/mini-jvm-0416/src/test/java/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,26 @@ +package com.coding.basic.stack.expr; + +import org.junit.Assert; +import org.junit.Test; + +public class PostfixExprTest { + + @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/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/CircleQueue.java b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..da6bf9fd58 --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,49 @@ +package com.coding.basic.queue; + +public class CircleQueue { + + // 用数组来保存循环队列的元素 + private Object[] elementData; + int size = 0; + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public CircleQueue(int capacity) { + elementData = new Object[capacity]; + } + + public boolean isEmpty() { + return front == rear; + + } + + public boolean isFull() { + return size == elementData.length; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + if (isFull()) { + throw new RuntimeException("The queue is full"); + } + elementData[rear++] = data; + size++; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("The queue is empty"); + } + E data = (E) elementData[front]; + elementData[front] = null; + front = (front + 1) % elementData.length; + size--; + return data; + } +} diff --git a/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Josephus.java b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..1c0c4bcce0 --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Josephus.java @@ -0,0 +1,35 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author chenming E-mail:cm_20094020@163.com + * @version 创建时间:2017年5月7日 下午10:16:22 + * + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1),并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + */ +public class Josephus { + +public static List execute(int n, int m){ + + Queue queue = new Queue(); + for (int i = 0; i < n; i++){ + queue.enQueue(i); + } + List result = new ArrayList(); + int i = 0; + while (!queue.isEmpty()) { + int x = queue.deQueue(); + if (++i % m == 0){ + result.add(x); + } else{ + queue.enQueue(x); + } + } + return result; + } +} diff --git a/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Queue.java b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..5b1191d59e --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/Queue.java @@ -0,0 +1,55 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + + 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/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/QueueWithTwoStacks.java b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..8d25563420 --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/main/java/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,37 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; +import java.util.Stack; + +public class QueueWithTwoStacks { + + private Stack stack1; + private Stack stack2; + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + private void moveStack1ToStack2() { + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + public int size() { + return stack1.size() + stack2.size(); + } + public void enQueue(E item) { + stack1.push(item); + } + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + if (stack2.isEmpty()) { + moveStack1ToStack2(); + } + return stack2.pop(); + } +} diff --git a/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/CircleQueueTest.java b/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..87f976728e --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,31 @@ +package com.coding.basic.queue; + +import org.junit.Assert; +import org.junit.Test; + +public class CircleQueueTest { + + @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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } +} diff --git a/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/JosephusTest.java b/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..d2c0456a05 --- /dev/null +++ b/group03/345943980/mini-jvm-0423/src/test/java/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,12 @@ +package com.coding.basic.queue; + +import org.junit.Assert; +import org.junit.Test; + +public class JosephusTest { + + @Test + public void testExecute() { + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + } +} diff --git a/group03/569045298/pom.xml b/group03/569045298/pom.xml index c2a9dd870e..ee8af60326 100644 --- a/group03/569045298/pom.xml +++ b/group03/569045298/pom.xml @@ -10,11 +10,6 @@ http://maven.apache.org - - org.junit.jupiter - junit-jupiter-api - RELEASE - junit junit diff --git a/group03/569045298/src/main/com/coderising/array/ArrayUtil.java b/group03/569045298/src/main/com/coderising/array/ArrayUtil.java deleted file mode 100644 index 992e0652fb..0000000000 --- a/group03/569045298/src/main/com/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.coderising.array; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -public class ArrayUtil { - - /** - * 给定一个整形数组a , 对该数组的值进行置换 - * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] - * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - */ - public int[] reverseArray(int[] origin) { - for (int i = 0; i < origin.length / 2; i++) { - int temp = origin[i]; - origin[i] = origin[origin.length - i - 1]; - origin[origin.length - i - 1] = temp; - } - return origin; - } - - /** - * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: - * {1,3,4,5,6,6,5,4,7,6,7,5} - */ - public int[] removeZero(int[] oldArray) { - int[] newArray = new int[oldArray.length]; - int index = 0; - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] != 0) { - newArray[index] = oldArray[i]; - index++; - } - } - int[] result = new int[index]; - System.arraycopy(newArray, 0, result, 0, index); - return result; - } - - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 - * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - */ - public int[] merge(int[] array1, int[] array2) { - Set set = new TreeSet<>(); - for (int i = 0; i < array1.length; i++) { - set.add(array1[i]); - } - for (int i = 0; i < array2.length; i++) { - set.add(array2[i]); - } - return set2Array(set); - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - */ - public int[] grow(int[] oldArray, int size) { - int[] newArray = new int[oldArray.length + size]; - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); - return newArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - */ - public int[] fibonacci(int max) { - List list = new ArrayList<>(); - for (int i = 1; i < max; i++) { - int f = fibonacci2(i); - if (f >= max) { - break; - } else { - list.add(f); - } - } - return list2Array(list); - } - - public int fibonacci2(int n) { - if (n == 0) { - return 0; - } else if (n == 1) { - return 1; - } - return fibonacci2(n - 1) + fibonacci2(n - 2); - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - */ - public int[] getPrimes(int max) { - List list = new ArrayList<>(); - for (int i = 2; i < max; i++) { - if (isPrime(i)) { - list.add(i); - } - } - return list2Array(list); - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - */ - public int[] getPerfectNumbers(int max) { - List list = new ArrayList<>(); - for (int i = 1; i <= max; i++) { - int temp = 0; - for (int n = 1; n < i / 2 + 1; n++) { - if (i % n == 0) { - temp += n; - } - } - if (temp == i) { - list.add(i); - } - } - return list2Array(list); - } - - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" - */ - public String join(int[] array, String seperator) { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - if (i != 0) { - stringBuilder.append(seperator); - } - stringBuilder.append(array[i]); - } - return stringBuilder.toString(); - } - - private int[] list2Array(List list) { - int[] result = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - result[i] = list.get(i); - } - return result; - } - - private int[] set2Array(Set set) { - int[] result = new int[set.size()]; - Iterator iterator = set.iterator(); - int index = 0; - while (iterator.hasNext()) { - result[index++] = iterator.next(); - } - return result; - } - - private boolean isPrime(int num) { - for (int i = 2; i < num; i++) { - if (num % i == 0) { - return false; - } - } - return true; - } - -} diff --git a/group03/569045298/src/main/com/coderising/litestruts/LoginAction.java b/group03/569045298/src/main/com/coderising/litestruts/LoginAction.java index 3c3de8ba91..c64f51946b 100644 --- a/group03/569045298/src/main/com/coderising/litestruts/LoginAction.java +++ b/group03/569045298/src/main/com/coderising/litestruts/LoginAction.java @@ -1,47 +1,46 @@ -package com.coderising.litestruts; - -/** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * - */ -public class LoginAction { - - private String name; - - private String password; - - private String message; - - public String execute() { - if ("test".equals(name) && "1234".equals(password)) { - this.message = "login successful"; - return "success"; - } - this.message = "login failed,please check your user/pwd"; - return "fail"; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getMessage() { - return this.message; - } - - public void setMessage(String message) { - this.message = message; - } -} +package com.coderising.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + */ +public class LoginAction { + + private String name; + + private String password; + + private String message; + + public String execute() { + if ("test".equals(name) && "1234".equals(password)) { + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMessage() { + return this.message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/group03/569045298/src/main/com/coderising/litestruts/ReflectionUtil.java b/group03/569045298/src/main/com/coderising/litestruts/ReflectionUtil.java new file mode 100644 index 0000000000..cd58cc9ca9 --- /dev/null +++ b/group03/569045298/src/main/com/coderising/litestruts/ReflectionUtil.java @@ -0,0 +1,97 @@ +package com.coderising.litestruts; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by zt on 2017/3/11. + */ +public final class ReflectionUtil { + + public static Map getMethodsMap(Class clazz) { + Map methodMap = new HashMap<>(); + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + methodMap.put(method.getName(), method); + } + return methodMap; + } + + public static Map getMethodsByStartName(Class clazz, String startWithName) { + Map methodMap = new HashMap<>(); + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().startsWith(startWithName)) { + methodMap.put(method.getName(), method); + } + } + return methodMap; + } + + public static Map getGetterMethods(Class clazz) { + return getMethodsByStartName(clazz, "get"); + } + + public static Map getSetterMethods(Class clazz) { + return getMethodsByStartName(clazz, "set"); + } + + public static String getMethodName(String fieldName, String startWithName) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(startWithName); + stringBuilder.append(fieldName.substring(0, 1).toUpperCase()); + stringBuilder.append(fieldName.substring(1)); + return stringBuilder.toString(); + } + + public static String getGettterMethodName(String fieldName) { + return getMethodName(fieldName, "get"); + } + + public static String getSettterMethodName(String fieldName) { + return getMethodName(fieldName, "set"); + } + + public static void setParameters(Map parameters, Object object) { + try { + Map methodMap = getSetterMethods(object.getClass()); + for (Map.Entry entry : parameters.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + Method setterMethod = methodMap.get(getSettterMethodName(key)); + setterMethod.invoke(object, value); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + public static Map getParametersMap(Class clazz, Object newInstance) { + try { + Map map = new HashMap<>(); + Map methodMap = getMethodsMap(clazz); + Field[] fields = clazz.getDeclaredFields(); + if (fields != null && fields.length > 0) { + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + String fieldName = field.getName(); + Method getterMethod = methodMap.get(getGettterMethodName(fieldName)); + Object value = getterMethod.invoke(newInstance); + map.put(fieldName, value); + } + } + return map; + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/group03/569045298/src/main/com/coderising/litestruts/Struts.java b/group03/569045298/src/main/com/coderising/litestruts/Struts.java index 7ec84c9a2d..dff1df1d72 100644 --- a/group03/569045298/src/main/com/coderising/litestruts/Struts.java +++ b/group03/569045298/src/main/com/coderising/litestruts/Struts.java @@ -1,156 +1,111 @@ -package com.coderising.litestruts; - -import com.coderising.litestruts.StrutsBean.Action; -import com.coderising.litestruts.StrutsBean.Result; - -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * 模拟struts执行 - * 读取类似struts.xml文件,根据xml的定义创建相关的Action类来执行 - */ -public class Struts { - - private static final String FILE_PATH = "src/main/com/coderising/litestruts/struts.xml"; - - public View runAction(String actionName, Map parameters) { - // 视图 - View view = new View(); - // 读取配置文件struts.xml - Map actions = this.xmlToList(); - if (null == actions || actions.size() == 0) { - return null; - } - try { - // 根据actionName找到相对应的class - Action action = actions.get(actionName); - Class clazz = Class.forName(action.getClassName()); - // 通过反射实例化 - Object newInstance = clazz.newInstance(); - // 获得所有方法 - Map methodMap = new HashMap<>(); - Method[] methods = clazz.getDeclaredMethods(); - for (Method method : methods) { - methodMap.put(method.getName(), method); - } - // 根据parameters中的数据,调用对象的setter方法 - for (Map.Entry entry : parameters.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - Method setterMethod = methodMap.get(settterMethodName(key)); - setterMethod.invoke(newInstance, value); - } - // 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" - Method executeMethod = clazz.getMethod("execute"); - Object object = executeMethod.invoke(newInstance); - // 通过反射找到对象的所有getter方法 - Map map = new HashMap<>(); - Field[] fields = clazz.getDeclaredFields(); - if (fields != null && fields.length > 0) { - // 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - String fieldName = field.getName(); - Method getterMethod = methodMap.get(gettterMethodName(fieldName)); - Object value = getterMethod.invoke(newInstance); - map.put(fieldName, value); - } - } - // 放到View对象的parameters中 - view.setParameters(map); - // 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp,放到View对象的jsp字段中 - List resultList = action.getResult(); - for (Result result : resultList) { - if (result.getName().equals(object)) { - view.setJsp(result.getValue()); - } - } - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } - return view; - } - - private Map xmlToList() { - Map map = new HashMap<>(); - SAXReader saxReader = new SAXReader(); - Document document; - try { - document = saxReader.read(new File(FILE_PATH)); - Element rootElement = document.getRootElement(); - Iterator iterator = rootElement.elementIterator("action"); - while (iterator.hasNext()) { - Action action = new Action(); - List results = new ArrayList<>(); - action.setResult(results); - Element element = iterator.next(); - List attributes = element.attributes(); - for (Attribute attribute : attributes) { - String attributeName = attribute.getName(); - if (attributeName.equals("name")) { - action.setName(attribute.getStringValue()); - } else if (attributeName.equals("class")) { - action.setClassName(attribute.getStringValue()); - } - } - Iterator iterator1 = element.elementIterator(); - while (iterator1.hasNext()) { - Result result = new Result(); - Element element1 = iterator1.next(); - List attributes1 = element1.attributes(); - for (Attribute attribute : attributes1) { - String attributeName = attribute.getName(); - if (attributeName.equals("name")) { - result.setName(attribute.getStringValue()); - } - } - result.setValue(element1.getStringValue()); - results.add(result); - } - map.put(action.getName(), action); - } - } catch (DocumentException e) { - e.printStackTrace(); - } - return map; - } - - private String gettterMethodName(String fieldName) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("get"); - stringBuilder.append(fieldName.substring(0, 1).toUpperCase()); - stringBuilder.append(fieldName.substring(1)); - return stringBuilder.toString(); - } - - private String settterMethodName(String fieldName) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("set"); - stringBuilder.append(fieldName.substring(0, 1).toUpperCase()); - stringBuilder.append(fieldName.substring(1)); - return stringBuilder.toString(); - } - -} +package com.coderising.litestruts; + +import com.coderising.litestruts.StrutsBean.Action; +import com.coderising.litestruts.StrutsBean.Result; + +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * 模拟struts执行 + * 读取类似struts.xml文件,根据xml的定义创建相关的Action类来执行 + */ +public class Struts { + + private static final String FILE_PATH = "src/main/com/coderising/litestruts/struts.xml"; + + public View runAction(String actionName, Map parameters) { + // 读取配置文件struts.xml + Map configuration = this.parseXML(); + if (null == configuration || configuration.size() == 0) { + return null; + } + try { + Action actions = configuration.get(actionName); + Class clazz = Class.forName(actions.getClassName()); + Object action = clazz.newInstance(); + ReflectionUtil.setParameters(parameters, action); + Method executeMethod = clazz.getMethod("execute"); + Object object = executeMethod.invoke(action); + Map map = ReflectionUtil.getParametersMap(clazz, action); + View view = new View(); + view.setParameters(map); + // 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp,放到View对象的jsp字段中 + List resultList = actions.getResult(); + for (Result result : resultList) { + if (result.getName().equals(object)) { + view.setJsp(result.getValue()); + } + } + return view; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } + return null; + } + + private Map parseXML() { + Map map = new HashMap<>(); + SAXReader saxReader = new SAXReader(); + Document document; + try { + document = saxReader.read(new File(FILE_PATH)); + Element rootElement = document.getRootElement(); + Iterator iterator = rootElement.elementIterator("action"); + while (iterator.hasNext()) { + Action action = new Action(); + List results = new ArrayList<>(); + action.setResult(results); + Element element = iterator.next(); + List attributes = element.attributes(); + for (Attribute attribute : attributes) { + String attributeName = attribute.getName(); + if (attributeName.equals("name")) { + action.setName(attribute.getStringValue()); + } else if (attributeName.equals("class")) { + action.setClassName(attribute.getStringValue()); + } + } + Iterator iterator1 = element.elementIterator(); + while (iterator1.hasNext()) { + Result result = new Result(); + Element element1 = iterator1.next(); + List attributes1 = element1.attributes(); + for (Attribute attribute : attributes1) { + String attributeName = attribute.getName(); + if (attributeName.equals("name")) { + result.setName(attribute.getStringValue()); + } + } + result.setValue(element1.getStringValue()); + results.add(result); + } + map.put(action.getName(), action); + } + } catch (DocumentException e) { + e.printStackTrace(); + } + return map; + } + +} diff --git a/group03/569045298/src/main/com/coderising/litestruts/View.java b/group03/569045298/src/main/com/coderising/litestruts/View.java index 258285e4f3..45c0b5e741 100644 --- a/group03/569045298/src/main/com/coderising/litestruts/View.java +++ b/group03/569045298/src/main/com/coderising/litestruts/View.java @@ -1,28 +1,28 @@ -package com.coderising.litestruts; - -import java.util.Map; - -public class View { - - private String jsp; - - private Map parameters; - - public String getJsp() { - return jsp; - } - - public View setJsp(String jsp) { - this.jsp = jsp; - return this; - } - - public Map getParameters() { - return parameters; - } - - public View setParameters(Map parameters) { - this.parameters = parameters; - return this; - } -} +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + + private String jsp; + + private Map parameters; + + public String getJsp() { + return jsp; + } + + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + + public Map getParameters() { + return parameters; + } + + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group03/569045298/src/main/com/coderising/litestruts/struts.xml b/group03/569045298/src/main/com/coderising/litestruts/struts.xml index 561e9693c1..f82a752b96 100644 --- a/group03/569045298/src/main/com/coderising/litestruts/struts.xml +++ b/group03/569045298/src/main/com/coderising/litestruts/struts.xml @@ -1,14 +1,14 @@ - - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - - /jsp/welcome.jsp - /jsp/error.jsp - - + + + + + /jsp/homepage.jsp + /jsp/showLogin.jsp + + + + /jsp/welcome.jsp + /jsp/error.jsp + + \ No newline at end of file diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/ArrayList.java b/group03/569045298/src/main/com/coding/basic/datastructure/ArrayList.java deleted file mode 100644 index 8d3de85e34..0000000000 --- a/group03/569045298/src/main/com/coding/basic/datastructure/ArrayList.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.coding.basic.datastructure; - - -/** - * Created by zt on 2017/2/19. - */ -public class ArrayList implements List { - - private static final int DEFAULT_CAPACITY = 10; - private int size = 0; - private Object[] elementData = null; - - public ArrayList() { - elementData = new Object[DEFAULT_CAPACITY]; - } - - public ArrayList(int initialCapacity) { - if (initialCapacity < 0) { - throw new RuntimeException("initialCapacity is smaller than zero"); - } - elementData = new Object[initialCapacity]; - } - - @Override - public void add(Object o) { - checkCapacity(size + 1); - elementData[size] = o; - size++; - } - - @Override - public void add(int index, Object o) { - checkCapacity(size + 1); - System.arraycopy(elementData, index, elementData, index + 1, size - index); - elementData[index] = o; - size++; - } - - @Override - public Object get(int index) { - checkRange(index); - return elementData[index]; - } - - @Override - public Object remove(int index) { - Object removedObject = elementData[index]; - System.arraycopy(elementData, index + 1, elementData, index, elementData.length - index - 1); - elementData[--size] = null; - return removedObject; - } - - @Override - public int size() { - return size; - } - - private void checkRange(int index) { - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException(); - } - } - - private void checkCapacity(int size) { - if (size > elementData.length) { - int newLength = elementData.length * 2; - Object[] newObject = new Object[newLength]; - System.arraycopy(elementData, 0, newObject, 0, elementData.length); - elementData = newObject; - } - } - - public Iterator iterator() { - return new ArrayListIterator(this); - } - - private class ArrayListIterator implements Iterator { - - private ArrayList arrayList = null; - private int position = 0; - - private ArrayListIterator(ArrayList arrayList) { - this.arrayList = arrayList; - } - - @Override - public boolean hasNext() { - return position < size(); - } - - @Override - public Object next() { - return get(position++); - } - - @Override - public Object remove() { - // TODO - return this.arrayList.remove(position--); - } - } -} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/LinkedList.java b/group03/569045298/src/main/com/coding/basic/datastructure/LinkedList.java deleted file mode 100644 index 0f4ac3231b..0000000000 --- a/group03/569045298/src/main/com/coding/basic/datastructure/LinkedList.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.coding.basic.datastructure; - -/** - * Created by zt on 2017/2/19. - */ -public class LinkedList implements List { - - private Node head; - - private Node tail; - - private int size = 0; - - public LinkedList() { - - } - - @Override - public void add(Object object) { - if (null == head) { - head = new Node(object); - head.next = null; - tail = head; - size++; - } else { - // 尾插法 - Node newNode = new Node(object); - tail.next = newNode; - tail = newNode; - tail.next = null; - size++; - } - } - - @Override - public void add(int index, Object object) { - checkRange(index); - if (null == head) { - add(object); - return; - } - if (index == 0) { - addFirst(object); - return; - } - Node pre = node(index - 1); - Node newNode = new Node(object); - newNode.next = pre.next; - pre.next = newNode; - size++; - } - - @Override - public Object get(int index) { - checkRange(index); - checkNodeNotNull(); - Node node = node(index); - return node.data; - } - - @Override - public Object remove(int index) { - checkRange(index); - checkNodeNotNull(); - Object object; - if (index == 0) { - object = removeFirst(); - return object; - } - Node pre = node(index - 1); - object = pre.next.data; - pre.next = pre.next.next; - size--; - return object; - } - - @Override - public int size() { - return size; - } - - public void addFirst(Object object) { - if (null == head) { - head = new Node(object); - head.next = null; - size++; - } else { - Node firstNode = new Node(object); - firstNode.next = head; - head = firstNode; - size++; - } - } - - public Object removeFirst() { - checkNodeNotNull(); - Object oldValue = head.data; - head = head.next; - size--; - return oldValue; - } - - public Object removeLast() { - checkNodeNotNull(); - Object oldValue; - if (size == 1) { - oldValue = head.data; - head = null; - return oldValue; - } - Node pre = node(size() - 2); - oldValue = pre.next.data; - pre.next = null; - size--; - return oldValue; - } - - private void checkRange(int index) { - if (index > size - 1 || index < 0) { - throw new IndexOutOfBoundsException(); - } - } - - private void checkNodeNotNull() { - if (null == head) { - throw new NullPointerException(); - } - } - - private Node node(int index) { - Node node = head; - for (int i = 0; i < index; i++) { - node = node.next; - } - return node; - } - - private static class Node { - Node next; - private Object data; - - public Node() { - - } - - public Node(Object data) { - this.data = data; - } - - public Node(Object data, Node next) { - this.data = data; - this.next = next; - } - - public Node(Object data, Node next, Node prev) { - this.data = data; - this.next = next; - } - } - - /*@Override - public void add(Object object) { - if (null == head) { - head = new Node(object); - head.next = null; - } else { - // 头插法 - Node nextNode = new Node(object); - nextNode.next = head.next; - head.next = nextNode; - } - }*/ - -} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/Queue.java b/group03/569045298/src/main/com/coding/basic/datastructure/Queue.java index d3d4ebfbab..f78de06510 100644 --- a/group03/569045298/src/main/com/coding/basic/datastructure/Queue.java +++ b/group03/569045298/src/main/com/coding/basic/datastructure/Queue.java @@ -1,6 +1,8 @@ package com.coding.basic.datastructure; +import com.coding.basic.datastructure.array.ArrayList; + /** * Created by zt on 2017/2/19. */ diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/Stack.java b/group03/569045298/src/main/com/coding/basic/datastructure/Stack.java deleted file mode 100644 index c8dbc6b3af..0000000000 --- a/group03/569045298/src/main/com/coding/basic/datastructure/Stack.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.coding.basic.datastructure; - -/** - * Created by zt on 2017/2/19. - */ -public class Stack { - - private ArrayList elementData = null; - - private int size = 0; - - public Stack() { - elementData = new ArrayList(); - } - - public void push(Object object) { - elementData.add(object); - size++; - } - - public Object pop() { - checkIsEmpty(); - Object peekObject = peek(); - elementData.remove(size - 1); - size--; - return peekObject; - } - - public Object peek() { - checkIsEmpty(); - return elementData.get(size - 1); - } - - private void checkIsEmpty() { - if (isEmpty()) { - throw new RuntimeException("stack is empty"); - } - } - - public boolean isEmpty() { - return size() == 0; - } - - public int size() { - return size; - } -} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayList.java b/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayList.java new file mode 100644 index 0000000000..b66481012b --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayList.java @@ -0,0 +1,105 @@ +package com.coding.basic.datastructure.array; + + +import com.coding.basic.datastructure.Iterator; +import com.coding.basic.datastructure.List; + +/** + * Created by zt on 2017/2/19. + */ +public class ArrayList implements List { + + private static final int DEFAULT_CAPACITY = 10; + private int size = 0; + private Object[] elementData = null; + + public ArrayList() { + elementData = new Object[DEFAULT_CAPACITY]; + } + + public ArrayList(int initialCapacity) { + if (initialCapacity < 0) { + throw new RuntimeException("initialCapacity is smaller than zero"); + } + elementData = new Object[initialCapacity]; + } + + @Override + public void add(Object o) { + checkCapacity(size + 1); + elementData[size] = o; + size++; + } + + @Override + public void add(int index, Object o) { + checkCapacity(size + 1); + System.arraycopy(elementData, index, elementData, index + 1, size - index); + elementData[index] = o; + size++; + } + + @Override + public Object get(int index) { + checkRange(index); + return elementData[index]; + } + + @Override + public Object remove(int index) { + Object removedObject = elementData[index]; + System.arraycopy(elementData, index + 1, elementData, index, elementData.length - index - 1); + elementData[--size] = null; + return removedObject; + } + + @Override + public int size() { + return size; + } + + private void checkRange(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(); + } + } + + private void checkCapacity(int size) { + if (size > elementData.length) { + int newLength = elementData.length * 2; + Object[] newObject = new Object[newLength]; + System.arraycopy(elementData, 0, newObject, 0, elementData.length); + elementData = newObject; + } + } + + public Iterator iterator() { + return new ArrayListIterator(this); + } + + private class ArrayListIterator implements Iterator { + + private ArrayList arrayList = null; + private int position = 0; + + private ArrayListIterator(ArrayList arrayList) { + this.arrayList = arrayList; + } + + @Override + public boolean hasNext() { + return position < size(); + } + + @Override + public Object next() { + return get(position++); + } + + @Override + public Object remove() { + // TODO + return this.arrayList.remove(position--); + } + } +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayUtil.java b/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayUtil.java new file mode 100644 index 0000000000..fa5057fbe8 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/array/ArrayUtil.java @@ -0,0 +1,194 @@ +package com.coding.basic.datastructure.array; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + */ + public int[] reverseArray(int[] origin) { + if (origin == null) { + return null; + } + for (int i = 0; i < origin.length / 2; i++) { + int temp = origin[i]; + origin[i] = origin[origin.length - i - 1]; + origin[origin.length - i - 1] = temp; + } + return origin; + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + */ + public int[] removeZero(int[] oldArray) { + if (oldArray == null) { + return null; + } + int[] newArray = new int[oldArray.length]; + int index = 0; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + newArray[index++] = oldArray[i]; + } + } + return Arrays.copyOf(newArray, index); + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + */ + public int[] merge(int[] array1, int[] array2) { + if (array1 == null && array2 == null) { + return null; + } + if (array1 == null || array2 == null) { + return array1 == null ? array2 : array1; + } + Set set = new TreeSet<>(); + for (int i = 0; i < array1.length; i++) { + set.add(array1[i]); + } + for (int i = 0; i < array2.length; i++) { + set.add(array2[i]); + } + return set2Array(set); + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + */ + public int[] grow(int[] oldArray, int size) { + if (oldArray == null) { + return null; + } + if (size < 0) { + throw new IndexOutOfBoundsException(); + } + int[] newArray = new int[oldArray.length + size]; + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); + return newArray; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + */ + public int[] fibonacci(int max) { + List list = new ArrayList<>(); + for (int i = 0; i < max; i++) { + int f = fibonacci2(i); + if (f < max) { + list.add(f); + } else { + break; + } + } + return list2Array(list); + } + + public int fibonacci2(int n) { + if (n == 0) { + return 0; + } else if (n == 1) { + return 1; + } + return fibonacci2(n - 1) + fibonacci2(n - 2); + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + */ + public int[] getPrimes(int max) { + List list = new ArrayList<>(); + for (int i = 2; i < max; i++) { + if (isPrime(i)) { + list.add(i); + } + } + return list2Array(list); + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + */ + public int[] getPerfectNumbers(int max) { + List list = new ArrayList<>(); + for (int i = 1; i <= max; i++) { + int temp = 0; + for (int n = 1; n < i / 2 + 1; n++) { + if (i % n == 0) { + temp += n; + } + } + if (temp == i) { + list.add(i); + } + } + return list2Array(list); + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + */ + public String join(int[] array, String seperator) { + if (array == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + if (i != 0) { + stringBuilder.append(seperator); + } + stringBuilder.append(array[i]); + } + return stringBuilder.toString(); + } + + private int[] list2Array(List list) { + int[] result = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + result[i] = list.get(i); + } + return result; + } + + private int[] set2Array(Set set) { + int[] result = new int[set.size()]; + Iterator iterator = set.iterator(); + int index = 0; + while (iterator.hasNext()) { + result[index++] = iterator.next(); + } + return result; + } + + private boolean isPrime(int num) { + for (int i = 2; i < num; i++) { + if (num % i == 0) { + return false; + } + } + return true; + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LRUPageFrame.java b/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..e43767aaf5 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LRUPageFrame.java @@ -0,0 +1,106 @@ +package com.coding.basic.datastructure.linklist; + +/** + * 用双向链表实现LRU算法 + * + * @author zt + */ +public class LRUPageFrame { + + private int capacity; + private Node first; + private Node last; + private int size = 0; + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + */ + public void access(int pageNum) { + if (first == null) { + first = new Node(); + first.pageNum = pageNum; + last = first; + size++; + } else { + if (size < capacity) { + linkFirst(pageNum); + size++; + } else { + Node p = first; + int count = 0; + while (p != null) { + if (p.pageNum == pageNum) { + if (p == first) { + break; + } else if (p == last) { + last = p.prev; + p.prev.next = null; + linkNodeToFirst(p); + } else { + p.next.prev = p.prev; + p.prev.next = p.next; + linkNodeToFirst(p); + } + break; + } + p = p.next; + count++; + } + // if doesn't contains the same value + if (count >= size) { + linkFirst(pageNum); + removeLast(); + } + } + } + } + + private void linkNodeToFirst(Node p) { + first.prev = p; + p.next = first; + p.prev = null; + first = p; + } + + private void linkFirst(int pageNum) { + Node node = new Node(); + node.pageNum = pageNum; + first.prev = node; + node.next = first; + first = node; + } + + private void removeLast() { + last = last.prev; + last.next = null; + } + + @Override + 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(); + } + + private static class Node { + Node prev; + Node next; + int pageNum; + + Node() { + + } + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LinkedList.java b/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LinkedList.java new file mode 100644 index 0000000000..f4d83f6c9c --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/linklist/LinkedList.java @@ -0,0 +1,321 @@ +package com.coding.basic.datastructure.linklist; + +import com.coding.basic.datastructure.Iterator; +import com.coding.basic.datastructure.List; + +/** + * Created by zt on 2017/2/19. + */ +public class LinkedList implements List { + + private Node head; + + private Node tail; + + private int size = 0; + + public LinkedList() { + + } + + @Override + public void add(Object object) { + if (null == head) { + head = new Node(object); + head.next = null; + tail = head; + size++; + } else { + // 尾插法 + Node newNode = new Node(object); + tail.next = newNode; + tail = newNode; + tail.next = null; + size++; + } + } + + /*@Override + public void add(Object object) { + if (null == head) { + head = new Node(object); + head.next = null; + } else { + // 头插法 + Node nextNode = new Node(object); + nextNode.next = head.next; + head.next = nextNode; + } + }*/ + + @Override + public void add(int index, Object object) { + checkRange(index); + if (null == head) { + add(object); + return; + } + if (index == 0) { + addFirst(object); + return; + } + Node pre = node(index - 1); + Node newNode = new Node(object); + newNode.next = pre.next; + pre.next = newNode; + size++; + } + + @Override + public Object get(int index) { + checkRange(index); + checkNodeNotNull(); + Node node = node(index); + return node.data; + } + + @Override + public Object remove(int index) { + checkRange(index); + checkNodeNotNull(); + Object object; + if (index == 0) { + object = removeFirst(); + return object; + } + Node pre = node(index - 1); + object = pre.next.data; + pre.next = pre.next.next; + size--; + return object; + } + + @Override + public int size() { + return size; + } + + public void addFirst(Object object) { + if (null == head) { + head = new Node(object); + head.next = null; + size++; + } else { + Node firstNode = new Node(object); + firstNode.next = head; + head = firstNode; + size++; + } + } + + public Object removeFirst() { + checkNodeNotNull(); + Object oldValue = head.data; + head = head.next; + size--; + return oldValue; + } + + public Object removeLast() { + checkNodeNotNull(); + Object oldValue; + if (size == 1) { + oldValue = head.data; + head = null; + return oldValue; + } + Node pre = node(size() - 2); + oldValue = pre.next.data; + pre.next = null; + size--; + return oldValue; + } + + private void checkRange(int index) { + if (index > size - 1 || index < 0) { + throw new IndexOutOfBoundsException(); + } + } + + private void checkNodeNotNull() { + if (null == head) { + throw new NullPointerException(); + } + } + + private Node node(int index) { + checkRange(index); + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node; + } + + public Iterator iterator() { + return new LinkedList.LinkedListIterator(); + } + + public void reverse() { + checkNodeNotNull(); + + Node temp = head.next; + // 指向原head位置,基准节点 + Node pivot = head; + while (pivot.next != null) { + Node p = temp.next; + temp.next = head; + pivot.next = p; + head = temp; + temp = p; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + for (int i = 1; i <= size / 2; i++) { + removeFirst(); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + */ + public void remove(int i, int length) { + if (i == 0) { + for (int j = 0; j < length; j++) { + head = head.next; + size--; + } + } else { + Node pre = node(i - 1); + for (int j = 0; j < length; j++) { + pre.next = pre.next.next; + size--; + } + } + } + + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + */ + public int[] getElements(LinkedList list) { + if (list == null) { + return null; + } + int[] result = new int[list.size()]; + Iterator iterator = list.iterator(); + int index = (int) iterator.next(); + int currentIndex = 0; + int arrayIndex = 0; + Node p = head; + while (p != null) { + if (index == currentIndex) { + result[arrayIndex++] = (int) p.data; + if (iterator.hasNext()) { + index = (int) iterator.next(); + } else { + return result; + } + } + currentIndex++; + p = p.next; + } + return null; + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + Node p = head; + while (p.next != null) { + if (p.data.equals(p.next.data)) { + p.next = p.next.next; + size--; + } else { + p = p.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + */ + public void removeRange(int min, int max) { + if (min > max) { + throw new RuntimeException("min is larger than max!"); + } + int start = 0; + int end = 0; + Node node = head; + while (node != null) { + int data = (int) node.data; + if (data <= min) { + start++; + end++; + } else if (data < max) { + end++; + } + node = node.next; + } + this.remove(start, end - start); + } + + private static class Node { + Node next; + private Object data; + + public Node() { + + } + + public Node(Object data) { + this.data = data; + } + + public Node(Object data, Node next) { + this.data = data; + this.next = next; + } + + public Node(Object data, Node next, Node prev) { + this.data = data; + this.next = next; + } + } + + private class LinkedListIterator implements Iterator { + + private Node cursor = head; + + @Override + public boolean hasNext() { + return cursor != null; + } + + @Override + public Object next() { + Object data = cursor.data; + cursor = cursor.next; + return data; + } + + @Override + public Object remove() { + // TODO + return null; + } + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/QuickMinStack.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/QuickMinStack.java new file mode 100644 index 0000000000..da697ae4b6 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/QuickMinStack.java @@ -0,0 +1,41 @@ +package com.coding.basic.datastructure.stack; + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回该数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + */ +public class QuickMinStack { + + private Stack stack; + private Stack minStack; + + public QuickMinStack() { + stack = new Stack<>(); + minStack = new Stack<>(); + } + + public void push(E data) { + stack.push(data); + if (minStack.isEmpty()) { + minStack.push(data); + } else { + if (minStack.peek().compareTo(data) >= 0) { + minStack.push(data); + } + } + } + + public E pop() { + E top = stack.pop(); + if (top.compareTo(minStack.peek()) <= 0) { + minStack.pop(); + } + return top; + } + + public E findMin() { + return minStack.peek(); + } +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/Stack.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/Stack.java new file mode 100644 index 0000000000..7bd0326872 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/Stack.java @@ -0,0 +1,49 @@ +package com.coding.basic.datastructure.stack; + +import com.coding.basic.datastructure.array.ArrayList; + +/** + * Created by zt on 2017/2/19. + */ +public class Stack { + + private ArrayList elementData = null; + + private int size = 0; + + public Stack() { + elementData = new ArrayList(); + } + + public void push(Object object) { + elementData.add(object); + size++; + } + + public Object pop() { + checkIsEmpty(); + Object peekObject = peek(); + elementData.remove(size - 1); + size--; + return peekObject; + } + + public Object peek() { + checkIsEmpty(); + return elementData.get(size - 1); + } + + private void checkIsEmpty() { + if (isEmpty()) { + throw new RuntimeException("stack is empty"); + } + } + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return size; + } +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackUtil.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackUtil.java new file mode 100644 index 0000000000..fb8e2aca2c --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackUtil.java @@ -0,0 +1,127 @@ +package com.coding.basic.datastructure.stack; + +import java.util.Stack; + +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty + */ + public static void reverse(Stack s) { + if (s == null || s.isEmpty()) { + return; + } + Integer top = s.pop(); + reverse(s); + addToBottom(s, top); + } + + public static void addToBottom(Stack s, Integer value) { + if (s.isEmpty()) { + s.push(value); + } else { + Integer top = s.pop(); + addToBottom(s, value); + s.push(top); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty + */ + public static void remove(Stack s, Object object) { + if (s == null || s.isEmpty()) { + return; + } + Stack temp = new Stack(); + while (!s.isEmpty()) { + Object top = s.pop(); + if (null == object && top != null) { + temp.push(top); + } + if (null != object && !object.equals(top)) { + temp.push(top); + } + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty + */ + public static Object[] getTop(Stack s, int len) { + if (len < 0) { + throw new RuntimeException("length should be larger than zero!"); + } + if (len > s.size()) { + throw new RuntimeException("length is bigger than stack size!"); + } + if (s == null || s.isEmpty()) { + return null; + } + Stack temp = new Stack(); + int count = 0; + while (!s.isEmpty() && count++ <= len) { + temp.push(s.pop()); + } + Object[] result = new Object[temp.size()]; + int index = result.length - 1; + while (!temp.isEmpty()) { + Object top = temp.pop(); + result[index--] = top; + s.push(top); + } + return result; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + */ + public static boolean isValidPairs(String s) { + Stack stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + switch (ch) { + case '(': + stack.push(ch); + break; + case ')': + if (!stack.isEmpty() && stack.peek() == '(') { + stack.pop(); + } else { + return false; + } + break; + case '[': + stack.push(ch); + break; + case ']': + if (!stack.isEmpty() && stack.peek() == '[') { + stack.pop(); + } else { + return false; + } + break; + case '{': + stack.push(ch); + break; + case '}': + if (!stack.isEmpty() && stack.peek() == '{') { + stack.pop(); + } else { + return false; + } + break; + } + } + return stack.isEmpty(); + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackWithTwoQueues.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..d86f161583 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/StackWithTwoQueues.java @@ -0,0 +1,54 @@ +package com.coding.basic.datastructure.stack; + + +import java.util.ArrayDeque; +import java.util.Queue; + +public class StackWithTwoQueues { + + private Queue firstQueue; + private Queue secondQueue; + + public StackWithTwoQueues() { + firstQueue = new ArrayDeque<>(); + secondQueue = new ArrayDeque<>(); + } + + public void push(E data) { + if (firstQueue.isEmpty() && secondQueue.isEmpty()) { + firstQueue.add(data); + return; + } + if (!firstQueue.isEmpty()) { + firstQueue.add(data); + return; + } + if (!secondQueue.isEmpty()) { + secondQueue.add(data); + return; + } + } + + public E pop() { + E data = null; + if (!firstQueue.isEmpty()) { + data = this.pop(firstQueue, secondQueue); + } else if (!secondQueue.isEmpty()) { + data = this.pop(secondQueue, firstQueue); + } + return data; + } + + private E pop(Queue fromQueue, Queue toQueue) { + E data = null; + while (fromQueue.size() > 0) { + if (fromQueue.size() == 1) { + data = fromQueue.poll(); + } else { + toQueue.add(fromQueue.poll()); + } + } + return data; + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/TwoStackInOneArray.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..27ff79d345 --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/TwoStackInOneArray.java @@ -0,0 +1,86 @@ +package com.coding.basic.datastructure.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + */ +public class TwoStackInOneArray { + + private static final int DEFAULT_CAPACITY = 10; + private Object[] data; + private int firstIndex; + private int lastIndex; + + public TwoStackInOneArray() { + this(DEFAULT_CAPACITY); + } + + public TwoStackInOneArray(int size) { + data = new Object[size]; + firstIndex = -1; + lastIndex = size; + } + + /** + * 向第一个栈中压入元素 + */ + public void push1(Object o) { + this.checkPosition(); + data[++firstIndex] = o; + } + + /** + * 从第一个栈中弹出元素 + */ + public Object pop1() { + return data[firstIndex--]; + } + + /** + * 获取第一个栈的栈顶元素 + */ + + public Object peek1() { + return data[firstIndex]; + } + + /** + * 向第二个栈压入元素 + */ + public void push2(Object o) { + this.checkPosition(); + data[--lastIndex] = o; + } + + /** + * 从第二个栈弹出元素 + */ + public Object pop2() { + return data[lastIndex++]; + } + + /** + * 获取第二个栈的栈顶元素 + */ + + public Object peek2() { + return data[lastIndex]; + } + + private void checkPosition() { + if (firstIndex + 1 == lastIndex) { + this.grow(); + } + } + + private void grow() { + Object[] newArray = new Object[data.length << 1]; + System.arraycopy(data, 0, newArray, 0, firstIndex + 1); + int secondStackSize = data.length - lastIndex; + int newLastIndex = newArray.length - secondStackSize; + System.arraycopy(data, lastIndex, newArray, newLastIndex, secondStackSize); + lastIndex = newLastIndex; + data = newArray; + } + +} diff --git a/group03/569045298/src/main/com/coding/basic/datastructure/stack/expr/InfixExpression.java b/group03/569045298/src/main/com/coding/basic/datastructure/stack/expr/InfixExpression.java new file mode 100644 index 0000000000..0cbabb008d --- /dev/null +++ b/group03/569045298/src/main/com/coding/basic/datastructure/stack/expr/InfixExpression.java @@ -0,0 +1,15 @@ +package com.coding.basic.datastructure.stack.expr; + +public class InfixExpression { + + private String expression; + + public InfixExpression(String expression) { + this.expression = expression; + } + + public float evaluate() { + return 0.0f; + } + +} diff --git a/group03/569045298/src/test/coderising/array/ArrayUtilTest.java b/group03/569045298/src/test/coderising/array/ArrayUtilTest.java index 52638781aa..4ed521a45c 100644 --- a/group03/569045298/src/test/coderising/array/ArrayUtilTest.java +++ b/group03/569045298/src/test/coderising/array/ArrayUtilTest.java @@ -1,6 +1,7 @@ package coderising.array; -import com.coderising.array.ArrayUtil; + +import com.coding.basic.datastructure.array.ArrayUtil; import org.junit.Assert; import org.junit.Before; @@ -38,10 +39,10 @@ public void testRemoveZero() { @Test public void testFibonacci() { int max = 1; - int[] expected = {}; + int[] expected = {0}; Assert.assertArrayEquals(expected, arrayUtil.fibonacci(max)); int max2 = 15; - int[] expected2 = {1, 1, 2, 3, 5, 8, 13}; + int[] expected2 = {0, 1, 1, 2, 3, 5, 8, 13}; Assert.assertArrayEquals(expected2, arrayUtil.fibonacci(max2)); } @@ -62,7 +63,7 @@ public void testMerge() { @Test public void testGetPerfectNumbers() { - int max = 6; + int max = 1000; arrayUtil.getPerfectNumbers(max); } diff --git a/group03/569045298/src/test/coderising/litestruts/StrutsTest.java b/group03/569045298/src/test/coderising/litestruts/StrutsTest.java index 61c25c3648..4b66733e72 100644 --- a/group03/569045298/src/test/coderising/litestruts/StrutsTest.java +++ b/group03/569045298/src/test/coderising/litestruts/StrutsTest.java @@ -1,46 +1,46 @@ -package coderising.litestruts; - -import com.coderising.litestruts.Struts; -import com.coderising.litestruts.View; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - - -public class StrutsTest { - - private Struts struts; - - @Before - public void setUp() { - struts = new Struts(); - } - - @Test - public void testLoginActionSuccess() { - String actionName = "login"; - Map params = new HashMap<>(); - params.put("name", "test"); - params.put("password", "1234"); - View view = struts.runAction(actionName, params); - Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); - Assert.assertEquals("login successful", view.getParameters().get("message")); - } - - @Test - public void testLoginActionFailed() { - String actionName = "login"; - Map params = new HashMap<>(); - params.put("name", "test"); - // 密码和预设的不一致 - params.put("password", "123456"); - View view = struts.runAction(actionName, params); - Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); - Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); - } - -} +package coderising.litestruts; + +import com.coderising.litestruts.Struts; +import com.coderising.litestruts.View; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + +public class StrutsTest { + + private Struts struts; + + @Before + public void setUp() { + struts = new Struts(); + } + + @Test + public void testLoginActionSuccess() { + String actionName = "login"; + Map params = new HashMap<>(); + params.put("name", "test"); + params.put("password", "1234"); + View view = struts.runAction(actionName, params); + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap<>(); + params.put("name", "test"); + // 密码和预设的不一致 + params.put("password", "123456"); + View view = struts.runAction(actionName, params); + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } + +} diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/TestDataStructure.java b/group03/569045298/src/test/com/coding/basic/datastructure/TestDataStructure.java index 9f90242595..834b5c566f 100644 --- a/group03/569045298/src/test/com/coding/basic/datastructure/TestDataStructure.java +++ b/group03/569045298/src/test/com/coding/basic/datastructure/TestDataStructure.java @@ -1,5 +1,9 @@ package com.coding.basic.datastructure; +import com.coding.basic.datastructure.array.ArrayList; +import com.coding.basic.datastructure.linklist.LinkedList; +import com.coding.basic.datastructure.stack.Stack; + import org.junit.Test; /** @@ -8,7 +12,7 @@ public class TestDataStructure { @Test - public void testLinedList() { + public void testLinkedList() { LinkedList list = new LinkedList(); for (int i = 0; i < 5; i++) { list.add(i); @@ -63,4 +67,105 @@ public void testArrayList() { System.out.println(arrayList.get(i)); } } + + @Test + public void testReverseLinkedList() { + LinkedList linkedList = new LinkedList(); + for (int i = 0; i < 10; i++) { + linkedList.add(i); + } + linkedList.reverse(); + printLinkedList(linkedList); + } + + @Test + public void testRemoveLinkedList() { + LinkedList linkedList = new LinkedList(); + for (int i = 0; i < 10; i++) { + linkedList.add(i); + } + linkedList.remove(0, 8); + printLinkedList(linkedList); + } + + @Test + public void testRemoveFirstHalf() { + LinkedList linkedList = new LinkedList(); + for (int i = 0; i < 1; i++) { + linkedList.add(i); + } + linkedList.removeFirstHalf(); + printLinkedList(linkedList); + } + + @Test + public void testRemoveDuplicateValues() { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(2); + linkedList.add(2); + linkedList.add(3); + linkedList.add(3); + linkedList.add(4); + linkedList.add(4); + linkedList.removeDuplicateValues(); + printLinkedList(linkedList); + } + + @Test + public void testLinkedListIterator() { + LinkedList linkedList = new LinkedList(); + for (int i = 0; i < 10; i++) { + linkedList.add(i); + } + Iterator iterator = linkedList.iterator(); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } + + @Test + public void testGetElements() { + LinkedList linkedList = new LinkedList(); + linkedList.add(11); + linkedList.add(101); + linkedList.add(201); + linkedList.add(301); + linkedList.add(401); + linkedList.add(501); + linkedList.add(601); + linkedList.add(701); + + LinkedList indexList = new LinkedList(); + indexList.add(0); + indexList.add(3); + indexList.add(4); + indexList.add(6); + + int[] result = linkedList.getElements(indexList); + for (int i = 0; i < result.length; i++) { + System.out.println(result[i]); + } + } + + @Test + public void testRemoveRange() { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(3); + linkedList.add(4); + linkedList.add(6); + linkedList.add(6); + linkedList.removeRange(1, 4); + printLinkedList(linkedList); + } + + private void printLinkedList(LinkedList linkedList) { + for (int i = 0; i < linkedList.size(); i++) { + System.out.print(linkedList.get(i) + ","); + } + } } diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/linklist/LRUPageFrameTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..5dbdf98f4e --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/linklist/LRUPageFrameTest.java @@ -0,0 +1,32 @@ +package com.coding.basic.datastructure.linklist; + +import org.junit.Assert; +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(3); + Assert.assertEquals("3,4,0", frame.toString()); + } + +} diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/stack/QuickMinStackTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..dff8f05b6f --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/stack/QuickMinStackTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.datastructure.stack; + +import org.junit.Assert; +import org.junit.Test; + + +/** + * Created by zt + * 2017/5/6 16:16 + */ +public class QuickMinStackTest { + + @Test + public void findMin() throws Exception { + QuickMinStack stack = new QuickMinStack<>(); + stack.push(9); + stack.push(2); + stack.push(3); + stack.push(2); + stack.push(7); + stack.push(0); + stack.push(1); + Assert.assertEquals(new Integer(0), stack.findMin()); + stack.pop(); + Assert.assertEquals(new Integer(0), stack.findMin()); + stack.pop(); + Assert.assertEquals(new Integer(2), stack.findMin()); + stack.pop(); + Assert.assertEquals(new Integer(2), stack.findMin()); + stack.push(-1); + Assert.assertEquals(new Integer(-1), stack.findMin()); + } + +} \ No newline at end of file diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackUtilTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackUtilTest.java new file mode 100644 index 0000000000..ded9c203c2 --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackUtilTest.java @@ -0,0 +1,83 @@ +package com.coding.basic.datastructure.stack; + + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Stack; + +public class StackUtilTest { + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + s.push(null); + Assert.assertEquals("[1, 2, 3, 4, 5, null]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[null, 5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 3); + Assert.assertEquals("[1, 2]", s.toString()); + s = new Stack(); + s.push(1); + StackUtil.remove(s, 2); + Assert.assertEquals("[1]", s.toString()); + s = new Stack(); + s.push(1); + StackUtil.remove(s, 1); + Assert.assertEquals("[]", s.toString()); + s = new Stack(); + s.push(1); + s.push(null); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, null, 3]", s.toString()); + s = new Stack(); + s.push(1); + s.push(null); + s.push(2); + s.push(3); + StackUtil.remove(s, null); + Assert.assertEquals("[1, 2, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(null); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 4); + Assert.assertEquals("[1, 2, null, 3, 4, 5]", s.toString()); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + Assert.assertEquals(null, values[3]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + Assert.assertFalse(StackUtil.isValidPairs("}])")); + } + +} diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackWithTwoQueuesTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..c81a4c98cd --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.datastructure.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by zt + * 2017/5/6 18:48 + */ +public class StackWithTwoQueuesTest { + + @Test + public void pop() { + StackWithTwoQueues stackWithTwoQueues = new StackWithTwoQueues<>(); + stackWithTwoQueues.push(1); + stackWithTwoQueues.push(2); + stackWithTwoQueues.push(3); + stackWithTwoQueues.push(4); + stackWithTwoQueues.push(5); + Assert.assertEquals(new Integer(5), stackWithTwoQueues.pop()); + Assert.assertEquals(new Integer(4), stackWithTwoQueues.pop()); + stackWithTwoQueues.push(6); + Assert.assertEquals(new Integer(6), stackWithTwoQueues.pop()); + Assert.assertEquals(new Integer(3), stackWithTwoQueues.pop()); + } + +} \ No newline at end of file diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/stack/TwoStackInOneArrayTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..efeb0f359d --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,28 @@ +package com.coding.basic.datastructure.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by zt + * 2017/5/6 19:35 + */ +public class TwoStackInOneArrayTest { + + @Test + public void pop() throws Exception { + TwoStackInOneArray twoStackInOneArray = new TwoStackInOneArray(15); + for (int i = 0; i < 10; i++) { + twoStackInOneArray.push1(new Integer(i)); + twoStackInOneArray.push2(new Integer(i + 10)); + } + Assert.assertEquals(new Integer(9), twoStackInOneArray.pop1()); + Assert.assertEquals(new Integer(19), twoStackInOneArray.pop2()); + Assert.assertEquals(new Integer(8), twoStackInOneArray.pop1()); + Assert.assertEquals(new Integer(7), twoStackInOneArray.pop1()); + Assert.assertEquals(new Integer(18), twoStackInOneArray.pop2()); + twoStackInOneArray.push1(666); + Assert.assertEquals(new Integer(666), twoStackInOneArray.pop1()); + } + +} \ No newline at end of file diff --git a/group03/569045298/src/test/com/coding/basic/datastructure/stack/expr/InfixExprTest.java b/group03/569045298/src/test/com/coding/basic/datastructure/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..51af111a13 --- /dev/null +++ b/group03/569045298/src/test/com/coding/basic/datastructure/stack/expr/InfixExprTest.java @@ -0,0 +1,50 @@ +package com.coding.basic.datastructure.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() { + + } + + @After + public void tearDown() { + + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpression expr = new InfixExpression("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpression expr = new InfixExpression("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpression expr = new InfixExpression("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpression expr = new InfixExpression("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpression expr = new InfixExpression("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group03/619224754/src/com/coding/basic/Stack.java b/group03/619224754/src/com/coding/basic/Stack.java deleted file mode 100644 index cf10ecc1b3..0000000000 --- a/group03/619224754/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.coding.basic; - -public class Stack { - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - this.elementData.add(o); - } - - public Object pop(){ - Object ret = this.elementData.remove(this.elementData.size() - 1); - return ret; - } - - public Object peek(){ - Object ret = this.elementData.get(this.elementData.size() - 1); - return null; - } - public boolean isEmpty(){ - return this.elementData.size() == 0; - } - public int size(){ - return this.elementData.size(); - } -} diff --git a/group03/619224754/src/com/coding/basic/stack/Stack.java b/group03/619224754/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..016b7630ba --- /dev/null +++ b/group03/619224754/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,27 @@ +package com.coding.basic.stack; + +import com.coding.basic.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + this.elementData.add(o); + } + + public Object pop(){ + Object ret = this.elementData.remove(this.elementData.size() - 1); + return ret; + } + + public Object peek(){ + Object ret = this.elementData.get(this.elementData.size() - 1); + return null; + } + public boolean isEmpty(){ + return this.elementData.size() == 0; + } + public int size(){ + return this.elementData.size(); + } +} diff --git a/group03/619224754/src/com/coding/basic/stack/StackUtil.java b/group03/619224754/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..1da51576f2 --- /dev/null +++ b/group03/619224754/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,133 @@ +package com.coding.basic.stack; + +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()) { + return; + } + + Stack retStack = new Stack(); + Object o = null; + do + { + o = s.pop(); + retStack.push(o); + } + while(o != null); + + s = retStack; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()) { + return; + } + + Stack tempStack = new Stack(); + Object o1 = null; + do + { + o1 = s.pop(); + if(o1 == o) { + break; + } + else { + tempStack.push(o1); + } + } + while(o1 != null); + + do + { + o1 = tempStack.pop(); + s.push(o1); + } + while(o1 != null); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if(s == null || s.isEmpty() ||len <= 0) { + return null; + } + + Object[] arr = new Object[len]; + if(s.size() < len){ + for (int i = 0; i < s.size(); i++) { + arr[i] = s.pop(); + } + for (int i = s.size(); i >= 0; i--) { + s.push(arr[i]); + } + } + else + { + for (int i = 0; i < len; i++) { + arr[i] = s.pop(); + } + for (int i = len; i >= 0; i--) { + s.push(arr[i]); + } + } + + return arr; + } + /** + * 字符串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){ + boolean isValid = true; + Stack stack = new Stack(); + for (int i = 0; i < s.length(); i++) { + if(s.charAt(i) =='(' || s.charAt(i) =='[' || s.charAt(i) =='{') { + stack.push(s.charAt(i)); + } + else if(s.charAt(i) ==')' || s.charAt(i) ==']' || s.charAt(i) =='}') { + char c = ' '; + switch(s.charAt(i)) + { + case ')': + c = (char) stack.pop(); + if(c != '(') + isValid = false; + break; + case ']': + c = (char) stack.pop(); + if(c != '[') + isValid = false; + break; + case '}': + c = (char) stack.pop(); + if(c != '{') + isValid = false; + break; + + } + if(!isValid) { + break; + } + } + } + return isValid; + } +} diff --git a/group03/664269713/DataStructure/DataStructure.iml b/group03/664269713/DataStructure/DataStructure.iml index 595934855d..73665fca7c 100644 --- a/group03/664269713/DataStructure/DataStructure.iml +++ b/group03/664269713/DataStructure/DataStructure.iml @@ -4,10 +4,11 @@ + - + @@ -16,5 +17,23 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/group03/664269713/DataStructure/src/com/ace/coding/DLinkedList.java b/group03/664269713/DataStructure/src/com/ace/coding/DLinkedList.java new file mode 100644 index 0000000000..3d96fc3fb2 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/coding/DLinkedList.java @@ -0,0 +1,38 @@ +package com.ace.coding; + +import java.util.Objects; + +/** + * Created by ace on 2017/4/2. + */ +public class DLinkedList { + private Node first; + private Node last; + private int currentSize; + + public DLinkedList(){ + currentSize = 0; + first = null; + last = null; + } + + public void add(Object obj){ + Node newNode = new Node(); + newNode.obj = obj; + if(first == null){ + first = newNode; + last = newNode; + } else { + + } + } + + + public static class Node{ + private Object obj; + private Node prev; + private Node next; + + public Node(){} + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/coding/LRUPageFrame.java b/group03/664269713/DataStructure/src/com/ace/coding/LRUPageFrame.java new file mode 100644 index 0000000000..338263fa64 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/coding/LRUPageFrame.java @@ -0,0 +1,136 @@ +package com.ace.coding; + +/** + * 用双向链表实现LRU算法 + * + */ +public class LRUPageFrame { + + private int capacity; + private int currentSize; + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + currentSize = 0; + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + */ + public void access(int pageNum) { + Node newNode = new Node(); + newNode.pageNum = pageNum; + + if(currentSize == 0){ + first = newNode; + last = first; + currentSize ++; + } else { + // if the node is exist then moveToHead + //else add to first + // if currentSize > 3 removeLast + Node currentNode = getNode(pageNum); + if(currentNode != null){ + remove(currentNode); + addFirst(newNode); + } else { + addFirst(newNode); + if(currentSize > 3){ + removeLast(); + } + } + } + } + + private void remove(Node node){ + Node pNode = first; + while(pNode != null){ + if(pNode == node){ + if(pNode == last){ + last = pNode.prev; + } else { + pNode.next.prev = pNode.prev; + } + if(pNode == first){ + first = pNode.next; + } else { + pNode.prev.next = pNode.next; + } + currentSize --; + } + pNode = pNode.next; + } + } + + private Node getNode(int pageNum){ + Node pNode = first; + while(pNode != null){ + if(pNode.pageNum == pageNum){ + return pNode; + } + pNode = pNode.next; + } + return null; + } + + private void removeLast(){ + Node pNode = last; + if(first.next == null){ + first = null; + last = null; + } else { + last.prev.next = null; + last = last.prev; + } + +// if(last != null){ +// if(last.prev != null){ +// last.prev.next = null; +// } else { +// first = null; +// } +// last = last.prev; +// } + + currentSize --; + } + + private void addFirst(Node newNode){ + if(last == null){ + last = newNode; + } else { + newNode.next = first; + first.prev = newNode; + } + first = newNode; + 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(); + } + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/coding/Queue.java b/group03/664269713/DataStructure/src/com/ace/coding/Queue.java index 15bcf5d497..16f983727a 100644 --- a/group03/664269713/DataStructure/src/com/ace/coding/Queue.java +++ b/group03/664269713/DataStructure/src/com/ace/coding/Queue.java @@ -18,7 +18,7 @@ public Object deQueue(){ } public boolean isEmpty(){ - return size()>0; + return size() == 0; } public int size(){ diff --git a/group03/664269713/DataStructure/src/com/ace/coding/StackUtil.java b/group03/664269713/DataStructure/src/com/ace/coding/StackUtil.java new file mode 100644 index 0000000000..12c6636b1d --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/coding/StackUtil.java @@ -0,0 +1,102 @@ +package com.ace.coding; + +public class StackUtil { + + /** + * 鍋囪鏍堜腑鐨勫厓绱犳槸Integer, 浠庢爤椤跺埌鏍堝簳鏄� : 5,4,3,2,1 璋冪敤璇ユ柟娉曞悗锛� 鍏冪礌娆″簭鍙樹负: + * 1,2,3,4,5 娉ㄦ剰锛氬彧鑳戒娇鐢⊿tack鐨勫熀鏈搷浣滐紝鍗硃ush,pop,peek,isEmpty锛� + * 鍙互浣跨敤鍙﹀涓�涓爤鏉ヨ緟鍔� + */ + public static void reverse(Stack s) { + if (s.size() == 0) { + return; + } + int last = getLast(s); + reverse(s); + s.push(last); + } + + public static int getLast(Stack s) { + int top = (int) s.pop(); + + if (s.size() == 0) { + return top; + } else { + int last = getLast(s); + s.push(top); + return last; + } + } + + /** + * 鍒犻櫎鏍堜腑鐨勬煇涓厓绱� 娉ㄦ剰锛氬彧鑳戒娇鐢⊿tack鐨勫熀鏈搷浣滐紝鍗硃ush,pop,peek,isEmpty锛� + * 鍙互浣跨敤鍙﹀涓�涓爤鏉ヨ緟鍔� + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack newStack = new Stack(); + for (int i = 0; i < s.size(); i++) { + Object obj = s.pop(); + if (obj == o) { + break; + } + newStack.push(obj); + } + + for (int j = 0; j < newStack.size(); j++) { + Object obj = newStack.pop(); + s.push(obj); + } + } + + /** + * 浠庢爤椤跺彇寰條en涓厓绱�, 鍘熸潵鐨勬爤涓厓绱犱繚鎸佷笉鍙� + * 娉ㄦ剰锛氬彧鑳戒娇鐢⊿tack鐨勫熀鏈搷浣滐紝鍗硃ush,pop,peek,isEmpty锛� 鍙互浣跨敤鍙﹀涓�涓爤鏉ヨ緟鍔� + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + Object[] objArr = new Object[len]; + Stack newStack = new Stack(); + + for (int i = 0; i < len; i++) { + Object obj = s.pop(); + objArr[i] = obj; + newStack.push(obj); + } + + for (int j = 0; j < len; j++) { + Object obj = newStack.pop(); + s.push(obj); + } + + return objArr; + } + + /** + * 瀛楃涓瞫 鍙兘鍖呭惈杩欎簺瀛楃锛� ( ) [ ] { }, a,b,c... x,yz + * 浣跨敤鍫嗘爤妫�鏌ュ瓧绗︿覆s涓殑鎷彿鏄笉鏄垚瀵瑰嚭鐜扮殑銆� 渚嬪s = "([e{d}f])" , + * 鍒欒瀛楃涓蹭腑鐨勬嫭鍙锋槸鎴愬鍑虹幇锛� 璇ユ柟娉曡繑鍥瀟rue 濡傛灉 s = "([b{x]y})", + * 鍒欒瀛楃涓蹭腑鐨勬嫭鍙蜂笉鏄垚瀵瑰嚭鐜扮殑锛� 璇ユ柟娉曡繑鍥瀎alse; + * + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + Stack stack = new Stack(); + int len = s.length(); + for (int i = 0; i < len; i++) { + stack.push(s.charAt(i)); + } + StringBuilder stringBuilder = new StringBuilder(); + + for (int j = 0; j < stack.size(); j++) { + stringBuilder.append(stack.pop()); + } + + return stringBuilder.toString().equals(s); + } + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/clz/AccessFlag.java b/group03/664269713/DataStructure/src/com/ace/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..744f7eeadb --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.ace.jvm.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/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassFile.java b/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..98f0539fc7 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.ace.jvm.clz; + +import com.ace.jvm.constant.ClassInfo; +import com.ace.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + 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 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(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassIndex.java b/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..421ae7ef42 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.ace.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group03/664269713/DataStructure/src/com/ace/jvm/constant/ClassInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..2e6cf0c08e --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.ace.jvm.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(); + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..1c67f67c4a --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.ace.jvm.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); + } + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantPool.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..c067852a99 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.ace.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/FieldRefInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..6b04332521 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.ace.jvm.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(); + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/MethodRefInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..1eb5b0e0a4 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.ace.jvm.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(); + } + + + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/NameAndTypeInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..b7a8125b92 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.ace.jvm.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()+")"; + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/NullConstantInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..b9adf49ac6 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.ace.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/StringInfo.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d027a02c87 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.ace.jvm.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); + } + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/constant/UTF8Info.java b/group03/664269713/DataStructure/src/com/ace/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..75d0695236 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.ace.jvm.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; + } + + + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/loader/ByteCodeIterator.java b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..42f779a0c4 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,40 @@ +package com.ace.jvm.loader; + +import java.util.Arrays; + +import com.ace.jvm.util.Util; + +public class ByteCodeIterator { + private int pos = 0; + private byte[] codes; + + public 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 = 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++] }); + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileLoader.java b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..7558f1d303 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileLoader.java @@ -0,0 +1,68 @@ +package com.ace.jvm.loader; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +import com.ace.jvm.clz.ClassFile; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + String path = getClassPath() + "//" + className.replaceAll("\\.", "//") + ".class"; + InputStream in = null; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try{ + in = new FileInputStream(path); + byte[] bytes = new byte[1024]; + int len = 0; + while((len = in.read(bytes)) != -1){ + out.write(bytes, 0 , len); + } + }catch (IOException e){ + e.printStackTrace(); + } finally { + if (in != null){ + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return out.toByteArray(); + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < clzPaths.size(); i++){ + if(i == clzPaths.size() - 1){ + sb.append(clzPaths.get(i)); + }else{ + sb.append(clzPaths.get(i) + ";"); + } + } + return sb.toString(); + } + + public ClassFile loadClass(String className){ + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileParser.java b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..845671a600 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/loader/ClassFileParser.java @@ -0,0 +1,134 @@ +package com.ace.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.ace.jvm.clz.AccessFlag; +import com.ace.jvm.clz.ClassFile; +import com.ace.jvm.clz.ClassIndex; +import com.ace.jvm.constant.ClassInfo; +import com.ace.jvm.constant.ConstantPool; +import com.ace.jvm.constant.FieldRefInfo; +import com.ace.jvm.constant.MethodRefInfo; +import com.ace.jvm.constant.NameAndTypeInfo; +import com.ace.jvm.constant.NullConstantInfo; +import com.ace.jvm.constant.StringInfo; +import com.ace.jvm.constant.UTF8Info; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + + String magicNum = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNum)) { + return null; + } + + clzFile.setMinorVersion(iter.nextU2ToInt()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + ClassIndex index = parseClassInfex(iter); + clzFile.setClassIndex(index); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + int flagValue = iter.nextU2ToInt(); + AccessFlag accessFlag = new AccessFlag(flagValue); + return accessFlag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + int thisClassIndex = iter.nextU2ToInt(); + classIndex.setThisClassIndex(thisClassIndex); + + int superClassIndex = iter.nextU2ToInt(); + classIndex.setSuperClassIndex(superClassIndex); + + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + ConstantPool pool = new ConstantPool(); + int poolCount = iter.nextU2ToInt(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i < poolCount - 1; i++) { + int tag = iter.nextU1ToInt(); + + if(tag == 7){ + int utf8Index = iter.nextU2ToInt(); + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(utf8Index); + + pool.addConstantInfo(classInfo); + } else if(tag == 1){ + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String str = null; + try { + str = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setLength(len); + utf8Info.setValue(str); + + pool.addConstantInfo(utf8Info); + } else if(tag == 8){ + StringInfo stringInfo = new StringInfo(pool); + int index = iter.nextU2ToInt(); + stringInfo.setIndex(index); + + pool.addConstantInfo(stringInfo); + } else if(tag == 9){ + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + int classInfoIndex = iter.nextU2ToInt(); + int nameAndTypeIndex = iter.nextU2ToInt(); + + fieldRefInfo.setClassInfoIndex(classInfoIndex); + fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + pool.addConstantInfo(fieldRefInfo); + } else if(tag == 10){ + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + int classInfoIndex = iter.nextU2ToInt(); + int nameAndTypeIndex = iter.nextU2ToInt(); + + methodRefInfo.setClassInfoIndex(classInfoIndex); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + pool.addConstantInfo(methodRefInfo); + } else if(tag == 12){ + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + int index1 = iter.nextU2ToInt(); + int index2 = iter.nextU2ToInt(); + + nameAndTypeInfo.setIndex1(index1); + nameAndTypeInfo.setIndex2(index2); + + pool.addConstantInfo(nameAndTypeInfo); + } else { + throw new RuntimeException("the constant pool tag " + tag + " is not exist."); + } + + } + + return pool; + } + +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/test/ClassFileloaderTest.java b/group03/664269713/DataStructure/src/com/ace/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..496d19dc71 --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,192 @@ +package com.ace.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.ace.jvm.clz.ClassFile; +import com.ace.jvm.clz.ClassIndex; +import com.ace.jvm.constant.ClassInfo; +import com.ace.jvm.constant.ConstantPool; +import com.ace.jvm.constant.MethodRefInfo; +import com.ace.jvm.constant.NameAndTypeInfo; +import com.ace.jvm.constant.UTF8Info; +import com.ace.jvm.loader.ClassFileLoader; + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/ace/jvm/test/EmployeeV1"; + + static String path1 = "D:\\Upgrade\\coding2017\\group03\\664269713\\DataStructure\\bin"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.ace.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); +// clzFile.print(); + } + + @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 = "com.ace.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 娉ㄦ剰锛氳繖涓瓧鑺傛暟鍙兘鍜屼綘鐨凧VM鐗堟湰鏈夊叧绯伙紝 浣犲彲浠ョ湅鐪嬬紪璇戝ソ鐨勭被鍒板簳鏈夊澶� + Assert.assertEquals(809, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.ace.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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()); + } +} diff --git a/group03/664269713/DataStructure/src/com/ace/jvm/test/EmployeeV1.java b/group03/664269713/DataStructure/src/com/ace/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..4add710f5e --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.ace.jvm.test; + +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/group03/664269713/DataStructure/src/com/ace/jvm/util/Util.java b/group03/664269713/DataStructure/src/com/ace/jvm/util/Util.java new file mode 100644 index 0000000000..fe7741649d --- /dev/null +++ b/group03/664269713/DataStructure/src/com/ace/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.ace.jvm.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 parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + return null; + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coderising/litestruts/StrutsTest.java b/group04/1020483199/HomeworkSuppned/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..b8c81faf3c --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group23/1028361767/Week1DataStructure/src/com/coderising/litestruts/View.java b/group04/1020483199/HomeworkSuppned/src/com/coderising/litestruts/View.java similarity index 100% rename from group23/1028361767/Week1DataStructure/src/com/coderising/litestruts/View.java rename to group04/1020483199/HomeworkSuppned/src/com/coderising/litestruts/View.java diff --git a/liuxin/data-structure/answer/src/com/coding/basic/BinaryTreeNode.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/BinaryTreeNode.java similarity index 100% rename from liuxin/data-structure/answer/src/com/coding/basic/BinaryTreeNode.java rename to group04/1020483199/HomeworkSuppned/src/com/coding/basic/BinaryTreeNode.java diff --git a/group23/601689050/Iterator.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/Iterator.java similarity index 100% rename from group23/601689050/Iterator.java rename to group04/1020483199/HomeworkSuppned/src/com/coding/basic/Iterator.java diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/List.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/List.java @@ -0,0 +1,9 @@ +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayList.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..4576c016af --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,35 @@ +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + public void add(Object o){ + + } + public void add(int index, Object o){ + + } + + public Object get(int index){ + return null; + } + + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public Iterator iterator(){ + return null; + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayUtil.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..45740e6d57 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,96 @@ +package com.coding.basic.array; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin){ + + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray){ + return null; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + return null; + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + return null; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + return null; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + return null; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + return null; + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator){ + return null; + } + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrame.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..24b9d8b155 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,164 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + Node node = find(pageNum); + //在该队列中存在, 则提到队列头 + if (node != null) { + + moveExistingNodeToHead(node); + + } else{ + + node = new Node(); + node.pageNum = pageNum; + + // 缓存容器是否已经超过大小. + if (currentSize >= capacity) { + removeLast(); + + } + + addNewNodetoHead(node); + + + + + } + } + + private void addNewNodetoHead(Node node) { + + if(isEmpty()){ + + node.prev = null; + node.next = null; + first = node; + last = node; + + } else{ + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + this.currentSize ++; + } + + private Node find(int data){ + + Node node = first; + while(node != null){ + if(node.pageNum == data){ + return node; + } + node = node.next; + } + return null; + + } + + + + + + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize --; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + * + * @param node + */ + private void moveExistingNodeToHead(Node node) { + + if (node == first) { + + return; + } + else if(node == last){ + //当前节点是链表尾, 需要放到链表头 + Node prevNode = node.prev; + prevNode.next = null; + last.prev = null; + last = prevNode; + + } else{ + //node 在链表的中间, 把node 的前后节点连接起来 + Node prevNode = node.prev; + prevNode.next = node.next; + + Node nextNode = node.next; + nextNode.prev = prevNode; + + + } + + node.prev = null; + node.next = first; + first.prev = node; + first = node; + + } + private boolean isEmpty(){ + return (first == null) && (last == null); + } + + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LinkedList.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/linklist/LinkedList.java @@ -0,0 +1,125 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueue.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..310817f374 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,57 @@ +package com.coding.basic.queue; + +import javax.management.RuntimeErrorException; + +public class CircleQueue { + + //用数组来保存循环队列的元素 + private Object[] elementData ; + int size = 0; + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public CircleQueue(int capacity){ + elementData = new Object[capacity]; + } + public boolean isEmpty() { + return front == rear; + + } + + public boolean isFull(){ + return size == elementData.length; + } + public int size() { + return size; + } + + public void enQueue(E data) { + if(isFull()){ + throw new RuntimeException("The queue is full"); + } + elementData[rear++] = data; + size++; + } + + public E deQueue() { + /*if(isEmpty()){ + throw new RuntimeException("The queue is empty"); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front+1) % elementData.length; + size --; + return data ;*/ + if (isEmpty()){ + throw new RuntimeException("is empty"); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front + 1) % elementData.length; + size --; + return data; + + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueueTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..7307eb77d4 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,44 @@ +package com.coding.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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Josephus.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..497abc5f07 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,39 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + + Queue queue = new Queue(); + for (int i = 0; i < n; i++){ + queue.enQueue(i); + } + + List result = new ArrayList(); + int i = 0; + + while (!queue.isEmpty() && queue.size() > 1) { + + int x = queue.deQueue(); + + if (++i % m == 0){ + result.add(x); + } else{ + queue.enQueue(x); + } + } + + System.out.println(result); + return result; + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/JosephusTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..5c2cf2cbec --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,43 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.myselfQueue.QueueWithTwoStacks; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + + @Test + public void testTwoStackQueue(){ + QueueWithTwoStacks q = new QueueWithTwoStacks(); + q.enQueue(1); + q.enQueue(2); + q.enQueue(3); + q.enQueue(4); + + System.out.println(q.deQueue()); + System.out.println(q.deQueue()); + System.out.println(q.deQueue()); + System.out.println(q.deQueue()); + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Queue.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..bc97df0800 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,55 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + private void moveStack1ToStack2() { + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + + } + + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + if (stack2.isEmpty()) { + moveStack1ToStack2(); + } + + return stack2.pop(); + } + + + + } + diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Stack.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..fedb243604 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,24 @@ +package com.coding.basic.stack; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + } + + public Object pop(){ + return null; + } + + public Object peek(){ + return null; + } + public boolean isEmpty(){ + return false; + } + public int size(){ + return -1; + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/StackUtil.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..7c86d22fe7 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,168 @@ +package com.coding.basic.stack; +import java.util.Stack; +public class StackUtil { + + public static void bad_reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + + + public static void reverse_247565311(Stack s){ + if(s == null || s.isEmpty()) { + return; + } + + int size = s.size(); + Stack tmpStack = new Stack(); + + for(int i=0;ii){ + tmpStack.push(s.pop()); + } + s.push(top); + while(tmpStack.size()>0){ + s.push(tmpStack.pop()); + } + } + } + + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + + Stack tmp = new Stack(); + while(!s.isEmpty()){ + tmp.push(s.pop()); + } + while(!tmp.isEmpty()){ + Integer top = tmp.pop(); + addToBottom(s,top); + } + + + } + public static void addToBottom(Stack s, Integer value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Integer top = s.pop(); + addToBottom(s,value); + s.push(top); + } + + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + + while(!s.isEmpty()){ + Object value = s.pop(); + if(!value.equals(o)){ + tmpStack.push(value); + } + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + + if(s == null || s.isEmpty() || s.size() stack = new Stack(); + for(int i=0;i s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + @Test + public void testReverse_247565311() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + Assert.assertEquals("[1, 2, 3]", s.toString()); + StackUtil.reverse_247565311(s); + Assert.assertEquals("[3, 2, 1]", s.toString()); + } + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Tail.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Tail.java new file mode 100644 index 0000000000..7f30ce55c8 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/Tail.java @@ -0,0 +1,5 @@ +package com.coding.basic.stack; + +public class Tail { + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..777a2f8014 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,73 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + //存放操作符栈 + Stack opStack = new Stack<>(); + //操作数据值栈 + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + + } + opStack.push(token); + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); + } + + + return numStack.pop().floatValue(); + } + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20e34e8852 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..9e501eda20 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,43 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + List inFixTokens = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList<>(); + + Stack opStack = new Stack(); + for(Token token : inFixTokens){ + + if(token.isOperator()){ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + postFixTokens.add(opStack.pop()); + + } + opStack.push(token); + + } + if(token.isNumber()){ + + postFixTokens.add(token); + + } + } + + while(!opStack.isEmpty()){ + postFixTokens.add(opStack.pop()); + } + + return postFixTokens; + } + + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfixTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..f879f55f14 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,41 @@ +package com.coding.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 InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..d65121633f --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,47 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack numStack = new Stack<>(); + for(Token token : tokens){ + System.out.println(token+"----"); + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } else{ + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(),f1,f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..0fc55de6fd --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..f811fd6d9a --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for(Token token : tokens){ + exprStack.push(token); + } + + while(!exprStack.isEmpty()){ + Token t = exprStack.pop(); + if(t.isNumber()){ + numStack.push(new Float(t.getIntValue())); + }else{ + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(),f1,f2)); + + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/Token.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParser.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..7a6cb2598e --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,54 @@ +package com.coding.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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParserTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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"); + + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExpr.java new file mode 100644 index 0000000000..0611a75c0a --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExpr.java @@ -0,0 +1,73 @@ +package com.coding.basic.stack.myself; + +import java.util.List; +import java.util.Stack; + +import com.coding.basic.stack.myself.Token; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + //存放操作符栈 + Stack opStack = new Stack<>(); + //操作数据值栈 + Stack numStack = new Stack<>(); + + for (Token token:tokens){ + //当前的token代表的是操作符时 + if (token.isOperator()){ + //当前操作符栈不为空并且当前操作符并不比栈顶优先级更高 + while (!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token preOperate = opStack.pop(); + float f2 = numStack.pop(); + float f1 = numStack.pop(); + float result = calculate(preOperate.toString(), f1, f2); + numStack.push(result); + } + opStack.push(token); + } + + if (token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + + + } + while (!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); + } + + return numStack.pop().floatValue(); + + } + + public float calculate(String op, float f1, float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExprTest.java new file mode 100644 index 0000000000..b0a58bcd0d --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.myself; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfix.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfix.java new file mode 100644 index 0000000000..b2a5206c81 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfix.java @@ -0,0 +1,79 @@ +package com.coding.basic.stack.myself; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coding.basic.stack.myself.Token; + +public class InfixToPostfix { + + public static List convert(String expr) { + /*List infixPost = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList<>(); + + Stack opStack = new Stack(); + //2-3*4+5 + for (Token token:infixPost){ + if(token.isOperator()){ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + System.out.println("满足条件的token"+token); + postFixTokens.add(opStack.pop());// + } + + opStack.push(token);//- + + } + + if(token.isNumber()){ + + postFixTokens.add(token);//2 3 + + } + } + + while (!opStack.isEmpty()){ + + postFixTokens.add(opStack.pop()); + + } + + return postFixTokens;*/ + + List infixPost = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList(); + + Stack openStack = new Stack(); + + for (Token token:infixPost){ + + if (token.isOperator()){ + + while (!openStack.isEmpty() + && !token.hasHigherPriority(openStack.peek())){ + postFixTokens.add(openStack.pop()); + } + + openStack.push(token); + } + + if (token.isNumber()){ + + postFixTokens.add(token); + } + } + + while (!openStack.isEmpty()){ + postFixTokens.add(openStack.pop()); + } + + return postFixTokens; + } + + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfixTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfixTest.java new file mode 100644 index 0000000000..c2b1aedacc --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/InfixToPostfixTest.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack.myself; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExpr.java new file mode 100644 index 0000000000..9fc596ef64 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExpr.java @@ -0,0 +1,49 @@ +package com.coding.basic.stack.myself; + +import java.util.List; +import java.util.Stack; + +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 numStack = new Stack(); + for (Token token:tokens){ + if (token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + }else{ + float f2 = numStack.pop(); + float f1 = numStack.pop(); + float result = calculate(token.toString(), f1, f2); + numStack.push(result); + } + + + } + return numStack.pop().floatValue(); + } + + public float calculate(String op, float f1, float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExprTest.java new file mode 100644 index 0000000000..2353fae242 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.myself; + + + +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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExpr.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExpr.java new file mode 100644 index 0000000000..dcce38cfce --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExpr.java @@ -0,0 +1,59 @@ +package com.coding.basic.stack.myself; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coding.basic.stack.myself.Token; + +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); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for(Token token : tokens){ + exprStack.push(token); + } + + while(!exprStack.isEmpty()){ + Token t = exprStack.pop(); + if(t.isNumber()){ + numStack.push(new Float(t.getIntValue())); + }else{ + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(),f1,f2)); + + } + } + return numStack.pop().floatValue(); + + } + + + public float calculate(String op, float f1, float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExprTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExprTest.java new file mode 100644 index 0000000000..694904d686 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack.myself; + +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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/Token.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/Token.java new file mode 100644 index 0000000000..9c81783697 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/Token.java @@ -0,0 +1,50 @@ +package com.coding.basic.stack.myself; + +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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParser.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParser.java new file mode 100644 index 0000000000..c6a96986fd --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack.myself; + +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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParserTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParserTest.java new file mode 100644 index 0000000000..84a0df926b --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myself/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.myself; + +import static org.junit.Assert.*; + +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"); + + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueue.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueue.java new file mode 100644 index 0000000000..42a13baed3 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueue.java @@ -0,0 +1,62 @@ +package com.coding.basic.stack.myselfQueue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + //用数组来保存循环队列的元素 + private Object[] elementData; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + private int size = 0; + + public CircleQueue(int capcility){ + elementData = new Object[capcility]; + } + + public boolean isEmpty() { + + return front == rear; + + } + + public boolean isFull(){ + return size == elementData.length; + } + + public int size() { + + return size; + } + + + + public void enQueue(E data) { + if (isFull()){ + throw new RuntimeException("the queue is full"); + } + + elementData[rear++] = data; + size++; + } + + public E deQueue() { + if (isEmpty()){ + throw new RuntimeException("the queue is empty"); + } + E data = (E) elementData[front]; + elementData[front] = null; + front = (front + 1) % elementData.length; + size --; + return data; + + } +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueueTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueueTest.java new file mode 100644 index 0000000000..f7ebe87fb3 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/CircleQueueTest.java @@ -0,0 +1,44 @@ +package com.coding.basic.stack.myselfQueue; + +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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Josephus.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Josephus.java new file mode 100644 index 0000000000..ce1187cf02 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Josephus.java @@ -0,0 +1,35 @@ +package com.coding.basic.stack.myselfQueue; + +import java.util.ArrayList; +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){ + List result = new ArrayList(); + Queue queue = new Queue(); + for (int i = 0; i < n; i++){ + queue.enQueue(i); + } + int x = 0; + while (queue.size() > 1){ + int data = queue.deQueue(); + + if (++x % m == 0){ + result.add(data); + }else { + queue.enQueue(data); + } + } + + return result; + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/JosephusTest.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/JosephusTest.java new file mode 100644 index 0000000000..273b6456bc --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.stack.myselfQueue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Queue.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Queue.java new file mode 100644 index 0000000000..47410c6070 --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.stack.myselfQueue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/QueueWithTwoStacks.java b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..59e141991d --- /dev/null +++ b/group04/1020483199/HomeworkSuppned/src/com/coding/basic/stack/myselfQueue/QueueWithTwoStacks.java @@ -0,0 +1,63 @@ +package com.coding.basic.stack.myselfQueue; + +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() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (stack2.isEmpty()){ + stack2 = convert(stack1); + } + + E pop = stack2.pop(); + return pop; + } + + + + + private Stack convert(Stack stack) { + Stack newStack = new Stack(); + while (!stack.isEmpty()){ + newStack.push(stack.pop()); + } + return newStack; + } + + + + } + diff --git a/group04/1299310140/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group04/1299310140/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..9cbc4c3fb4 --- /dev/null +++ b/group04/1299310140/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public byte[] getBytes(int length){ + byte[] data = Arrays.copyOfRange(codes, pos, pos + length); + pos += length; + 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 nextU1ToString(){ + return Util.byteToHexString(new byte[]{codes[pos++]}); + } + + public String nextU2ToString(){ + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++]}); + } + + public String nextU4ToString(){ + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + +} diff --git a/group04/1299310140/src/com/coderising/jvm/loader/ClassFileParser.java b/group04/1299310140/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..bb3535dcf6 --- /dev/null +++ b/group04/1299310140/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,137 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ClassFile classFile = new ClassFile(); + + ByteCodeIterator iter = new ByteCodeIterator(codes); + + String magicNumber = iter.nextU4ToString(); + System.out.println("magicNumber:"+magicNumber); + + int minorVersion = iter.nextU2ToInt(); + int majorVersion = iter.nextU2ToInt(); + classFile.setMinorVersion(minorVersion); + classFile.setMajorVersion(majorVersion); + + ConstantPool constantPool = this.parseConstantPool(iter); + classFile.setConstPool(constantPool); + + AccessFlag accessFlag = this.parseAccessFlag(iter); + classFile.setAccessFlag(accessFlag); + + ClassIndex classIndex = this.parseClassIndex(iter); + classFile.setClassIndex(classIndex); + + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter){ + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter){ + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(thisClassIndex); + classIndex.setSuperClassIndex(superClassIndex); + + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter){ + + ConstantPool constantPool = new ConstantPool(); + + constantPool.addConstantInfo(new NullConstantInfo()); + + int constantNumber = iter.nextU2ToInt();//常量池项的个数 + + for(int i = 1;i <= constantNumber - 1;i++){ + + int type = iter.nextU1ToInt(); + + if(type == 1){ + //UTF8Info + int length = iter.nextU2ToInt(); + byte[] bytes = iter.getBytes(length); + String value = ""; + try { + value = new String(bytes,"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + UTF8Info utf8Info = new UTF8Info(constantPool); + utf8Info.setLength(length); + utf8Info.setValue(value); + + constantPool.addConstantInfo(utf8Info); + }else if(type == 7){ + //ClassInfo + int utf8Index = iter.nextU2ToInt(); + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(utf8Index); + + constantPool.addConstantInfo(classInfo); + }else if(type == 8){ + //StringInfo + int index = iter.nextU2ToInt(); + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(index); + + constantPool.addConstantInfo(stringInfo); + }else if(type == 9){ + //FieldRefInfo + int classInfoIndex = iter.nextU2ToInt(); + int nameAndTypeIndex = iter.nextU2ToInt(); + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(classInfoIndex); + fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + constantPool.addConstantInfo(fieldRefInfo); + }else if(type == 10){ + //MethodRefInfo + int classInfoIndex = iter.nextU2ToInt(); + int nameAndTypeIndex = iter.nextU2ToInt(); + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(classInfoIndex); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + constantPool.addConstantInfo(methodRefInfo); + }else if(type == 12){ + //NameAndTypeInfo + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(nameIndex); + nameAndTypeInfo.setIndex2(descriptorIndex); + + constantPool.addConstantInfo(nameAndTypeInfo); + }else{ + // + throw new RuntimeException("该常量项还未实现!!!"); + } + } + + return constantPool; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/queue/CircleQueue.java b/group04/1299310140/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..0c61bbfae6 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0;//指向下一个空位 + //实际大小 + private int size = 0; + + public CircleQueue(int i) { + this.elementData = new Object[i]; + } + + public boolean isEmpty() { + return size == 0; + } + + public boolean isFull() { + return size == elementData.length; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + if(isFull()){ + throw new RuntimeException("The queue is full!!!"); + } + + elementData[rear] = data; + rear = (rear + 1) % elementData.length; + size++; + } + + public E deQueue() { + if(isEmpty()){ + throw new RuntimeException("The queue is empty!!!"); + } + + E result = (E) elementData[front]; + elementData[front] = null; + front = (front + 1) % elementData.length; + size--; + return result; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/queue/Josephus.java b/group04/1299310140/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..d0c1f2ca79 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,37 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +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){ + + Queue queue = new Queue(); + for(int i = 0;i < n;i++){ + queue.enQueue(i); + } + + int temp = 0; + List result = new ArrayList(); + while(!queue.isEmpty()){ + temp = (temp + 1) % m; + Object queueFirst = queue.deQueue(); + if(temp == 0){ + result.add((Integer) queueFirst); + }else{ + queue.enQueue(queueFirst); + } + } + + return result; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group04/1299310140/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..4776c06513 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +package com.coding.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() && stack2.isEmpty(); + } + + public int size() { + return stack1.size() + stack2.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(this.isEmpty()){ + return null; + } + + if(stack2.isEmpty()){ + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + + return stack2.pop(); + } + + } + diff --git a/group04/1299310140/src/com/coding/basic/stack/QuickMinStack.java b/group04/1299310140/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..324ea1ba9a --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,68 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回该数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + private ArrayList elementData = new ArrayList(); + + public Boolean isEmpty(){ + return elementData.size() == 0; + } + + public int size(){ + return elementData.size(); + } + + public void push(int data){ + int[] temp = new int[3];//data min max + if(isEmpty()){ + temp[0] = data; + temp[1] = data; + temp[2] = data; + elementData.add(temp); + return; + } + + int min = this.elementData.get(size()-1)[1]; + int max = this.elementData.get(size()-1)[2]; + + temp[0] = data; + + if(data < min){ + temp[1] = data; + }else{ + temp[1] = min; + } + + if(data > max){ + temp[2] = data; + }else{ + temp[2] = max; + } + + elementData.add(temp); + } + + public int pop(){ + return this.elementData.remove(size()-1)[0]; + } + + public int peek(){ + return this.elementData.get(size()-1)[0]; + } + + public int findMin(){ + return this.elementData.get(size()-1)[1]; + } + + public int findMax(){ + return this.elementData.get(size()-1)[2]; + } +} diff --git a/group04/1299310140/src/com/coding/basic/stack/QuickMinStackTest.java b/group04/1299310140/src/com/coding/basic/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..09be7c9496 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/QuickMinStackTest.java @@ -0,0 +1,53 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class QuickMinStackTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + QuickMinStack stack = new QuickMinStack(); + Assert.assertTrue(stack.isEmpty()); + Assert.assertEquals(0,stack.size()); + + stack.push(3); + Assert.assertFalse(stack.isEmpty()); + Assert.assertEquals(1,stack.size()); + Assert.assertEquals(3,stack.peek()); + Assert.assertEquals(3,stack.findMin()); + Assert.assertEquals(3,stack.findMax()); + Assert.assertEquals(3,stack.pop()); + Assert.assertTrue(stack.isEmpty()); + Assert.assertEquals(0,stack.size()); + + stack.push(5); + stack.push(6); + stack.push(3); + stack.push(7); + stack.push(1); + Assert.assertEquals(1,stack.findMin()); + Assert.assertEquals(7,stack.findMax()); + + stack.pop(); + Assert.assertEquals(3,stack.findMin()); + Assert.assertEquals(7,stack.findMax()); + + stack.pop(); + Assert.assertEquals(3,stack.findMin()); + Assert.assertEquals(6,stack.findMax()); + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/StackUtil.java b/group04/1299310140/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..1dd70e80f4 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,150 @@ +package com.coding.basic.stack; + +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) {//s:[1,2,3,4,5] + if(s == null || s.isEmpty()){ + return; + } + + Stack reverseOne = new Stack(); + while(!s.isEmpty()){ + reverseOne.push(s.pop()); + }//s:[] reverseOne:[5,4,3,2,1] + + Stack reverseTwo = new Stack(); + while(!reverseOne.isEmpty()){ + reverseTwo.push(reverseOne.pop()); + }//s:[] reverseOne:[] reverseTwo:[1,2,3,4,5] + + while(!reverseTwo.isEmpty()){ + s.push(reverseTwo.pop()); + }//s:[5,4,3,2,1] reverseOne:[] reverseTwo:[] + + } + + //递归实现 + public static void reverse_V1(Stack s){ + if(s == null || s.isEmpty()){ + return; + } + + Object top = s.pop(); + if(!s.isEmpty()){ + StackUtil.reverse_V1(s); + + Stack temp = new Stack(); + while(!s.isEmpty()){ + temp.push(s.pop()); + } + + s.push(top); + + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + + }else{ + s.push(top); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } + + Stack temp = new Stack(); + Object top = null; + while(!s.isEmpty()){ + top = s.pop(); + if(top.equals(o)){ + break; + } + temp.push(top); + } + + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) {//若len>s的size,则Object[size]~Object[len-1]为null + if(s == null || s.isEmpty() || len <= 0){ + return null; + } + + Object[] result = new Object[len]; + int i = 0; + for(i = 0;i < len;i++){ + if(s.isEmpty()){ + break; + } + result[i] = s.pop(); + } + + for(int j = i - 1;j >= 0;j--){ + s.push(result[j]); + } + return result; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,y,z + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + if(s == null || s.length() == 0 || s.length() == 1){ + return true; + } + + char[] sc = s.toCharArray(); + Stack scStack = new Stack();//用该栈保存参数字符串的字符数组 + for(int i = 0;i < sc.length;i++){ + scStack.push(sc[i]); + } + + Stack temp = new Stack();//保存')' ']' '}' + while(!scStack.isEmpty()){ + char scStackTop = (char)scStack.pop(); + if(scStackTop == ')' || scStackTop == ']' || scStackTop == '}'){ + temp.push(scStackTop); + continue; + } + + if(scStackTop == '(' || scStackTop == '[' || scStackTop == '{'){ + if(temp.isEmpty()){ + return false; + } + char tempTop = (char)temp.pop(); + //scStackTop:'('or'['or'{' tempTop:')'or']'or'}' + if((scStackTop + 1 == tempTop) || (scStackTop + 2 == tempTop)){ + continue; + }else{ + return false; + } + } + } + return true; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueues.java b/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..c176be9b95 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,54 @@ +package com.coding.basic.stack; + +import com.coding.basic.Queue; + +public class StackWithTwoQueues { + + private Queue queue1; + private Queue queue2; + + public StackWithTwoQueues() { + queue1 = new Queue(); + queue2 = new Queue(); + } + + public Boolean isEmpty(){ + return queue1.isEmpty() && queue2.isEmpty(); + } + + public int size(){ + return queue1.size() + queue2.size(); + } + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + if(isEmpty()){ + throw new RuntimeException("The Stack is empty!!!"); + } + + while(!queue1.isEmpty()){ + Object temp = queue1.deQueue(); + if(queue1.isEmpty()){ + return (int)temp; + }else{ + queue2.enQueue(temp); + } + } + + //queue1为空,queue2不为空 + while(!queue2.isEmpty()){ + Object temp = queue2.deQueue(); + if(queue2.isEmpty()){ + return (int)temp; + }else{ + queue1.enQueue(temp); + } + } + + return -1;//永远不会执行 + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueuesTest.java b/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..013ceaa10e --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class StackWithTwoQueuesTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + Assert.assertTrue(stack.isEmpty()); + Assert.assertEquals(0,stack.size()); + + stack.push(4); + Assert.assertFalse(stack.isEmpty()); + Assert.assertEquals(1,stack.size()); + + Assert.assertEquals(4,stack.pop()); + Assert.assertTrue(stack.isEmpty()); + + stack.push(2); + stack.push(3); + stack.push(5); + Assert.assertFalse(stack.isEmpty()); + Assert.assertEquals(3,stack.size()); + + Assert.assertEquals(5,stack.pop()); + + stack.push(6); + stack.push(7); + stack.push(8); + Assert.assertEquals(8,stack.pop()); + Assert.assertEquals(7,stack.pop()); + Assert.assertEquals(6,stack.pop()); + Assert.assertEquals(3,stack.pop()); + Assert.assertEquals(2,stack.pop()); + Assert.assertTrue(stack.isEmpty()); + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArray.java b/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..311233daaa --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,100 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + + private Object[] data = new Object[10]; + private int pos1 = 0;//指向栈1的下一个空位 + private int pos2 = data.length - 1;//指向栈2的下一个空位 + + public Boolean isEmpty1(){ + return pos1 == 0; + } + + public Boolean isEmpty2(){ + return pos2 == data.length - 1; + } + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + this.data[pos1] = o; + pos1++; + if(pos1 == pos2){//扩容 + grow(); + } + } + + private void grow(){//容量增加一倍 + Object[] target = new Object[this.data.length * 2]; + System.arraycopy(this.data, 0, target, 0, pos1); + System.arraycopy(this.data, pos2 + 1, target, pos2 + 1 + data.length, data.length - pos2 -1); + pos2 = pos2 + data.length; + data = target; + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if(this.isEmpty1()){ + throw new RuntimeException("The stack1 is empty!!!"); + } + + pos1--; + Object result = this.data[pos1]; + this.data[pos1] = null; + return result; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + public Object peek1(){ + return this.data[pos1-1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + this.data[pos2] = o; + pos2--; + if(pos1 == pos2){//扩容 + grow(); + } + } + + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if(isEmpty2()){ + throw new RuntimeException("The stack2 is empty!!!"); + } + + pos2++; + Object result = this.data[pos2]; + this.data[pos2] = null; + return result; + } + + /** + * 获取第二个栈的栈顶元素 + * @return + */ + public Object peek2(){ + return this.data[pos2 + 1]; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArrayTest.java b/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..0fc822b4c7 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,65 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TwoStackInOneArrayTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + TwoStackInOneArray twoStack = new TwoStackInOneArray(); + Assert.assertTrue(twoStack.isEmpty1()); + Assert.assertTrue(twoStack.isEmpty2()); + + twoStack.push1(1); + twoStack.push1(2); + twoStack.push1(3); + twoStack.push1(4); + twoStack.push1(5); + + twoStack.push2(6); + twoStack.push2(7); + twoStack.push2(8); + twoStack.push2(9); + twoStack.push2(10); + twoStack.push2(11); + + twoStack.push1(12); + twoStack.push1(13); + twoStack.push1(14); + twoStack.push1(15); + + Assert.assertEquals(15,twoStack.pop1()); + Assert.assertEquals(14,twoStack.pop1()); + Assert.assertEquals(13,twoStack.pop1()); + Assert.assertEquals(12,twoStack.pop1()); + Assert.assertEquals(5,twoStack.pop1()); + Assert.assertEquals(4,twoStack.pop1()); + Assert.assertEquals(3,twoStack.pop1()); + Assert.assertEquals(2,twoStack.pop1()); + Assert.assertEquals(1,twoStack.pop1()); + + Assert.assertEquals(11,twoStack.pop2()); + Assert.assertEquals(10,twoStack.pop2()); + Assert.assertEquals(9,twoStack.pop2()); + Assert.assertEquals(8,twoStack.pop2()); + Assert.assertEquals(7,twoStack.pop2()); + Assert.assertEquals(6,twoStack.pop2()); + + Assert.assertTrue(twoStack.isEmpty1()); + Assert.assertTrue(twoStack.isEmpty2()); + } + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/expr/InfixExpr.java b/group04/1299310140/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..08ade05557 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List expr_LToken = parser.parse(this.expr); + + Stack operandStack_SF = new Stack(); + Stack operatorStack_SToken = new Stack(); + for(Token token : expr_LToken){ + if(token.isNumber()){ + operandStack_SF.push(new Float(token.getIntValue())); + }else{ + while(!operatorStack_SToken.isEmpty() && + !token.hasHigherPriority(operatorStack_SToken.peek())){ + //运算符栈不为空 且 当前运算符的优先级 小于等于 栈顶运算符的优先级 + Float f2 = operandStack_SF.pop(); + Float f1 = operandStack_SF.pop(); + String operator = operatorStack_SToken.pop().toString(); + Float result = CalculateUtil.calculate(operator, f1, f2); + operandStack_SF.push(result); + } + operatorStack_SToken.push(token); + } + } + + //此时运算符栈 栈底到栈顶 运算符的优先级 严格递增 + while(!operatorStack_SToken.isEmpty()){ + Float f2 = operandStack_SF.pop(); + Float f1 = operandStack_SF.pop(); + String operator = operatorStack_SToken.pop().toString(); + Float result = CalculateUtil.calculate(operator, f1, f2); + operandStack_SF.push(result); + } + return operandStack_SF.pop().floatValue(); + } + + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group04/1299310140/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..e3c8ddc1d4 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,37 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List infixExpr_LToken = parser.parse(expr); + + List postfixExpr_LToken = new ArrayList(); + Stack operatorStack_SToken = new Stack(); + for(Token token : infixExpr_LToken){ + if(token.isNumber()){ + postfixExpr_LToken.add(token); + }else{ + while(!operatorStack_SToken.isEmpty() && + !token.hasHigherPriority(operatorStack_SToken.peek())){ + //运算符栈不为空 且 当前运算符的优先级 小于等于 栈顶运算符的优先级 + postfixExpr_LToken.add(operatorStack_SToken.pop()); + } + operatorStack_SToken.push(token); + } + } + + //此时运算符栈 栈底到栈顶 运算符的优先级 严格递增 + while(!operatorStack_SToken.isEmpty()){ + postfixExpr_LToken.add(operatorStack_SToken.pop()); + } + return postfixExpr_LToken; + } + + + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/expr/MyInfixExpr.java b/group04/1299310140/src/com/coding/basic/stack/expr/MyInfixExpr.java new file mode 100644 index 0000000000..a0ca0bda4b --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/expr/MyInfixExpr.java @@ -0,0 +1,75 @@ +package com.coding.basic.stack.expr; + +import java.util.Stack; + +public class MyInfixExpr { + //操作数为整数,操作符只支持+、-、*、/,/的返回值为float类型 + private String expr = ""; + private char[] sc = null; + private int pos = 0; + + public MyInfixExpr(String expr) { + this.expr = expr; + this.sc = expr.toCharArray(); + } + + //下一个操作数 + private int nextOperand(){ + int result = sc[pos] - 48;//char:'0'-->int:0 + pos++; + while(pos < sc.length && sc[pos] >= '0' && sc[pos] <= '9'){ + result = result * 10 + (sc[pos] - 48); + pos++; + } + return result; + } + + //下一个操作符 + private char nextOperator(){ + return sc[pos++]; + } + + public float evaluate() { + Stack stack = this.multiplyDivide(); + float result = add(stack); + return result; + } + + //将栈内所有操作数相加 + private float add(Stack stack){ + if(stack == null || stack.isEmpty()){ + return 0; + } + + float result = 0; + while(!stack.isEmpty()){ + result = result + (float)stack.pop(); + } + return result; + } + + //操作数入栈,完成乘除运算,'-'随数入栈 + private Stack multiplyDivide(){ + Stack operandStack = new Stack(); + operandStack.push((float)this.nextOperand()); + int tempOperand = 0; + char tempOperator = 0; + while(pos < sc.length){ + tempOperator = this.nextOperator(); + tempOperand = this.nextOperand(); + if(tempOperator == '+'){ + operandStack.push((float)tempOperand); + }else if(tempOperator == '-'){ + operandStack.push((float)(- tempOperand)); + }else if(tempOperator == '*'){ + float top = (float)operandStack.pop(); + operandStack.push(top * tempOperand); + }else if(tempOperator == '/'){ + float top = (float)operandStack.pop(); + operandStack.push(top / tempOperand); + } + } + + return operandStack; + } +} diff --git a/group04/1299310140/src/com/coding/basic/stack/expr/PostfixExpr.java b/group04/1299310140/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..f034a4bed7 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,32 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List expr_LToken = parser.parse(this.expr); + + Stack operandStack_SF = new Stack(); + for(Token token : expr_LToken){ + if(token.isNumber()){ + operandStack_SF.push(new Float(token.getIntValue())); + }else{ + Float f2 = operandStack_SF.pop(); + Float f1 = operandStack_SF.pop(); + Float result = CalculateUtil.calculate(token.toString(), f1, f2); + operandStack_SF.push(result); + } + } + return operandStack_SF.pop().floatValue(); + } + + +} diff --git a/group04/1299310140/src/com/coding/basic/stack/expr/PrefixExpr.java b/group04/1299310140/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..e3cf5d3feb --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,38 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List expr_LToken = parser.parse(this.expr); + + Stack expr_SToken = new Stack(); + for(Token token : expr_LToken){ + expr_SToken.push(token); + } + + Stack operandStack_SF = new Stack(); + while(!expr_SToken.isEmpty()){ + Token token = expr_SToken.pop(); + if(token.isNumber()){ + operandStack_SF.push(new Float(token.getIntValue())); + }else{ + Float f1 = operandStack_SF.pop(); + Float f2 = operandStack_SF.pop(); + Float result = CalculateUtil.calculate(token.toString(), f1, f2); + operandStack_SF.push(result); + } + } + return operandStack_SF.pop().floatValue(); + } + + +} diff --git a/group04/1299310140/src/com/coding/basic/tree/BinaryTreeUtil.java b/group04/1299310140/src/com/coding/basic/tree/BinaryTreeUtil.java new file mode 100644 index 0000000000..6d48f6e68f --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/tree/BinaryTreeUtil.java @@ -0,0 +1,130 @@ +package com.coding.basic.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class BinaryTreeUtil { + /** + * 用 递归 的方式实现对二叉树的 前序 遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + if(root == null || root.getData() == null){ + return result; + } + + result.add(root.getData()); + result.addAll(preOrderVisit(root.getLeft())); + result.addAll(preOrderVisit(root.getRight())); + + return result; + } + + /** + * 用 递归 的方式实现对二叉树的 中序 遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + if(root == null || root.getData() == null){ + return result; + } + + result.addAll(inOrderVisit(root.getLeft())); + result.add(root.getData()); + result.addAll(inOrderVisit(root.getRight())); + + return result; + } + + /** + * 用 递归 的方式实现对二叉树的 后序 遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + if(root == null || root.getData() == null){ + return result; + } + + result.addAll(postOrderVisit(root.getLeft())); + result.addAll(postOrderVisit(root.getRight())); + result.add(root.getData()); + + return result; + } + + /** + * 用 非递归 的方式实现对二叉树的 前序 遍历 + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + List result = new ArrayList(); + + if(root == null || root.getData() == null){ + return result; + } + + Stack> stack = new Stack>(); + stack.push(root); + while(!stack.isEmpty()){ + BinaryTreeNode temp = stack.pop(); + result.add(temp.getData()); + + if(temp.getRight() != null){ + stack.push(temp.getRight()); + } + + if(temp.getLeft() != null){ + stack.push(temp.getLeft()); + } + } + + return result; + } + + /** + * 用 非递归 的方式实现对二叉树的 中序 遍历 + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + List result = new ArrayList(); + + if(root == null || root.getData() == null){ + return result; + } + + Stack> stack = new Stack>(); + while(root != null){ + stack.push(root); + root = root.getLeft(); + } + + while(!stack.isEmpty()){ + BinaryTreeNode temp = stack.pop(); + result.add(temp.getData()); + + temp = temp.getRight(); + while(temp != null){ + stack.push(temp); + temp = temp.getLeft(); + } + } + + return result; + } + +} diff --git a/group04/1299310140/src/com/coding/basic/tree/FileList.java b/group04/1299310140/src/com/coding/basic/tree/FileList.java new file mode 100644 index 0000000000..a346803663 --- /dev/null +++ b/group04/1299310140/src/com/coding/basic/tree/FileList.java @@ -0,0 +1,28 @@ +package com.coding.basic.tree; + +import java.io.File; + +public class FileList { + + public static void list(File f,int l) { + if(!f.isFile() && !f.isDirectory()){ + return; + } + + for(int i = 0;i < l;i++){//对齐 + System.out.print("|--"); + } + + System.out.println(f.getName()); + if(f.isDirectory()){ + File[] files_L = f.listFiles(); + for(File file : files_L){ + list(file,l+1); + } + } + } + + public static void main(String[] args){ + list(new File("C:/"),0); + } +} diff --git a/group04/1796244932/learn01/pom.xml b/group04/1796244932/learn01/pom.xml index f62b63ec4b..974a96ddcd 100644 --- a/group04/1796244932/learn01/pom.xml +++ b/group04/1796244932/learn01/pom.xml @@ -44,6 +44,38 @@ 4.0.0.Alpha8 + + + + javassist + javassist + 3.12.1.GA + + + + + + cglib + cglib + 2.2.2 + + + + + org.apache.commons + commons-lang3 + 3.5 + + + + + commons-io + commons-io + 2.4 + + + + diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyIterator.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyIterator.java deleted file mode 100644 index e53306fa03..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyIterator.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dudy.learn01.base; -public interface MyIterator { - public boolean hasNext(); - public Object next(); - -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyQueue.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyQueue.java deleted file mode 100644 index 25b9da93f2..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyQueue.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dudy.learn01.base; -public class MyQueue { - - private MyLinkedList elementData = new MyLinkedList(); - - public void enQueue(Object o){ - elementData.addLast(o); - } - - public Object deQueue(){ - - return elementData.removeFirst(); - } - - public boolean isEmpty(){ - return elementData.size() == 0 ; - } - - public int size(){ - return elementData.size(); - } -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyStack.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyStack.java deleted file mode 100644 index e59c366e0a..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyStack.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dudy.learn01.base; -public class MyStack { - private MyArrayList elementData = new MyArrayList(); - - public void push(Object o){ - elementData.add(o); - } - - public Object pop(){ - - Object o = elementData.get(elementData.size()-1); - elementData.remove(elementData.size()); - return o; - } - - public Object peek(){ - - return elementData.get(elementData.size()-1); - } - public boolean isEmpty(){ - return elementData.size() == 0; - } - public int size(){ - return elementData.size(); - } -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/Business.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/Business.java new file mode 100644 index 0000000000..5c7526ca83 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/Business.java @@ -0,0 +1,16 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +/** + * Created by dudy on 2017/3/22. + */ +public class Business implements IBusiness,IBusiness2{ + @Override + public void dosomething() { + System.out.println("dosomething....."); + } + + @Override + public void dosomething2() { + System.out.println("dosomething2....."); + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/CGlibDemo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/CGlibDemo.java new file mode 100644 index 0000000000..c49131ce59 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/CGlibDemo.java @@ -0,0 +1,28 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +import net.sf.cglib.proxy.Enhancer; + +/** + * Created by dudy on 2017/3/22. + */ +public class CGlibDemo { + + public static void main(String[] args) { + byteCodeGe(); + } + + public static void byteCodeGe(){ + //创建一个织入器 + Enhancer enhancer = new Enhancer(); + // 设置父类 + enhancer.setSuperclass(Business.class); + // 设置需要织入的逻辑 + enhancer.setCallback(new LogIntercept()); + //使用织入器创建子类 + IBusiness2 newBusiness = (IBusiness2) enhancer.create(); + newBusiness.dosomething2(); + + } + + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/DynamicProxyDemo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/DynamicProxyDemo.java new file mode 100644 index 0000000000..0ffd41eeb9 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/DynamicProxyDemo.java @@ -0,0 +1,25 @@ +package com.dudy.learn01.base.aop.DynamicProxy; +import java.lang.reflect.Proxy; + +/** + * Created by dudy on 2017/3/22. + */ +public class DynamicProxyDemo { + + + public static void main(String[] args) { + + // 需要代理的接口,被代理类实现的多个接口都必须放在这里 + Class[] proxyInterface = new Class[]{IBusiness.class,IBusiness2.class}; + // 构建AOP的Advice,这里需要传入业务类的实例 + LogInvocationHandler handler = new LogInvocationHandler(new Business()); + //生成代理类的字节码加载器 + ClassLoader loader = DynamicProxyDemo.class.getClassLoader(); + //织入器,织入代码并生成代理类 + IBusiness2 proxyBusiness = (IBusiness2) Proxy.newProxyInstance(loader, proxyInterface, handler); + + proxyBusiness.dosomething2(); + } + + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness.java new file mode 100644 index 0000000000..d18ff447c9 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness.java @@ -0,0 +1,8 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +/** + * Created by dudy on 2017/3/22. + */ +public interface IBusiness { + void dosomething(); +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness2.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness2.java new file mode 100644 index 0000000000..375de2f103 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/IBusiness2.java @@ -0,0 +1,9 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +/** + * Created by dudy on 2017/3/22. + */ +public interface IBusiness2 { + + public void dosomething2(); +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogIntercept.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogIntercept.java new file mode 100644 index 0000000000..5e3c59cf01 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogIntercept.java @@ -0,0 +1,25 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; + +/** + * Created by dudy on 2017/3/22. + */ +public class LogIntercept implements MethodInterceptor { + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy proxy) throws Throwable { + //执行原有的逻辑,注意这里是invokeSuper + Object rev = proxy.invokeSuper(o, objects); + //执行织入的日志 + if (method.getName().equals("dosomething2")){ + System.out.println("CGlib dosometing2....."); + } + + + return rev; + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogInvocationHandler.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogInvocationHandler.java new file mode 100644 index 0000000000..3f3a8ece82 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/DynamicProxy/LogInvocationHandler.java @@ -0,0 +1,30 @@ +package com.dudy.learn01.base.aop.DynamicProxy; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; + +/** + * Created by dudy on 2017/3/22. + * 打印日志的切面 + */ +public class LogInvocationHandler implements InvocationHandler{ + + private Object targer; //目标对象 + + public LogInvocationHandler(Object targer) { + this.targer = targer; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + // 执行原有逻辑 + Object rev = method.invoke(targer, args); + // 执行织入的日志,你可以控制哪些哪些方法执行切入逻辑 + if (method.getName().equals("dosomething2")){ + System.out.println("记录日志"); + } + + return rev; + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/node.md b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/node.md new file mode 100644 index 0000000000..0a9f1b14b9 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/aop/node.md @@ -0,0 +1,7 @@ +## AOP 实现机制 + +### AOP各种实现 +aop就是面向切面编程, 可以从几个层面来实现AOP +编译期 +字节码加载前 +字节码加载后 diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/juc/ThreadLocalTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/juc/ThreadLocalTest.java similarity index 98% rename from group04/1796244932/learn01/src/main/java/com/dudy/learn01/juc/ThreadLocalTest.java rename to group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/juc/ThreadLocalTest.java index e4239ae521..b4d89c8dce 100644 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/juc/ThreadLocalTest.java +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/juc/ThreadLocalTest.java @@ -1,4 +1,4 @@ -package com.dudy.learn01.juc; +package com.dudy.learn01.base.juc; /** * Created by dudy on 2017/3/9. diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/DownloadThread.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..52b14143e0 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/DownloadThread.java @@ -0,0 +1,60 @@ +package com.dudy.learn01.coderising.download; + + +import com.dudy.learn01.coderising.download.api.Connection; + +import java.io.*; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +public class DownloadThread extends Thread{ + + private Connection conn; + private int startPos; + private int endPos; + private RandomAccessFile raf; + //private CyclicBarrier cb; + private CountDownLatch downLatch; + + + public DownloadThread(Connection conn, int startPos, int endPos, + /*CyclicBarrier cb*/ + CountDownLatch downLatch){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; +// this.cb = cb; + this.downLatch = downLatch; + } + public void run(){ + try { + byte[] read = conn.read(startPos, endPos); + + System.out.println("read length: -> "+read.length); + //这里要注意新创建一个RandomAccessFile对象,而不能重复使用download方法中创建的 + raf = new RandomAccessFile(new File("/Users/dudy/Desktop/1.png"), "rw"); + //将写文件的指针指向下载的起始点 + raf.seek(startPos); + raf.write(read, 0, read.length); + + downLatch.countDown(); +// cb.await(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (raf != null){ + raf.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + if (conn != null){ + conn.close(); + } + + } + } +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/FileDownloader.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..92fe70fcff --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/FileDownloader.java @@ -0,0 +1,95 @@ +package com.dudy.learn01.coderising.download; + + + +import com.dudy.learn01.coderising.download.api.Connection; +import com.dudy.learn01.coderising.download.api.ConnectionManager; +import com.dudy.learn01.coderising.download.api.DownloadListener; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.CyclicBarrier; + +public class FileDownloader { + + private static final int THREAD_NUM = 3; + + private String url; + + private DownloadListener listener; + + private ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute() throws IOException { + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + //CyclicBarrier cb = new CyclicBarrier(THREAD_NUM); + CountDownLatch downLatch = new CountDownLatch(THREAD_NUM); + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + for (int i = 0;i < THREAD_NUM; i++){ + + int start=i*length/THREAD_NUM; + int end = (i+1)*length/THREAD_NUM-1; + if(i==THREAD_NUM-1) + { + end =length; + } + + new DownloadThread(cm.open(url),start,end,downLatch).start(); + } + + //cb.await(); + downLatch.await(); + getListener().notifyFinished(); + + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/Connection.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/Connection.java new file mode 100644 index 0000000000..e23cdeec20 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.dudy.learn01.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionException.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..4bfee9d3df --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.dudy.learn01.coderising.download.api; + +public class ConnectionException extends Exception { + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionManager.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..2ca142435e --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/ConnectionManager.java @@ -0,0 +1,13 @@ +package com.dudy.learn01.coderising.download.api; + +import java.io.IOException; +import java.net.MalformedURLException; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException, IOException; +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/DownloadListener.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..79f47e537a --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/api/DownloadListener.java @@ -0,0 +1,4 @@ +package com.dudy.learn01.coderising.download.api; +public interface DownloadListener { + public void notifyFinished(); +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionImpl.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..ffc93c32e0 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,90 @@ +package com.dudy.learn01.coderising.download.impl; + + +import com.dudy.learn01.coderising.download.api.Connection; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ConnectionImpl implements Connection { + + + private HttpURLConnection connection; + + public ConnectionImpl(String url) { + try { + this.connection = (HttpURLConnection) new URL(url).openConnection(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + + InputStream in = connection.getInputStream(); + byte buffer[] = new byte[endPos-startPos+1]; + byte result[] = new byte[endPos-startPos+1]; + int count = 0; // 记录已经读取的数据 + int length = -1 ; + + while ((length = in.read(buffer)) > 0){ + System.arraycopy(buffer,0,result,count,length); + count += length; + } + return result; + } + + @Override + public int getContentLength() { + return connection.getContentLength(); + } + + @Override + public void close() { + if (connection != null){ + connection.disconnect(); + } + } + + public static void main(String[] args) throws Exception{ + //String PATH = "http://demo2.yun.myuclass.com/upload/demo2.yun.myuclass.com/winshare/pagelogo/250617391.png"; + String PATH = "http://www.lgstatic.com/www/static/mycenter/modules/common/img/tou_42952f6.png"; + + URL url = new URL(PATH); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + //conn.setConnectTimeout(5000); + //conn.setRequestMethod("GET"); + //设置头部的参数,表示请求服务器资源的某一部分 + //conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + //设置了上面的头信息后,响应码为206代表请求资源成功,而不再是200 + int code = conn.getResponseCode(); + System.out.println(conn.getContentLength()); + if(code == 200){ + + InputStream is = conn.getInputStream(); + int hasRead = 0; + byte[] buf = new byte[conn.getContentLength()]; + System.out.println(buf.length); + //这里要注意新创建一个RandomAccessFile对象,而不能重复使用download方法中创建的 + RandomAccessFile raf = new RandomAccessFile(new File("/Users/dudy/Desktop/1.png"), "rw"); + //将写文件的指针指向下载的起始点 + raf.seek(0); + + while((hasRead = is.read(buf,0,conn.getContentLength())) > 0) { + System.out.println("hasRead = " + hasRead); + raf.write(buf, 0, hasRead); + } + is.close(); + raf.close(); + conn.disconnect(); + } + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionManagerImpl.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..b4f172cab2 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,27 @@ +package com.dudy.learn01.coderising.download.impl; + + + +import com.dudy.learn01.coderising.download.api.Connection; +import com.dudy.learn01.coderising.download.api.ConnectionException; +import com.dudy.learn01.coderising.download.api.ConnectionManager; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + + private Connection connection = null; + + @Override + public Connection open(String url) throws ConnectionException, IOException { + + connection = new ConnectionImpl(url); + + return connection; + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/AttributeInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..c33bdd2c66 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/CodeAttr.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..2bd2185db5 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,69 @@ +package com.dudy.learn01.coderising.jvm.attr; + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.coderising.jvm.cmd.ByteCodeCommand; +import com.dudy.learn01.coderising.jvm.constant.ConstantPool; +import com.dudy.learn01.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){ + + return null; + } + + + 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 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){ + + return null; + } + + 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableItem.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..ac72775739 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableTable.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..c104c3a648 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,40 @@ +package com.dudy.learn01.coderising.jvm.attr; + +import com.dudy.learn01.coderising.jvm.constant.ConstantPool; +import com.dudy.learn01.coderising.jvm.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){ + + return null; + } + + + 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/StackMapTable.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..dcb5f3f2c1 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.dudy.learn01.coderising.jvm.attr; + + +import com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/AccessFlag.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..95ed555e0e --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassFile.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..ae9201c6fd --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,102 @@ +package com.dudy.learn01.coderising.jvm.clz; + +import com.dudy.learn01.coderising.jvm.constant.ClassInfo; +import com.dudy.learn01.coderising.jvm.constant.ConstantPool; +import com.dudy.learn01.coderising.jvm.field.Field; +import com.dudy.learn01.coderising.jvm.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){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassIndex.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..63a74c95a5 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.dudy.learn01.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/BiPushCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..2cb178133f --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/ByteCodeCommand.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..dd0c751d41 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,130 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.coderising.jvm.constant.ConstantInfo; +import com.dudy.learn01.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 this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/CommandParser.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..e575214e89 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,86 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; + +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) { + + + return null; + } + + 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetFieldCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..f8288f81ec --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetStaticFieldCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..2a60aaf57c --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.dudy.learn01.coderising.jvm.cmd; + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeSpecialCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..bae82fa144 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,21 @@ +package com.dudy.learn01.coderising.jvm.cmd; + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeVirtualCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..3247d36ed9 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.dudy.learn01.coderising.jvm.cmd; + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/LdcCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..4615d143de --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,28 @@ +package com.dudy.learn01.coderising.jvm.cmd; +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.coderising.jvm.constant.ConstantInfo; +import com.dudy.learn01.coderising.jvm.constant.ConstantPool; +import com.dudy.learn01.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 = (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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NewObjectCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..611c503bce --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.dudy.learn01.coderising.jvm.cmd; + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NoOperandCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..12dc9aee67 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,22 @@ +package com.dudy.learn01.coderising.jvm.cmd; + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/OneOperandCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..097e83239a --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/PutFieldCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..4a819d1e5a --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + +import com.dudy.learn01.coderising.jvm.clz.ClassFile; +import com.dudy.learn01.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/TwoOperandCmd.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..132c9313d2 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,64 @@ +package com.dudy.learn01.coderising.jvm.cmd; + + +import com.dudy.learn01.coderising.jvm.constant.*; +import com.dudy.learn01.coderising.jvm.clz.ClassFile; + +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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ClassInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..7e858fddd8 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..eff4475e02 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.dudy.learn01.coderising.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantPool.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..26637e950b --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/FieldRefInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7d80c44569 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/MethodRefInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f19e35e7a0 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NameAndTypeInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..02715297f1 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NullConstantInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..86661fd20d --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.dudy.learn01.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/StringInfo.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..61449b0d20 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/UTF8Info.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..39c51f8859 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.dudy.learn01.coderising.jvm.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.visistUTF8(this); + + } + + + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/field/Field.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..1da61a8ab8 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.dudy.learn01.coderising.jvm.field; + +import com.dudy.learn01.coderising.jvm.constant.ConstantPool; +import com.dudy.learn01.coderising.jvm.constant.UTF8Info; +import com.dudy.learn01.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 desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ByteCodeIterator.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..f5808ce0d0 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package com.dudy.learn01.coderising.jvm.loader; + +import com.dudy.learn01.coderising.jvm.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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ClassFileLoader.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..49d296a9b6 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,132 @@ +package com.dudy.learn01.coderising.jvm.loader; + +import com.dudy.learn01.coderising.jvm.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", 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/test/EmployeeV1.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..33731cf429 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.dudy.learn01.coderising.jvm.test; + +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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/util/Util.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..44b3e2ee01 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.dudy.learn01.coderising.jvm.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= capacity) { + removeLastNode(); + } + + addNewNodeToHeader(node); + } + } + + private void addNewNodeToHeader(Node node) { + // TODO Auto-generated method stub + + if (first == null) { + first = node; + last = node; + currentSize++; + return; + } + + node.next = first; + if(first.next == null){ + last.prev = node; + } else { + first.prev = node; + } + first = node; + currentSize++; + + } + + private void removeLastNode() { + // TODO Auto-generated method stub + last.prev.next = null; + last = last.prev; + currentSize--; + } + + private void moveNodeToHead(Node node) { + + if(first.pageNum == node.pageNum){ + return; + } + + if(last.pageNum == node.pageNum){ + Node pLast = last.prev; + pLast.next = null; + + last.next = first; + last.prev = null; + + first.prev = last; + first = last; + last = pLast; + + return; + } + + node.prev.next = node.next; + node.next.prev = node.prev; + node.prev = null; + node.next = first; + first.prev = node; + first = node; + + } + + private Node find(int pageNum) { + Node n = first; + for (int i = 0; i < currentSize; i++) { + if (n.pageNum == pageNum) { + return n; + } + + n = n.next; + } + + return null; + } + + 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(","); + } + } + + StringBuilder reverse = new StringBuilder(); + Node n = last; + while(n != null){ + reverse.append(n.pageNum); + n = n.prev; + if(n != null){ + reverse.append(","); + } + } + System.out.println("buffer: "+ buffer.toString()); + System.out.println("reverse: " + reverse.toString()); + return buffer.toString(); + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/LRUPageFrameTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/LRUPageFrameTest.java new file mode 100644 index 0000000000..539e0d9af3 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/LRUPageFrameTest.java @@ -0,0 +1,33 @@ +package com.dudy.learn01.data_structure.list; + +import com.dudy.learn01.data_structure.list.LRUPageFrame; +import org.junit.Assert; +import org.junit.Test; + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyArrayList.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyArrayList.java similarity index 94% rename from group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyArrayList.java rename to group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyArrayList.java index 5a8e82aaaf..ee7a336948 100644 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyArrayList.java +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyArrayList.java @@ -1,4 +1,7 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.list; + +import com.dudy.learn01.data_structure.MyIterator; +import com.dudy.learn01.data_structure.MyList; import java.util.Arrays; diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyLinkedList.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyLinkedList.java similarity index 97% rename from group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyLinkedList.java rename to group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyLinkedList.java index a425f54e81..f5b0b2f9fc 100644 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyLinkedList.java +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/list/MyLinkedList.java @@ -1,6 +1,9 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.list; +import com.dudy.learn01.data_structure.MyIterator; +import com.dudy.learn01.data_structure.MyList; + import java.util.LinkedList; /** diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/CircleQueue.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/CircleQueue.java new file mode 100644 index 0000000000..af410daea1 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/CircleQueue.java @@ -0,0 +1,78 @@ +package com.dudy.learn01.data_structure.queue; + +import java.util.Random; + +/** + * 用数组实现循环队列 + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int tear = 0; + + public boolean isEmpty() { + return tear == front && elementData[0] == null; + } + + public int size() { + if(tear == front && elementData[0]!= null){ + return DEFAULT_SIZE; + } else { + return (tear - front + DEFAULT_SIZE) % DEFAULT_SIZE; + } + } + + public boolean full(){ + return tear == front && elementData[0] != null; + } + + + public void enQueue(E data) { + if(full()){ + System.out.println("队列已满"); + } else { + elementData[tear] = data; + tear = (tear + 1) % DEFAULT_SIZE; + } + } + + public E deQueue() { + if(isEmpty()) return null; + E e = (E) elementData[front]; + elementData[front] = null; + front = (front + 1) % DEFAULT_SIZE; + return e; + } + + public static void main(String[] args) { + CircleQueue queue = new CircleQueue<>(); + Random r = new Random(); + queue.enQueue(1); + queue.enQueue(3); + queue.enQueue(4); + queue.enQueue(6); + queue.enQueue(7); + + System.out.println(queue.size()); + for (int i = 0; i < 10; i++) { + queue.enQueue(r.nextInt(100)); + } + + System.out.println("size = " + queue.size()); + + + for(int i=0;i < 11 ; i++){ + System.out.print(queue.deQueue() + ","); + } + + System.out.println("size = " + queue.size()); + + } +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/Josephus.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/Josephus.java new file mode 100644 index 0000000000..9ea3f93ed8 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/Josephus.java @@ -0,0 +1,33 @@ +package com.dudy.learn01.data_structure.queue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +/** + * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 + */ +public class Josephus { + + public static List execute(int n, int m) { + + List list = new ArrayList<>(); + Queue queue = new ArrayBlockingQueue<>(n); + for(int i = 0; i< n; i++){ + queue.add(i); + } + int loop = 1; + while(!queue.isEmpty()){ + Integer value = queue.poll(); + if(loop % m == 0){ + list.add(value);loop = 1; + } else{ + queue.add(value);loop++; + } + } + return list; + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/JosephusTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/JosephusTest.java new file mode 100644 index 0000000000..bbf4c906b1 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/JosephusTest.java @@ -0,0 +1,26 @@ +package com.dudy.learn01.data_structure.queue; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + System.out.println(Josephus.execute(7, 2).toString()); + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/MyQueue.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/MyQueue.java new file mode 100644 index 0000000000..6c816b2802 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/MyQueue.java @@ -0,0 +1,25 @@ +package com.dudy.learn01.data_structure.queue; + +import com.dudy.learn01.data_structure.list.MyLinkedList; + +public class MyQueue { + + private MyLinkedList elementData = new MyLinkedList(); + + public void enQueue(Object o){ + elementData.addLast(o); + } + + public Object deQueue(){ + + return elementData.removeFirst(); + } + + public boolean isEmpty(){ + return elementData.size() == 0 ; + } + + public int size(){ + return elementData.size(); + } +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/QueueWithTwoStacks.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..13d02e879d --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/QueueWithTwoStacks.java @@ -0,0 +1,58 @@ +package com.dudy.learn01.data_structure.queue; + +import java.util.Random; +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return stack1.size() + stack2.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + + if (isEmpty()) { + return null; + } + if (stack2.size() == 0) { + for (int i = 0; i < stack1.size(); i++) { + stack2.push(stack1.pop()); + } + } + + return stack2.pop(); + } + + public static void main(String[] args) { + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + Random r = new Random(); + int loop = r.nextInt(15); + System.out.println("loop = " + loop); + for (int i = 0; i < loop; i++) { + queue.enQueue(r.nextInt(100)); + } + System.out.println("size = " + queue.size()); + while (queue.size() > 0) { + System.out.print(queue.deQueue() + ","); + } + } + +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExpr.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExpr.java new file mode 100644 index 0000000000..4ad14f5cea --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExpr.java @@ -0,0 +1,102 @@ +package com.dudy.learn01.data_structure.queue.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + Stack number = new Stack(); + Stack opt = new Stack(); + + public InfixExpr(String expr) { + + this.expr = expr; + } + + public float evaluate() { + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + + for (Token token: tokens){ + if (token.isOperator()){ + if (opt.isEmpty()){ + opt.push(token); + } else { + while (!opt.isEmpty() && + !token.hasHigherPriority(opt.peek())){ + Token prevOperator = opt.pop(); + calculator(number.pop(),number.pop(),prevOperator.value); + } + opt.push(token); + + } + } + + if (token.isNumber()){ + number.push(token); + } + } + + while (!opt.isEmpty()){ + calculator(number.pop(), number.pop(),opt.pop().value); + } + + + +// for (int i = 0; i < tokens.size(); i++) { +// Token token = tokens.get(i); +// if (token.isNumber()) { +// number.push(token); +// } +// +// if (token.isOperator()) { +// if (opt.isEmpty()) { +// opt.push(token); continue; +// } +// +// if (!opt.isEmpty() && !token.hasHigherPriority(opt.peek())) { +// calculator(tokens.get(++i), number.pop(), token.value); +// +// } else { +// opt.push(token); +// } +// } +// } +// +// while(!opt.empty()){ +// +// calculator(number.pop(), number.pop(), opt.pop().value); +// } + + return Float.parseFloat(number.pop().value); + } + + /** + * + * @param token 第二个操作数 + * @param pop 第一个操作数 + * @param op 运算符 + */ + private void calculator(Token token, Token pop, String op) { + Integer number1 = Integer.parseInt(pop.value); + Integer number2 = Integer.parseInt(token.value); + Integer value = null; + if ("*".equals(op)) { + value = number1 * number2; + } + if ("/".equals(op)) { + value = number1 / number2; + } + if ("-".equals(op)) { + value = number1 - number2; + } + if ("+".equals(op)) { + value = number1 + number2; + } + + number.push(new Token(2,value+"")); + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExprTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExprTest.java new file mode 100644 index 0000000000..4a4fa8981c --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixExprTest.java @@ -0,0 +1,51 @@ +package com.dudy.learn01.data_structure.queue.expr; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfix.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfix.java new file mode 100644 index 0000000000..9c958ac169 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfix.java @@ -0,0 +1,44 @@ +package com.dudy.learn01.data_structure.queue.expr; + +import java.util.*; + +public class InfixToPostfix { + + public static List convert(String expr) { + + List tokens = new ArrayList<>(); + + Stack optStack = new Stack<>(); + TokenParser parser = new TokenParser(); + List list = parser.parse(expr); + for (int i = 0;i < list.size(); i++){ + Token token = list.get(i); + if(token.isNumber()){ + tokens.add(token);continue; + } + + if (token.isOperator()){ + if (optStack.isEmpty()){ + optStack.push(token);continue; + } + + if (token.hasHigherPriority(optStack.peek())){ + tokens.add(list.get(++i)); + tokens.add(token); + } else { + tokens.add(optStack.pop()); + optStack.push(token); + } + } + } + + while (!optStack.isEmpty()){ + tokens.add(optStack.pop()); + } + + return tokens; + } + + + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfixTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..fd60670c1f --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/InfixToPostfixTest.java @@ -0,0 +1,27 @@ +package com.dudy.learn01.data_structure.queue.expr; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +/** + * Created by dudy on 2017/5/7. + */ +public class InfixToPostfixTest { + + + @Test + public void testEvaluate() { + List tokens = InfixToPostfix.convert("2+3*4+5"); + System.out.println(tokens); + + Assert.assertEquals("[2, 3, 4, *, +, 5, +]", tokens.toString()); + + //10 2 3 * - 50 + + List list1 = InfixToPostfix.convert("10-2*3+50"); + System.out.println(list1); + + Assert.assertEquals("[10, 2, 3, *, -, 50, +]", list1.toString()); + } +} diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExpr.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExpr.java new file mode 100644 index 0000000000..6c679d93ca --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExpr.java @@ -0,0 +1,55 @@ +package com.dudy.learn01.data_structure.queue.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + Stack optStack = new Stack<>(); + Stack numStack = new Stack<>(); + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(Float.parseFloat(token.value)); + } else if (token.isOperator()) { + Float num2 = numStack.pop(); + Float num1 = numStack.pop(); + Float value = calculator(num1, num2, token.value); + numStack.push(value); + } + } + + + return numStack.pop(); + } + + private Float calculator(Float num1, Float num2, String op) { + Float res = 0.0f; + + if ("*".equals(op)) { + res = num1 * num2; + } else if ("/".equals(op)) { + res = num1 / num2; + } else if ("-".equals(op)) { + res = num1 - num2; + } else if ("+".equals(op)) { + res = num1 + num2; + } else { + System.out.println("opt is not support..."); + } + + return res; + } + + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExprTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExprTest.java new file mode 100644 index 0000000000..4f61074c6e --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PostfixExprTest.java @@ -0,0 +1,39 @@ +package com.dudy.learn01.data_structure.queue.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); + } + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExpr.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExpr.java new file mode 100644 index 0000000000..cf9206df6d --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExpr.java @@ -0,0 +1,68 @@ +package com.dudy.learn01.data_structure.queue.expr; + +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + /** + * 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素), + * 并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。 + * 例如前缀表达式“- × + 3 4 5 6”: + * (1) 从右至左扫描,将6、5、4、3压入堆栈; + * (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈; + * (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈; + * (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 + * 可以看出,用计算机计算前缀表达式的值是很容易的。 + * + * @return + */ + public float evaluate() { + float result = 0; + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack optStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (int i = tokens.size() - 1; i >= 0; i--) { + Token token = tokens.get(i); + if (token.isNumber()) { + numStack.push(Float.parseFloat(token.value)); + } else if (token.isOperator()) { + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float sum = calculator(num1, num2, token.value); + numStack.push(sum); + } + } + + + return numStack.pop(); + } + + private Float calculator(Float num1, Float num2, String op) { + Float res = 0.0f; + + if ("*".equals(op)) { + res = num1 * num2; + } else if ("/".equals(op)) { + res = num1 / num2; + } else if ("-".equals(op)) { + res = num1 - num2; + } else if ("+".equals(op)) { + res = num1 + num2; + } else { + System.out.println("opt is not support..."); + } + + return res; + } + + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExprTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExprTest.java new file mode 100644 index 0000000000..59dad95f20 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.dudy.learn01.data_structure.queue.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); + } + + + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/Token.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/Token.java new file mode 100644 index 0000000000..b3bbbdfc28 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/Token.java @@ -0,0 +1,49 @@ +package com.dudy.learn01.data_structure.queue.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParser.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParser.java new file mode 100644 index 0000000000..4af3564656 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParser.java @@ -0,0 +1,56 @@ +package com.dudy.learn01.data_structure.queue.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); + } +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParserTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParserTest.java new file mode 100644 index 0000000000..8943545b7a --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/queue/expr/TokenParserTest.java @@ -0,0 +1,38 @@ +package com.dudy.learn01.data_structure.queue.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"); + + 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()); + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/MyStack.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/MyStack.java new file mode 100644 index 0000000000..e44ef3d40d --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/MyStack.java @@ -0,0 +1,29 @@ +package com.dudy.learn01.data_structure.stack; + +import com.dudy.learn01.data_structure.list.MyArrayList; + +public class MyStack { + private MyArrayList elementData = new MyArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + + Object o = elementData.get(elementData.size()-1); + elementData.remove(elementData.size()); + return o; + } + + public Object peek(){ + + return elementData.get(elementData.size()-1); + } + public boolean isEmpty(){ + return elementData.size() == 0; + } + public int size(){ + return elementData.size(); + } +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtil.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtil.java new file mode 100644 index 0000000000..8d1b6c8f64 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtil.java @@ -0,0 +1,120 @@ +package com.dudy.learn01.data_structure.stack; + +import java.util.Collections; +import java.util.Stack; + +public class StackUtil { + + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + + if(s == null || s.isEmpty()){ + return; + } + + //Collections.reverse(s); + Stack stack = new Stack<>(); + while(!s.isEmpty()){ + stack.push(s.pop()); + } + System.out.println(stack.toString()); + while(!stack.isEmpty()){ + Integer pop = stack.pop(); + addToBottom(s,pop); + } + + + } + + private static void addToBottom(Stack s, Integer pop) { + // TODO Auto-generated method stub + if(s.isEmpty()){ + s.push(pop); + } else { + Integer temp = s.pop(); + addToBottom(s, pop); + s.push(temp); + } + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Integer o) { + if(s == null || s.isEmpty() ){ + return; + } + + Stack tempStack = new Stack<>(); + while(!s.isEmpty()){ + Integer value = s.pop(); + if(o.equals(value)){ + break; + } + tempStack.push(value); + } + + while(!tempStack.isEmpty()){ + s.push(tempStack.pop()); + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Integer[] getTop(Stack s,int len) { + Integer[] o = new Integer[len]; + for (int i = 0; i < o.length; i++) { + o[i] = s.pop(); + } + + for (int i = o.length-1; i >= 0; i--) { + s.push(o[i]); + } + + return o; + } + /** + * 字符串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){ + char[] c = s.toCharArray(); + + Stack stack = new Stack(); + for (int i = 0; i< c.length; i++){ + char c1 = c[i]; + if (c1 == '(' || c1 == '[' || c1 == '{'){ + stack.push(c1); + } + + if (!stack.isEmpty()){ + if ( (c1 == ')' && stack.peek() == '(') + || (c1 == ']' && stack.peek() == '[') + || (c1 == '}' && stack.peek() == '{' )){ + stack.pop(); + } + } + } + + return stack.isEmpty(); + } + + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtilTest.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtilTest.java new file mode 100644 index 0000000000..d819853f98 --- /dev/null +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/stack/StackUtilTest.java @@ -0,0 +1,64 @@ +package com.dudy.learn01.data_structure.stack; +import java.util.Stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyBinaryTree.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/tree/MyBinaryTree.java similarity index 96% rename from group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyBinaryTree.java rename to group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/tree/MyBinaryTree.java index cfc06bc0d2..88fbd9fc26 100644 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/base/MyBinaryTree.java +++ b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/data_structure/tree/MyBinaryTree.java @@ -1,4 +1,4 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.tree; public class MyBinaryTree { diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/DownloadThread.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/DownloadThread.java deleted file mode 100644 index 97ca01e13b..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/DownloadThread.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.dudy.learn01.download; - -import com.dudy.learn01.download.api.Connection; - -import java.io.*; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.CyclicBarrier; - -public class DownloadThread extends Thread{ - - private Connection conn; - private int startPos; - private int endPos; - private RandomAccessFile raf; - //private CyclicBarrier cb; - private CountDownLatch downLatch; - - - public DownloadThread(Connection conn, int startPos, int endPos, - /*CyclicBarrier cb*/ - CountDownLatch downLatch){ - - this.conn = conn; - this.startPos = startPos; - this.endPos = endPos; -// this.cb = cb; - this.downLatch = downLatch; - } - public void run(){ - try { - byte[] read = conn.read(startPos, endPos); - - System.out.println("read length: -> "+read.length); - //这里要注意新创建一个RandomAccessFile对象,而不能重复使用download方法中创建的 - raf = new RandomAccessFile(new File("/Users/dudy/Desktop/1.png"), "rw"); - //将写文件的指针指向下载的起始点 - raf.seek(startPos); - raf.write(read, 0, read.length); - - downLatch.countDown(); -// cb.await(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (raf != null){ - raf.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - if (conn != null){ - conn.close(); - } - - } - } -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/FileDownloader.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/FileDownloader.java deleted file mode 100644 index eee5825b84..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/FileDownloader.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.dudy.learn01.download; - -import com.dudy.learn01.download.api.Connection; -import com.dudy.learn01.download.api.ConnectionManager; -import com.dudy.learn01.download.api.DownloadListener; - -import java.io.IOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.CyclicBarrier; - -public class FileDownloader { - - private static final int THREAD_NUM = 3; - - private String url; - - private DownloadListener listener; - - private ConnectionManager cm; - - - public FileDownloader(String _url) { - this.url = _url; - - } - - public void execute() throws IOException { - // 在这里实现你的代码, 注意: 需要用多线程实现下载 - // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 - // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) - // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 - // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 - // 具体的实现思路: - // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 - // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 - // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 - // 3. 把byte数组写入到文件中 - // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 - - // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 - Connection conn = null; - try { - //CyclicBarrier cb = new CyclicBarrier(THREAD_NUM); - CountDownLatch downLatch = new CountDownLatch(THREAD_NUM); - - conn = cm.open(this.url); - - int length = conn.getContentLength(); - - for (int i = 0;i < THREAD_NUM; i++){ - - int start=i*length/THREAD_NUM; - int end = (i+1)*length/THREAD_NUM-1; - if(i==THREAD_NUM-1) - { - end =length; - } - - new DownloadThread(cm.open(url),start,end,downLatch).start(); - } - - //cb.await(); - downLatch.await(); - getListener().notifyFinished(); - - } catch (Exception e) { - e.printStackTrace(); - }finally{ - if(conn != null){ - conn.close(); - } - } - - - - - } - - public void setListener(DownloadListener listener) { - this.listener = listener; - } - - - - public void setConnectionManager(ConnectionManager ucm){ - this.cm = ucm; - } - - public DownloadListener getListener(){ - return this.listener; - } - -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/Connection.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/Connection.java deleted file mode 100644 index 513c0004e9..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/Connection.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dudy.learn01.download.api; - -import java.io.IOException; - -public interface Connection { - /** - * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * @param startPos 开始位置, 从0开始 - * @param endPos 结束位置 - * @return - */ - public byte[] read(int startPos,int endPos) throws IOException; - /** - * 得到数据内容的长度 - * @return - */ - public int getContentLength(); - - /** - * 关闭连接 - */ - public void close(); -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionException.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionException.java deleted file mode 100644 index 71af9bf06d..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionException.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.dudy.learn01.download.api; - -public class ConnectionException extends Exception { - -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionManager.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionManager.java deleted file mode 100644 index 5f4777f6e0..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/ConnectionManager.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dudy.learn01.download.api; - -import java.io.IOException; -import java.net.MalformedURLException; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * @param url - * @return - */ - public Connection open(String url) throws ConnectionException, IOException; -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/DownloadListener.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/DownloadListener.java deleted file mode 100644 index fa3b5bead0..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.dudy.learn01.download.api; - -public interface DownloadListener { - public void notifyFinished(); -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionImpl.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionImpl.java deleted file mode 100644 index 5eb6b45d41..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.dudy.learn01.download.impl; - -import com.dudy.learn01.download.api.Connection; - -import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ConnectionImpl implements Connection { - - - private HttpURLConnection connection; - - public ConnectionImpl(String url) { - try { - this.connection = (HttpURLConnection) new URL(url).openConnection(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public byte[] read(int startPos, int endPos) throws IOException { - - connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - - InputStream in = connection.getInputStream(); - byte buffer[] = new byte[endPos-startPos+1]; - byte result[] = new byte[endPos-startPos+1]; - int count = 0; // 记录已经读取的数据 - int length = -1 ; - - while ((length = in.read(buffer)) > 0){ - System.arraycopy(buffer,0,result,count,length); - count += length; - } - return result; - } - - @Override - public int getContentLength() { - return connection.getContentLength(); - } - - @Override - public void close() { - if (connection != null){ - connection.disconnect(); - } - } - - public static void main(String[] args) throws Exception{ - //String PATH = "http://demo2.yun.myuclass.com/upload/demo2.yun.myuclass.com/winshare/pagelogo/250617391.png"; - String PATH = "http://www.lgstatic.com/www/static/mycenter/modules/common/img/tou_42952f6.png"; - - URL url = new URL(PATH); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - //conn.setConnectTimeout(5000); - //conn.setRequestMethod("GET"); - //设置头部的参数,表示请求服务器资源的某一部分 - //conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - //设置了上面的头信息后,响应码为206代表请求资源成功,而不再是200 - int code = conn.getResponseCode(); - System.out.println(conn.getContentLength()); - if(code == 200){ - - InputStream is = conn.getInputStream(); - int hasRead = 0; - byte[] buf = new byte[conn.getContentLength()]; - System.out.println(buf.length); - //这里要注意新创建一个RandomAccessFile对象,而不能重复使用download方法中创建的 - RandomAccessFile raf = new RandomAccessFile(new File("/Users/dudy/Desktop/1.png"), "rw"); - //将写文件的指针指向下载的起始点 - raf.seek(0); - - while((hasRead = is.read(buf,0,conn.getContentLength())) > 0) { - System.out.println("hasRead = " + hasRead); - raf.write(buf, 0, hasRead); - } - is.close(); - raf.close(); - conn.disconnect(); - } - } - -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionManagerImpl.java b/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index 809f98d91b..0000000000 --- a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dudy.learn01.download.impl; - -import com.dudy.learn01.download.api.Connection; -import com.dudy.learn01.download.api.ConnectionException; -import com.dudy.learn01.download.api.ConnectionManager; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; - -public class ConnectionManagerImpl implements ConnectionManager { - - - private Connection connection = null; - - @Override - public Connection open(String url) throws ConnectionException, IOException { - - connection = new ConnectionImpl(url); - - return connection; - } - -} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayListTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayListTest.java similarity index 87% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayListTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayListTest.java index 5c6edd8fec..a18c00ecd8 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayListTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayListTest.java @@ -1,5 +1,7 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; +import com.dudy.learn01.data_structure.MyIterator; +import com.dudy.learn01.data_structure.list.MyArrayList; import org.junit.Test; import java.util.ArrayList; diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayUtilTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayUtilTest.java similarity index 95% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayUtilTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayUtilTest.java index 25fd306dc9..993d0df8e2 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyArrayUtilTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyArrayUtilTest.java @@ -1,5 +1,6 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; +import com.dudy.learn01.data_structure.array.MyArrayUtil; import org.junit.Test; /** diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyBinaryTreeTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyBinaryTreeTest.java similarity index 84% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyBinaryTreeTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyBinaryTreeTest.java index 65bee44580..27d533d5a8 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyBinaryTreeTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyBinaryTreeTest.java @@ -1,9 +1,8 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; +import com.dudy.learn01.data_structure.tree.MyBinaryTree; import org.junit.Test; -import static org.junit.Assert.*; - /** * Created by dudy on 2017/2/21. */ diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyLinkedListTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyLinkedListTest.java similarity index 94% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyLinkedListTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyLinkedListTest.java index cce7a1c163..ff0b6e0cb0 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyLinkedListTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyLinkedListTest.java @@ -1,7 +1,9 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; import java.util.LinkedList; +import com.dudy.learn01.data_structure.MyIterator; +import com.dudy.learn01.data_structure.list.MyLinkedList; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyQueueTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyQueueTest.java similarity index 79% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyQueueTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyQueueTest.java index de8d683abe..2f3116eb63 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyQueueTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyQueueTest.java @@ -1,9 +1,8 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; +import com.dudy.learn01.data_structure.queue.MyQueue; import org.junit.Test; -import static org.junit.Assert.*; - /** * Created by dudy on 2017/2/20. */ diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyStackTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyStackTest.java similarity index 90% rename from group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyStackTest.java rename to group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyStackTest.java index 51175953b0..848180b498 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/base/MyStackTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/data_structure/base/MyStackTest.java @@ -1,11 +1,10 @@ -package com.dudy.learn01.base; +package com.dudy.learn01.data_structure.base; +import com.dudy.learn01.data_structure.stack.MyStack; import org.junit.Test; import java.util.Stack; -import static org.junit.Assert.*; - /** * Created by dudy on 2017/2/20. */ diff --git a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/download/FileDownloaderTest.java b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/download/FileDownloaderTest.java index fc427e2171..7e9fe3b54b 100644 --- a/group04/1796244932/learn01/src/test/java/com/dudy/learn01/download/FileDownloaderTest.java +++ b/group04/1796244932/learn01/src/test/java/com/dudy/learn01/download/FileDownloaderTest.java @@ -1,8 +1,10 @@ package com.dudy.learn01.download; -import com.dudy.learn01.download.api.ConnectionManager; -import com.dudy.learn01.download.api.DownloadListener; -import com.dudy.learn01.download.impl.ConnectionManagerImpl; + +import com.dudy.learn01.coderising.download.FileDownloader; +import com.dudy.learn01.coderising.download.api.ConnectionManager; +import com.dudy.learn01.coderising.download.api.DownloadListener; +import com.dudy.learn01.coderising.download.impl.ConnectionManagerImpl; import org.junit.Test; diff --git a/group04/349184132/Study/src/com/coderising/download/DownloadThread.java b/group04/349184132/Study/src/com/coderising/download/DownloadThread.java deleted file mode 100644 index 2b806a7f44..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/DownloadThread.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.coderising.download; - -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; - -import com.coderising.download.api.Connection; - -public class DownloadThread extends Thread { - Connection conn; - int startPos; - int endPos; - int threadId = 0; - CyclicBarrier barrier; - - public DownloadThread(CyclicBarrier barrier, Connection conn, int threadId, - int startPos, int endPos) { - this.barrier = barrier; - this.conn = conn; - this.threadId = threadId; - this.startPos = startPos; - this.endPos = endPos; - } - - public void run() { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile("yunpan.exe", "rwd"); - - raf.seek(startPos); - - byte[] buffer = conn.read(startPos, endPos); - - raf.write(buffer, 0, buffer.length); - raf.close(); - barrier.await(); - System.out.println("threadId" + threadId +"download success !"); - - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (BrokenBarrierException e) { - e.printStackTrace(); - } - - } -} diff --git a/group04/349184132/Study/src/com/coderising/download/FileDownloader.java b/group04/349184132/Study/src/com/coderising/download/FileDownloader.java deleted file mode 100644 index 281dafde96..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/FileDownloader.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.coderising.download; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.net.URL; -import java.util.concurrent.CyclicBarrier; - -import com.coderising.download.api.Connection; -import com.coderising.download.api.ConnectionException; -import com.coderising.download.api.ConnectionManager; -import com.coderising.download.api.DownloadListener; - -public class FileDownloader { - - boolean isFinished = false; - - String url; - - DownloadListener listener; - - ConnectionManager cm; - - private static final int THREAD_NUM = 3; - - public FileDownloader(String _url) { - this.url = _url; - - } - - public void execute() { - // 在这里实现你的代码, 注意: 需要用多线程实现下载 - // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 - // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, - // endPos来指定) - // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 - // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 - // 具体的实现思路: - // 1. 需要调用ConnectionManager的open方法打开连接, - // 然后通过Connection.getContentLength方法获得文件的长度 - // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 - // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 - // 3. 把byte数组写入到文件中 - // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 - - // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 - - CyclicBarrier barrier = new CyclicBarrier(THREAD_NUM,new Runnable(){ - - @Override - public void run() { - listener.notifyFinished(); - } - - }); - - Connection conn = null; - try { - conn = cm.open(url); - - int length = conn.getContentLength(); - System.out.println("----文件总长度---- :" + length); - RandomAccessFile raf = new RandomAccessFile("yunpan.exe","rwd"); - - raf.setLength(length); - - int block = length / THREAD_NUM; - - for(int threadId = 0; threadId < THREAD_NUM; threadId++){ - int startPos = (threadId) * block; - int endPos = (threadId + 1 ) * block -1; - if(threadId-1 == THREAD_NUM){ - endPos = length; - } - System.out.println("---threadId--- :" + threadId + - "---startIndex---" + startPos + - "---endIndex---" + endPos); - //开启 线程 - URL u = new URL(url); - new DownloadThread(barrier,cm.open(url),threadId,startPos,endPos).start(); - } - - - } catch (ConnectionException e) { - - e.printStackTrace(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally{ - if(conn!=null){ - conn.close(); - } - } - - } - - public void setListener(DownloadListener listener) { - this.listener = listener; - } - - public void setConnectionManager(ConnectionManager ucm) { - this.cm = ucm; - } - - public DownloadListener getListener() { - return this.listener; - } - - -} diff --git a/group04/349184132/Study/src/com/coderising/download/FileDownloaderTest.java b/group04/349184132/Study/src/com/coderising/download/FileDownloaderTest.java deleted file mode 100644 index 604712d2a9..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/FileDownloaderTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.coderising.download; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.coderising.download.api.ConnectionManager; -import com.coderising.download.api.DownloadListener; -import com.coderising.download.impl.ConnectionManagerImpl; - -public class FileDownloaderTest { - boolean downloadFinished = false; - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testDownload() { - - String url = "http://down.360safe.com/yunpan/360wangpan_setup.exe"; - FileDownloader downloader = new FileDownloader(url); - - - ConnectionManager cm = new ConnectionManagerImpl(); - downloader.setConnectionManager(cm); - - downloader.setListener(new DownloadListener() { - @Override - public void notifyFinished() { - downloadFinished = true; - } - - }); - - - downloader.execute(); - -// 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - //休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); - - - - } - -} diff --git a/group04/349184132/Study/src/com/coderising/download/api/ConnectionException.java b/group04/349184132/Study/src/com/coderising/download/api/ConnectionException.java deleted file mode 100644 index 1599be1296..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/api/ConnectionException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.coderising.download.api; - -public class ConnectionException extends Exception { - - public ConnectionException(String string) { - // TODO 自动生成的构造函数存根 - } - - -} diff --git a/group04/349184132/Study/src/com/coderising/download/impl/ConnectionImpl.java b/group04/349184132/Study/src/com/coderising/download/impl/ConnectionImpl.java deleted file mode 100644 index 3ad903146b..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.coderising.download.impl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; - -import com.coderising.download.api.Connection; - -public class ConnectionImpl implements Connection{ - private HttpURLConnection conn ; - public ConnectionImpl(HttpURLConnection conn) { - this.conn = conn; - } - @Override - public byte[] read(int startPos, int endPos) throws IOException { - conn.setRequestMethod("GET"); - conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - conn.setConnectTimeout(5000); - - InputStream is = conn.getInputStream(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - int length = 0; - byte[] buffer = new byte[1024]; - while(-1 != ( length = is.read(buffer))){ - bos.write(buffer,0,length); - } - bos.flush(); - is.close(); - bos.close(); - - - return bos.toByteArray(); - } - - @Override - public int getContentLength() { - - return conn.getContentLength(); - } - - @Override - public void close() { - if(conn!=null){ - conn = null; - } - } - -} diff --git a/group04/349184132/Study/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group04/349184132/Study/src/com/coderising/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index 9132787cf8..0000000000 --- a/group04/349184132/Study/src/com/coderising/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.coderising.download.impl; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; - -import com.coderising.download.api.Connection; -import com.coderising.download.api.ConnectionException; -import com.coderising.download.api.ConnectionManager; - -public class ConnectionManagerImpl implements ConnectionManager { - @Override - public Connection open(String url) throws ConnectionException { - - URL u; - HttpURLConnection hc ; - try { - u = new URL(url); - hc = (HttpURLConnection) u.openConnection(); - Connection conn = new ConnectionImpl(hc);; - return conn; - } catch (MalformedURLException e) { - e.printStackTrace(); - - } catch (IOException e) { - e.printStackTrace(); - } - return null; - - - - - - } - -} diff --git a/group04/349184132/Study/src/com/coderising/jvm/Method/Method.java b/group04/349184132/Study/src/com/coderising/jvm/Method/Method.java new file mode 100644 index 0000000000..488d66869c --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/Method/Method.java @@ -0,0 +1,99 @@ +package com.coderising.jvm.Method; + +/** + * Created by wang on 2017/4/16. + */ +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + + + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + + + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for( int j=1; j<= attribCount; j++){ + + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else{ + throw new RuntimeException("only CODE attribute is implemented , please implement the "+ attrName); + } + + } + + return m ; + + } +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/attr/AttributeInfo.java b/group04/349184132/Study/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..6ea1bb367b --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.attr; + +/** + * Created by wang on 2017/4/16. + */ + +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; + } + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/attr/CodeAttr.java b/group04/349184132/Study/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..b6711ba618 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,124 @@ +package com.coderising.jvm.attr; + +/** + * Created by wang on 2017/4/16. + */ + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.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 attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + //ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code); + + int exceptionTableLen = iter.nextU2ToInt(); + //TODO 处理exception + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.nextU2ToInt(); + + for(int x=1; x<=subAttrCount; x++){ + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(2); + //line item table + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } + else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } + else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } + else{ + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + 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 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 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 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(); + + } + + + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableItem.java b/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..98ef0c3de8 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + +/** + * Created by wang on 2017/4/16. + */ +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; + } +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableTable.java b/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..ab6dcd04f2 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.attr; + +/** + * Created by wang on 2017/4/16. + */ +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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 index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.nextU2ToInt(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + 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(); + } +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/attr/StackMapTable.java b/group04/349184132/Study/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..ec6a8b3475 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.attr; + +/** + * Created by wang on 2017/4/16. + */ +import com.coderising.jvm.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; + + } +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/clz/AccessFlag.java b/group04/349184132/Study/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group04/349184132/Study/src/com/coderising/jvm/clz/ClassFile.java b/group04/349184132/Study/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + 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 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(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/clz/ClassIndex.java b/group04/349184132/Study/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group04/349184132/Study/src/com/coderising/jvm/constant/ClassInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantPool.java b/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/FieldRefInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/MethodRefInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/NullConstantInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/StringInfo.java b/group04/349184132/Study/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/constant/UTF8Info.java b/group04/349184132/Study/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/field/Field.java b/group04/349184132/Study/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..6d1e5dd02a --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,53 @@ +package com.coderising.jvm.field; + +/** + * Created by wang on 2017/4/16. + */ +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group04/349184132/Study/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..a5fc48cf2c --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + private byte[] codes; + private int pos = 0; + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public String nextU4ToHexString() { + return Util.byteToHexString(new byte[] {codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[]{ codes[pos++] ,codes[pos++]}); + } + + public int nextU1ToInt() { + return Util.byteToInt(new byte[] { codes[pos++]}); + } + + + public int nextU4ToInt(){return Util.byteToInt(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; + } + + public byte[] getByte(int len) { + if(len + pos >= codes.length){ + throw new IndexOutOfBoundsException(); + } + byte[] data = Arrays.copyOfRange(codes,pos,pos+len); + pos += len; + return data; + } +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/loader/ClassFileLoader.java b/group04/349184132/Study/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +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", 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()); + } + + + +} diff --git a/group04/349184132/Study/src/com/coderising/jvm/test/EmployeeV1.java b/group04/349184132/Study/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group04/349184132/Study/src/com/coderising/jvm/test/TestBytetoHex.java b/group04/349184132/Study/src/com/coderising/jvm/test/TestBytetoHex.java new file mode 100644 index 0000000000..5f6d5f2d53 --- /dev/null +++ b/group04/349184132/Study/src/com/coderising/jvm/test/TestBytetoHex.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.test; + +/** + * Created by wang on 2017/3/29. + */ +public class TestBytetoHex { + + public String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i size-1) + throw new IllegalArgumentException(); + } + + public void add(int index, Object o){ + rangeCheck(index); + //bug size++; + + + System.arraycopy(elementData,index,elementData,index+1,size-index); + elementData[index] = o; + size++; + } + + + public Object get(int index){ + rangeCheck(index); + return elementData[index]; + } + + public Object remove(int index){ + rangeCheck(index); + Object oldElement = elementData[index]; + System.arraycopy(elementData,index+1,elementData,index,size-index-1); + elementData[--size]= null; + return oldElement; + } + + public int size(){ + return size; + } + public boolean isEmpty(){ return size==0; } + + public Iterator iterator(){ + return new ArrayListIterator(); + } + + private class ArrayListIterator implements Iterator{ + private int pos = 0; + @Override + public boolean hasNext() { + return possize) + throw new IllegalArgumentException(); + return elementData[pos++]; + } + + } + + + +} diff --git a/group04/349184132/Study/src/com/dataStructure/BinaryTreeNode.java b/group04/349184132/Study/src/com/dataStructure/BinaryTreeNode.java new file mode 100644 index 0000000000..2b069a80b3 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/BinaryTreeNode.java @@ -0,0 +1,75 @@ +package com.dataStructure; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + private BinaryTreeNode root; + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public BinaryTreeNode getLeft() { + return left; + } + + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + + public BinaryTreeNode getRight() { + return right; + } + + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o) { + BinaryTreeNode newNode = null; // 新結點 + if (o == null) + throw new NullPointerException("element is not null"); + + if (root == null) { + root = new BinaryTreeNode(); + root.setData(o); + } else { + newNode = new BinaryTreeNode(); + BinaryTreeNode nowNode = root; //當前結點 + int val = (int) root.getData(); + nowNode.setData(o); + while (true) { + + if ((int) newNode.getData() < val) { // 新結點的值 < 當前結點 + if (nowNode.left == null) { + nowNode.setLeft(newNode); + break; + } else { + nowNode = nowNode.left; + } + } else if ((int) newNode.getData() > val) { + if (nowNode.right == null) { + nowNode.setRight(newNode); + break; + } else { + nowNode = newNode.right; + + } + } else { + + throw new IllegalArgumentException("element exist"); + } + } + } + return newNode; + } + + +} diff --git a/group04/349184132/Study/src/com/dataStructure/Iterator.java b/group04/349184132/Study/src/com/dataStructure/Iterator.java new file mode 100644 index 0000000000..6ac68a250e --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/Iterator.java @@ -0,0 +1,7 @@ +package com.dataStructure; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrame.java b/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrame.java new file mode 100644 index 0000000000..af61d81560 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrame.java @@ -0,0 +1,177 @@ +package com.dataStructure.LRU; + +/** + * Created by wang on 2017/3/27. + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node(int pageNum) { + + this.pageNum = pageNum; + } + } + + private int capacity; + private int size; + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + + + public boolean contains(int pageNum){ + Node cur = first; + while(cur != null){ + if(pageNum == cur.pageNum){ + return true; + } + cur = cur.next; + } + return false; + } + + public boolean isFull(){ + if(size==capacity){ + return true; + } + return false; + } + + private void isLegal(int pageNum){ + if(pageNum<0){ + throw new IllegalArgumentException(); + } + } + + /** + * 获取缓存中对象 + * + * @param + * @return + */ + public void access(int pageNum) { + isLegal(pageNum); + if(isFull()){ + if(contains(pageNum)){ + advance(pageNum); + }else{ + removeLast(); + addFirst(pageNum); + } + }else{ + if(contains(pageNum)){ + advance(pageNum); + }else{ + add(pageNum); + } + } + + } + + + /** + * 填充页面 + * @param pageNum + */ + + private void add(int pageNum) { + if(isEmpty()){ + Node node = new Node(pageNum); + first = node; + last = node; + size++; + }else{ + Node node = new Node(pageNum); + Node oldfirst = first; + node.next = oldfirst; + oldfirst.prev = node; + first = node; + size++; + } + } + + private boolean isEmpty() { + return size==0; + } + + private void advance(int pageNum) { + + + if(pageNum==first.pageNum){ + + }else{ + if(pageNum==last.pageNum){ + removeLast(); + addFirst(pageNum); + }else{ + Node x = findNode(pageNum); + exchNum(x); + } + } + + } + + private void exchNum(Node x) { + int temp = first.pageNum; + first.pageNum = x.pageNum; + x.pageNum = temp; + } + + private Node findNode(int pageNum) { + Node cur = first; + while(cur != null){ + if(pageNum == cur.pageNum){ + break; + } + cur = cur.next; + } + return cur; + } + + private void addFirst(int pageNum) { + Node oldFirst = first; + Node newFirst = new Node(pageNum); + + oldFirst.prev = newFirst; + newFirst.next = oldFirst; + + first = newFirst; + size++; + } + + private void removeLast() { + last = last.prev; + last.next = null; + size--; + } + + + + 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(); + } + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrameTest.java b/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrameTest.java new file mode 100644 index 0000000000..9dc10d3ded --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/LRU/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.dataStructure.LRU; + +/** + * Created by wang on 2017/3/27. + */ +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + } + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/LRU/LinkedList.java b/group04/349184132/Study/src/com/dataStructure/LRU/LinkedList.java new file mode 100644 index 0000000000..bde81890b7 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/LRU/LinkedList.java @@ -0,0 +1,191 @@ +package com.dataStructure.LRU; + +import com.dataStructure.Iterator; +import com.dataStructure.List; + +import java.util.Objects; + +/** + * Created by wang on 2017/3/27. + */ +public class LinkedList implements List { + + private Node first; + private Node last; + private int size = 0; + public void add(Object o) { + if(isEmypty()){ + Node node = new Node(o); + first = node; + last = node; + size++; + }else{ + addLast(o); + } + } + + public void add(int index, Object o) { + checkRange(index); + if(isEmypty()){ + Node node = new Node(o); + first = node; + last = node; + size++; + }else{ + if(index==0){ + addFirst(o); + }else{ + Node node = getNode(index); + Node newNode = new Node(o); + Node pre = node.pre; + + pre.next = newNode; + newNode.pre = pre; + newNode.next = node; + node.pre = newNode; + + size++; + } + } + } + + private Node getNode(int index) { + Node node = first; + int count = 0; + while(countsize-1){ + throw new ArrayIndexOutOfBoundsException(); + } + } + + public Object get(int index) { + checkRange(index); + return getNode(index).data; + } + + + + + public Object set(int index ,Object o){ + checkRange(index); + Node node = getNode(index); + Object oldData = node.data; + node.data = o; + return oldData; + } + + public Object remove(int index) { + checkRange(index); + if(index==0){ + return removeFirst(); + }else{ + if(index==size-1){ + return removeLast(); + }else{ + Node node = getNode(index); + Node pre = node.pre; + Node next = node.next; + + pre.next = next; + next.pre = pre; + node.pre = null; + node.next = null; + + return node.data; + } + } + + } + + + + public int size() { + return size; + } + + public boolean isEmypty(){ + return first==null || last == null; + } + + public void addFirst(Object o) { + Node newFirst = new Node(o); + Node oldfirst = first; + newFirst.next = oldfirst; + first = newFirst; + size++; + } + + public void addLast(Object o) { + Node oldLast = last; + Node node = new Node(o); + oldLast.next = node; + node.pre = oldLast; + last = node; + size++; + } + // not help GC + public Object removeFirst() { + Node oldFirst = first; + first = first.next; + size--; + return oldFirst.data; + } + // not help GC + public Object removeLast() { + Node oldLast = last; + last = last.pre; + size--; + return oldLast.data; + } + + public boolean contain(Object o){ + Node x = first; + while(x!=null){ + if(Objects.deepEquals(x.data,o)){ + return true; + } + x = x.next; + } + return false; + } + + public Iterator iterator() { + return new LinkIterator(); + } + + private class LinkIterator implements Iterator{ + private int cursor = 0; + @Override + public boolean hasNext() { + return cursor= size){ + throw new ArrayIndexOutOfBoundsException(); + } + return get(cursor++); + } + public boolean remove(){ + LinkedList.this.remove(cursor); + return true; + } + } + private static class Node { + Object data; + Node pre; + Node next; + + public Node(Object data) { + this.data = data; + } + } +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/LinkedList.java b/group04/349184132/Study/src/com/dataStructure/LinkedList.java new file mode 100644 index 0000000000..aa059ad82c --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/LinkedList.java @@ -0,0 +1,186 @@ +package com.dataStructure; + +public class LinkedList implements List { + + private Node head; + private Node now; + + + private int size = 0; + + public void add(Object o) { + if (head == null) { + head = new Node(o, null); + now = head; + } else { + + Node node = new Node(o, null); + now.next = node; + now = node; + } + size++; + + } + + private void rangeCheck(int index) { + if (index < 0 || index > size - 1) + throw new IllegalArgumentException(); + } + + public void add(int index, Object o) { + rangeCheck(index); + + if (index == 0) { + addFirst(o); + } else { + Node node = new Node(o, null); + Node now = head; + Node next = head; + for (int i = 1; i <= index; i++) { + next = next.next; + if (i == index) { + node.next = next; + now.next = node; + } + now = now.next; + } + size++; + } + } + + public Object get(int index) { + Node indexNode = head; + if (index == 0) + return indexNode.data; + else { + + for (int i = 1; i <= index; i++) { + indexNode = indexNode.next; + if (i == index) + return indexNode.data; + } + } + return null; + } + + public Object remove(int index) { + rangeCheck(index); + + if (index == 0) { + return removeFirst(); + } else { + Node pre = head; + Node now = head; + for (int i = 1; i <= index; i++) { + now = now.next; + if (i == index) { + pre.next = now.next; + } + pre = pre.next; + } + size--; + return now.data; + } + } + + public int size() { + return size; + } + + public boolean isEmpty() { + return size == 0; + } + + public void addFirst(Object o) { + Node oldhead = head; + Node newhead = new Node(o, oldhead); + head = newhead; + size++; + } + + public void addLast(Object o) { + if(head==null){ + addFirst(o); + }else { + Node node = head; + while (node != null) { + node = node.next; + if (node == null) { + Node lastnode = new Node(o, null); + node = lastnode; + } + } + size++; + } + } + + public Object removeFirst() { + Node oldhead = head; + Node newhead = head.next; + head = newhead; + size--; + return oldhead.data; + } + + public Object removeLast() { + if(size == 1){ + Node first = head; + Object data = first.data; + head = null; + size--; + return data; + }else{ + Node lastPre = getNode(size-2); + Node last = lastPre.next; + Object data = last.data; + lastPre.next = null; + size--; + return data; + } + + } + + private Node getNode(int index) { + rangeCheck(index); + Node cur = head; + int i = 0; + while(i <=index){ + cur = cur.next; + i++; + } + return cur; + } + + public Iterator iterator() { + return new LinkedListIterator(); + } + + private class LinkedListIterator implements Iterator { + int pos = 0; + + @Override + public boolean hasNext() { + return pos < size; + } + + @Override + public Object next() { + if (pos > size) + throw new IllegalArgumentException(); + return get(pos++); + } + } + + private static class Node { + Object data; + Node next; + + private Node(Object data, Node next) { + this.data = data; + this.next = next; + + } + + } + +} diff --git a/group04/349184132/Study/src/com/dataStructure/List.java b/group04/349184132/Study/src/com/dataStructure/List.java new file mode 100644 index 0000000000..b3aabba4e8 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/List.java @@ -0,0 +1,9 @@ +package com.dataStructure; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group04/349184132/Study/src/com/dataStructure/Queue.java b/group04/349184132/Study/src/com/dataStructure/Queue.java new file mode 100644 index 0000000000..3025b84015 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/Queue.java @@ -0,0 +1,29 @@ +package com.dataStructure; + +public class Queue { + private LinkedList elementData = new LinkedList(); + private int size = 0; + public void enQueue(Object o){ + elementData.add(o); + size++; + } + + public Object deQueue(){ + if(isEmpty()) + try { + throw new IllegalAccessException(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + size--; + return elementData.removeFirst(); + } + + public boolean isEmpty(){ + return size==0; + } + + public int size(){ + return size; + } +} diff --git a/group04/349184132/Study/src/com/dataStructure/Stack.java b/group04/349184132/Study/src/com/dataStructure/Stack.java new file mode 100644 index 0000000000..684ad43d0a --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/Stack.java @@ -0,0 +1,36 @@ +package com.dataStructure; + +public class Stack { + private ArrayList elementData = new ArrayList(); + private int size = 0; + public void push(Object o){ + elementData.add(o); + size++; + } + + + public Object pop(){ + if(isEmpty()){ + try { + throw new IllegalAccessException(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + Object obj = elementData.get(--size); + elementData.remove(size); + return obj; + } + + public Object peek(){ + return elementData.get(size-1); + } + + public boolean isEmpty(){ + return size==0; + } + + public int size(){ + return size; + } +} diff --git a/group04/349184132/Study/src/com/dataStructure/StackUtil.java b/group04/349184132/Study/src/com/dataStructure/StackUtil.java new file mode 100644 index 0000000000..b76a61a7b1 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/StackUtil.java @@ -0,0 +1,110 @@ +package com.dataStructure; + +import java.util.Objects; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s==null){ + return ; + } + Queue temp = new Queue(); + while(!s.isEmpty()){ + Integer num = (Integer) s.pop(); + temp.enQueue(num); + } + while (!temp.isEmpty()){ + Integer num = (Integer) temp.deQueue(); + s.push(num); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null){ + return ; + } + Stack temp = new Stack(); + while(!s.isEmpty()){ + Object elem = s.pop(); + if(!Objects.deepEquals(elem,o)){ + temp.push(elem); + } + } + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if(s == null){ + return null; + } + if(len <0 || len > s.size()){ + throw new IndexOutOfBoundsException(); + } + Object[] result = new Object[len]; + + for(int i=0; i 0) { + if (a1 == len1 || a2 == len2) { + break; + } + if (array1[a1] < array2[a2]) { + array3[a3] = array1[a1]; + a1++; + a3++; + } else { + if (array1[a1] > array2[a2]) { + array3[a3] = array2[a2]; + a2++; + a3++; + } else { + array3[a3] = array1[a1]; + a1++; + a2++; + a3++; + } + } + len3--; + } + if (a1 == len1 && a2 == len2) { + return array3; + } + if (a1 == len1) { + for (int i = a2; i < len2; i++) { + array3[a3] = array2[a2]; + a3++; + } + } else { + for (int i = a1; i < len1; i++) { + array3[a3] = array1[a1]; + a3++; + } + } + int[] temp = new int[a3]; + System.arraycopy(array3, 0, temp, 0, temp.length); + array3 = temp; + return array3; + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * + * @param oldArray + * @param size + * @return + */ + public static int[] grow(int[] oldArray, int size) { + int[] newArray = new int[oldArray.length + size]; + for (int i = 0; i < oldArray.length; i++) { + newArray[i] = oldArray[i]; + } + return newArray; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 例如, max = 15 , + * 则返回的数组应该为 [1,1,2,3,5,8,13] max = 1, 则返回空数组 [] + * + * @param max + * @return + */ + public static int[] fibonacci(int max) { + if (max == 1) + return new int[0]; + else { + int[] arr = new int[max]; + arr[0] = 1; + arr[1] = 1; + + int val = 0; + int f1 = 1; + int f2 = 1; + + int index = 2; + + while (val < max) { + val = f1 + f2; + if(val>max){ + break; + } + f1 = f2; + f2 = val; + arr[index++] = val; + } + int[] temp = new int[index]; + System.arraycopy(arr, 0, temp, 0, temp.length); + arr = temp; + return arr; + } + } + + /** + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public static int[] getPrimes(int max) { + int val = 2; // 数值增加 + int index = 0; // 数组索引 + int[] primes = new int[max]; // 存放素数数组 + boolean flag = true; + + while (val < max) { + + for (int i = 2; i prase(String expr){ + + List tokens = new LinkedList<>(); + + 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(isNumber(c)){ + int nextIsNumberIndex = nextIsNumber(expr,i); + String num = expr.substring(i,nextIsNumberIndex); + Token t = new Token(Token.NUMBER,num); + tokens.add(t); + i=nextIsNumberIndex; + }else{ + throw new RuntimeException( c + " is not operator or number ! " ); + } + } + return tokens; + + } + + private int nextIsNumber(String expr,int i) { + while(i tokens = exprParse.prase(this.expr); + + Stack val = new Stack<>(); + Stack op = new Stack<>(); + + + for(int i=0; i topPrio){ + op.push(token.getValue()); + }else if(entryPrio <= topPrio){ + float result = getResult(val,op); + val.push(result); + op.push(token.getValue()); + } + } + + + }else if(token.getType() == Token.NUMBER){ + val.push(Float.parseFloat(token.getValue())); + + } + } + + while(!op.isEmpty()){ + float result = getResult(val,op); + val.push(result); + } + + + return val.peek(); + } + + private float getResult(Stack val, Stack op) { + float v2 = val.pop(); + float v1 = val.pop(); + return calculate(op.pop(),v1,v2); + } + + public int getPriority(String op){ + if(op.equals("+") || op.equals("-")){ + return 1; + }else if(op.equals("*") || op.equals("/")){ + return 2; + }else{ + throw new RuntimeException("Not support this operator!"); + } + } + + private float calculate(String ops , float v1 , float v2){ + if(ops.equals("+") ){ + return v1 + v2; + }else if(ops.equals("-")){ + return v1 - v2; + }else if(ops.equals("*")){ + return v1 * v2; + }else if(ops.equals("/")){ + return v1 / v2; + }else{ + throw new RuntimeException("Not support this operator"); + } + } + + + + + + + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/expr/InfixExprTest.java b/group04/349184132/Study/src/com/dataStructure/expr/InfixExprTest.java new file mode 100644 index 0000000000..3c7255e16a --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/expr/InfixExprTest.java @@ -0,0 +1,51 @@ +package com.dataStructure.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +/** + * Created by wang on 2017/4/14. + */ + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/expr/Token.java b/group04/349184132/Study/src/com/dataStructure/expr/Token.java new file mode 100644 index 0000000000..7920df312f --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/expr/Token.java @@ -0,0 +1,25 @@ +package com.dataStructure.expr; + +/** + * Created by wang on 2017/4/14. + */ +public class Token { + public static final int OPERATOR = 0; + public static final int NUMBER = 1; + private int type ; + private String value; + public Token(int type, String value) { + this.type = type; + this.value = value; + } + + + + public int getType() { + return type; + } + + public String getValue() { + return value; + } +} diff --git a/group04/349184132/Study/src/com/dataStructure/linkedList/Iterator.java b/group04/349184132/Study/src/com/dataStructure/linkedList/Iterator.java new file mode 100644 index 0000000000..aaacd05e86 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/linkedList/Iterator.java @@ -0,0 +1,7 @@ +package com.dataStructure.linkedList; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group04/349184132/Study/src/com/dataStructure/linkedList/LinkedList.java b/group04/349184132/Study/src/com/dataStructure/linkedList/LinkedList.java new file mode 100644 index 0000000000..3c541b7951 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/linkedList/LinkedList.java @@ -0,0 +1,388 @@ +package com.dataStructure.linkedList; + +import java.util.Objects; + + + +public class LinkedList implements List { + + private Node head; + + private int size = 0; + + public LinkedList(){ + this.head = new Node(null,null); + } + + public boolean add(T o){ + + if(head.next == null){ + Node element = new Node(o,null); + head.next = element; + size++; + return true; + } + + Node current = head.next; + while(current != null){ + if(current.next==null){ + Node element = new Node(o,null); + current.next = element; + size++; + return true; + } + current = current.next; + } + + return false; + } + + + private void rangeCheck(int index) { + if (index < -1 || index > size - 1) + throw new IndexOutOfBoundsException(" index "); + } + public boolean add(int index , T o){ + rangeCheck(index); + + Node node = getNode(index); + Node pre = getNode(index-1); + Node newNode = new Node(o,node); + pre.next = newNode; + size++; + return true; + } + + + private Node getNode(int index){ + rangeCheck(index); + Node current = head.next; + int count = 0; + while(current!=null){ + if(count==index){ + return current; + } + count++; + current = current.next; + } + return null; + } + + public T get(int index){ + Node node = getNode(index); + return (T)node.data; + } + public T remove(int index){ + rangeCheck(index); + + Node pre = getNode(index-1); + Node cur = getNode(index); + Node next = cur.next; + pre.next = next; + cur.next = null; + size--; + return (T)cur.data; + } + + + public T remove(T o) { + int index = 0; + for (Node x = head.next; x != null; x = x.next) { + if (Objects.deepEquals(x.data, o)) { + return remove(index); + } + index++; + } + size--; + + return null; + } + + @Override + public T set(int index, T element) { + Node node = getNode(index); + node.data = element; + + return (T)node.data; + } + + @Override + public boolean contains(Object o) { + + return indexOf(o)!=-1; + } + + @Override + public int indexOf(Object o) { + int index = 0; + + for (Node x = head.next; x != null; x = x.next) { + if (Objects.deepEquals(x.data, o)) + return index; + index++; + } + return -1; + } + + @Override + public Object[] toArray() { + Object[] result = new Object[size]; + int i = 0; + for(Node x = head.next; x != null; x = x.next){ + result[i++] = x.data; + } + return null; + } + + @Override + public void clear() { + for(Node cur = head.next;cur!=null;cur = cur.next){ + Node x = cur; + x.data = null; + x.next = null; + } + head = null; + size = 0; + } + + + public int size(){ + return size; + } + public boolean isEmpty() { + return size == 0; + } + public void addFirst(Object o){ + Node newFirst = new Node(o,null); + Node oldFirst = head.next; + head.next = newFirst; + newFirst.next = oldFirst; + size++; + } + public void addLast(Object o){ + Node last = getNode(size-1); + Node newLast = new Node(o,null); + last.next = newLast; + size++; + } + public T removeFirst(){ + Node oldFirst = head.next; + Node nextNode = oldFirst.next; + head.next = nextNode; + size--; + return (T)oldFirst; + } + public T removeLast(){ + Node x = getNode(size-2);//倒数第二个结点 + Node last = x.next; + x.next = null; + size--; + return (T)last; + } + public Iterator iterator(){ + return new LinkedListIterator(); + } + + private class LinkedListIterator implements Iterator { + int pos = 0; + + @Override + public boolean hasNext() { + return pos < size; + } + + @Override + public Object next() { + if (pos > size) + throw new IllegalArgumentException(); + return get(pos++); + } + } + + + + private static class Node{ + Object data; + Node next; + private Node(Object data, Node next) { + this.data = data; + this.next = next; + + } + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public Node reverseFor(Node head){ + if(head==null){ + return null; + } + Node pre = null; + Node curr = head; + Node next = head.next; + while(curr.next!=null){ + + head.next = pre; + pre = curr; + curr = curr.next; + next = next.next; + head = curr; + } + pre = null; + curr = null; + return head; + } + /** + * 递归写法 + * @param + * @return + */ + public Node reverseRecursion(Node current){ + if(current == null || current.next == null){ + return current; + } + Node nextNode = current.next; + current = null; + Node reverseNode = reverseRecursion(current.next); + nextNode.next = current; + + + return reverseNode; + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int delectLength = size/2; + for(int i=0;isize-length){ + throw new IllegalArgumentException(i +" or "+length +" error"); + } + for(int j=i;j101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + if(list==null){ + throw new NullPointerException("List is null"); + } + int[] result = new int[list.size()]; + int index = 0; + for(Iterator iter = list.iterator();iter.hasNext();){ + int LinkIndex = (int)iter.next(); + result[index] = (Integer) get(LinkIndex); + } + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + if(list == null){ + throw new NullPointerException("List is null"); + } + int index = 0; + for(Node cur = head.next ; cur !=null ; cur = cur.next){ + for(Node newList = list.head.next ; newList != null; newList = newList.next ){ + if(Objects.deepEquals(cur.data, newList.data)){ + remove(index); + } + } + index++; + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + for(Node current=head.next;current!=null;current=current.next){ + Node nextNode = current.next; + + if(current.data.equals(nextNode.data)){ + Node nextNodeNext = nextNode.next; + if(nextNodeNext==null){ + current.next = null; + }else{ + current.next = nextNodeNext; + nextNode.next = null; + } + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if (min + max > size && min == max) { + throw new IndexOutOfBoundsException("Arguement is Illegal"); + } + int index = 0; + for (Node curr = head.next; curr != null; curr = curr.next) { + if(((int)curr.data>min) && ((int)curr.data { + public boolean add(T o); + + public boolean add(int index, T o); + + public T get(int index); + + T set(int index, T element); + + public T remove(int index); + + public T remove(T o); + + public int size(); + + public boolean isEmpty(); + + public Iterator iterator(); + + public boolean contains(Object o); + + int indexOf(Object o); + + + Object[] toArray(); + + void clear(); + +} diff --git a/group04/349184132/Study/src/com/dataStructure/test/StackUtilTest.java b/group04/349184132/Study/src/com/dataStructure/test/StackUtilTest.java new file mode 100644 index 0000000000..ba8eb8ad1e --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/test/StackUtilTest.java @@ -0,0 +1,90 @@ +package com.dataStructure.test; + +import com.dataStructure.Stack; +import com.dataStructure.StackUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +/** +* StackUtil Tester. +* +* @author +* @since
���� 7, 2017
+* @version 1.0 +*/ +public class StackUtilTest { + Stack s = new Stack(); + + @Before + public void before() throws Exception { + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + } + + @After + public void after() throws Exception { + } + + /** + * Method: reverse(Stack s) + */ + @Test + public void testReverse() throws Exception { + + StackUtil.reverse(s); + int[] result = new int[s.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = (Integer) s.pop(); + } + int[] expect = new int[]{1, 2, 3, 4, 5}; + Assert.assertArrayEquals(expect, result); + } + + /** + * Method: remove(Stack s, Object o) + */ + @Test + public void testRemove() throws Exception { + int[] result = new int[s.size() - 1]; + StackUtil.remove(s, 1); + for (int i = 0; i < result.length; i++) { + result[i] = (Integer) s.pop(); + } + int[] expect = new int[]{5, 4, 3, 2}; + Assert.assertArrayEquals(expect, result); + + } + + /** + * Method: getTop(Stack s, int len) + */ + @Test + public void testGetTop() throws Exception { + // stack 5 4 3 2 1 + Object[] result = StackUtil.getTop(s, 2); + // 5 4 + Object[] expect = {5, 4}; + Assert.assertArrayEquals(expect, result); + } + + /** + * Method: isValidPairs(String s) + */ + @Test + public void testIsValidPairs() throws Exception { + String s1 = "([e{d}f])"; + boolean flag1 = StackUtil.isValidPairs(s1); + Assert.assertEquals(true, flag1); // ArrayList.remove 边界 删除最后一个 + String s2 = "([b{x]y})"; + boolean flag2 = StackUtil.isValidPairs(s2); + Assert.assertEquals(false, flag2); + } + + +} \ No newline at end of file diff --git a/group04/349184132/Study/src/com/dataStructure/test/TestArrayList.java b/group04/349184132/Study/src/com/dataStructure/test/TestArrayList.java new file mode 100644 index 0000000000..94fd273183 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/test/TestArrayList.java @@ -0,0 +1,69 @@ +package com.dataStructure.test; + +import org.junit.Test; + +import com.dataStructure.ArrayList; +import com.dataStructure.Iterator; + +public class TestArrayList { + private ArrayList al = new ArrayList(); + @Test + public void testAddObject() { + al.add("1"); + al.add(12); + al.add("wang"); + + } + + @Test + public void testAddIntObject() { + al.add("1"); + al.add(12); + al.add("wang"); + + al.add(1, 13); + } + + @Test + public void testGet() { + al.add("1"); + al.add(12); + al.add("wang"); + + al.get(1); + } + + @Test + public void testRemove() { + al.add("1"); + al.add(12); + al.add("wang"); + + al.remove(0); + } + + @Test + public void testSize() { + al.size(); + } + + + @Test + public void testIsEmpty() { + al.isEmpty(); + } + + @Test + public void testIterator() { + al.add("1"); + al.add(12); + al.add("wang"); + + Iterator iterator = al.iterator(); + while(iterator.hasNext()){ + System.out.println(iterator.next()); + } + + } + +} diff --git a/group04/349184132/Study/src/com/dataStructure/test/TestLinkedList.java b/group04/349184132/Study/src/com/dataStructure/test/TestLinkedList.java new file mode 100644 index 0000000000..dae63ff1c3 --- /dev/null +++ b/group04/349184132/Study/src/com/dataStructure/test/TestLinkedList.java @@ -0,0 +1,97 @@ +package com.dataStructure.test; + +import org.junit.Test; + +import com.dataStructure.Iterator; +import com.dataStructure.LinkedList; + +public class TestLinkedList { + LinkedList link = new LinkedList(); + @Test + public void testAddObject() { + link.add(1); + link.add(2); + link.add(3); + } + + @Test + public void testAddIntObject() { + link.add(1); + link.add(2); + link.add(3); + + link.add(2,4); + } + + @Test + public void testGet() { + link.add(1); + link.add(2); + link.add(3); + link.get(1); + } + + @Test + public void testRemove() { + link.add(1); + link.add(2); + link.add(3); + + link.remove(1); + } + + @Test + public void testSize() { + link.size(); + } + + @Test + public void testIsEmpty() { + link.isEmpty(); + } + + @Test + public void testAddFirst() { + link.add(1); + link.add(2); + link.add(3); + + link.addFirst(9); + } + + @Test + public void testAddLast() { + link.add(1); + link.add(2); + link.add(3); + + link.addLast(0); + } + + @Test + public void testRemoveFirst() { + link.add(1); + link.add(2); + link.add(3); + + link.removeFirst(); + } + + @Test + public void testRemoveLast() { + link.add(1); + link.add(2); + link.add(3); + + link.removeLast(); + } + + @Test + public void testIterator() { + Iterator iterator = link.iterator(); + while(iterator.hasNext()){ + System.out.println(iterator.next()); + } + } + +} diff --git a/group04/349184132/Study/src/com/first/ArrayList.java b/group04/349184132/Study/src/com/first/ArrayList.java deleted file mode 100644 index 721bf41ad0..0000000000 --- a/group04/349184132/Study/src/com/first/ArrayList.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.first; - - -public class ArrayList implements List { - - private int size = 0; - - private Object[] elementData ; - - private final static int DefaultSize = 10; - - public ArrayList(){ this(DefaultSize); } - - public ArrayList(int capacity){ - if(capacity<0) - throw new IllegalArgumentException(); - elementData = new Object[capacity]; - } - - public void add(Object o){ - if(size==elementData.length) - ResizeCapacity(); - elementData[size++] = o; - } - - private void ResizeCapacity(){ - Object[] newDatas = new Object[size*2+1]; - System.arraycopy(elementData,0,newDatas,0,size); - elementData = newDatas; - } - - private void rangeCheck(int index){ - if(index<0 || index > size-1) - throw new IllegalArgumentException(); - } - - public void add(int index, Object o){ - rangeCheck(index); - //bug size++; - System.arraycopy(elementData,index,elementData,index+1,size-index); - elementData[index] = o; - size++; - } - - - public Object get(int index){ - rangeCheck(index); - return elementData[index]; - } - - public Object remove(int index){ - rangeCheck(index); - Object oldElement = elementData[index]; - System.arraycopy(elementData,index+1,elementData,index,size-index-1); - size--; - return oldElement; - } - - public int size(){ - return size; - } - public boolean isEmpty(){ return size==0; } - - public Iterator iterator(){ - return new ArrayListIterator(); - } - - private class ArrayListIterator implements Iterator{ - private int pos = 0; - @Override - public boolean hasNext() { - return possize) - throw new IllegalArgumentException(); - return elementData[pos++]; - } - - } - - - -} diff --git a/group04/349184132/Study/src/com/first/BinaryTreeNode.java b/group04/349184132/Study/src/com/first/BinaryTreeNode.java deleted file mode 100644 index 31647f36dd..0000000000 --- a/group04/349184132/Study/src/com/first/BinaryTreeNode.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.first; - -public class BinaryTreeNode { - - private Object data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - private BinaryTreeNode root; - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public BinaryTreeNode getLeft() { - return left; - } - - public void setLeft(BinaryTreeNode left) { - this.left = left; - } - - public BinaryTreeNode getRight() { - return right; - } - - public void setRight(BinaryTreeNode right) { - this.right = right; - } - - public BinaryTreeNode insert(Object o) { - BinaryTreeNode newNode = null; // 新結點 - if (o == null) - throw new NullPointerException("element is not null"); - - if (root == null) { - root = new BinaryTreeNode(); - root.setData(o); - } else { - newNode = new BinaryTreeNode(); - BinaryTreeNode nowNode = root; //當前結點 - int val = (int) root.getData(); - nowNode.setData(o); - while (true) { - - if ((int) newNode.getData() < val) { // 新結點的值 < 當前結點 - if (nowNode.left == null) { - nowNode.setLeft(newNode); - break; - } else { - nowNode = nowNode.left; - } - } else if ((int) newNode.getData() > val) { - if (nowNode.right == null) { - nowNode.setRight(newNode); - break; - } else { - nowNode = newNode.right; - - } - } else { - - throw new IllegalArgumentException("element exist"); - } - } - } - return newNode; - } - - -} diff --git a/group04/349184132/Study/src/com/first/Iterator.java b/group04/349184132/Study/src/com/first/Iterator.java deleted file mode 100644 index ea250e3cf5..0000000000 --- a/group04/349184132/Study/src/com/first/Iterator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.first; - -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group04/349184132/Study/src/com/first/LinkedList.java b/group04/349184132/Study/src/com/first/LinkedList.java deleted file mode 100644 index cf9d274943..0000000000 --- a/group04/349184132/Study/src/com/first/LinkedList.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.first; - -public class LinkedList implements List { - - private Node head; - private Node now; - - - private int size = 0; - - public void add(Object o) { - if (head == null) { - head = new Node(o, null); - now = head; - } else { - - Node node = new Node(o, null); - now.next = node; - now = node; - } - size++; - - } - - private void rangeCheck(int index) { - if (index < 0 || index > size - 1) - throw new IllegalArgumentException(); - } - - public void add(int index, Object o) { - rangeCheck(index); - - if (index == 0) { - addFirst(o); - } else { - Node node = new Node(o, null); - Node now = head; - Node next = head; - for (int i = 1; i <= index; i++) { - next = next.next; - if (i == index) { - node.next = next; - now.next = node; - } - now = now.next; - } - size++; - } - } - - public Object get(int index) { - Node indexNode = head; - if (index == 0) - return indexNode.data; - else { - - for (int i = 1; i <= index; i++) { - indexNode = indexNode.next; - if (i == index) - return indexNode.data; - } - } - return null; - } - - public Object remove(int index) { - rangeCheck(index); - - if (index == 0) { - return removeFirst(); - } else { - Node pre = head; - Node now = head; - for (int i = 1; i <= index; i++) { - now = now.next; - if (i == index) { - pre.next = now.next; - } - pre = pre.next; - } - size--; - return now.data; - } - } - - public int size() { - return size; - } - - public boolean isEmpty() { - return size == 0; - } - - public void addFirst(Object o) { - Node oldhead = head; - Node newhead = new Node(o, oldhead); - head = newhead; - size++; - } - - public void addLast(Object o) { - Node node = head; - while (node != null) { - node = node.next; - if (node == null) { - Node lastnode = new Node(o, null); - node = lastnode; - } - } - size++; - } - - public Object removeFirst() { - Node oldhead = head; - Node newhead = head.next; - oldhead.next = null; - head = newhead; - size--; - return oldhead.data; - } - - public Object removeLast() { - Node node = head; - Node prev = head; - while (node != null) { - node = node.next; - if (node == null) { - prev.next = null; - } - prev = prev.next; - } - size--; - return node.data; - } - - public Iterator iterator() { - return new LinkedListIterator(); - } - - private class LinkedListIterator implements Iterator { - int pos = 0; - - @Override - public boolean hasNext() { - return pos < size; - } - - @Override - public Object next() { - if (pos > size) - throw new IllegalArgumentException(); - return get(pos++); - } - } - - private static class Node { - Object data; - Node next; - - private Node(Object data, Node next) { - this.data = data; - this.next = next; - - } - - } - -} diff --git a/group04/349184132/Study/src/com/first/List.java b/group04/349184132/Study/src/com/first/List.java deleted file mode 100644 index 9c244deb3d..0000000000 --- a/group04/349184132/Study/src/com/first/List.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.first; - -public interface List { - public void add(Object o); - public void add(int index, Object o); - public Object get(int index); - public Object remove(int index); - public int size(); -} diff --git a/group04/349184132/Study/src/com/first/Queue.java b/group04/349184132/Study/src/com/first/Queue.java deleted file mode 100644 index 130e16930e..0000000000 --- a/group04/349184132/Study/src/com/first/Queue.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.first; - -public class Queue { - private LinkedList elementData = new LinkedList(); - private int size = 0; - public void enQueue(Object o){ - elementData.addLast(o); - size++; - } - - public Object deQueue(){ - if(isEmpty()) - try { - throw new IllegalAccessException(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - size--; - return elementData.removeFirst(); - } - - public boolean isEmpty(){ - return size==0; - } - - public int size(){ - return size; - } -} diff --git a/group04/349184132/Study/src/com/first/Stack.java b/group04/349184132/Study/src/com/first/Stack.java deleted file mode 100644 index 7d8477b962..0000000000 --- a/group04/349184132/Study/src/com/first/Stack.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.first; - -public class Stack { - private ArrayList elementData = new ArrayList(); - private int size = 0; - public void push(Object o){ - elementData.add(o); - size++; - } - - - public Object pop(){ - if(isEmpty()){ - try { - throw new IllegalAccessException(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - return elementData.get(--size); - } - - public Object peek(){ - return elementData.get(size-1); - } - - public boolean isEmpty(){ - return size==0; - } - - public int size(){ - return size; - } -} diff --git a/group04/349184132/Study/src/com/first/test/TestArrayList.java b/group04/349184132/Study/src/com/first/test/TestArrayList.java deleted file mode 100644 index af7ed55f0a..0000000000 --- a/group04/349184132/Study/src/com/first/test/TestArrayList.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.first.test; - -import org.junit.Test; - -import com.first.ArrayList; -import com.first.Iterator; - -public class TestArrayList { - private ArrayList al = new ArrayList(); - @Test - public void testAddObject() { - al.add("1"); - al.add(12); - al.add("wang"); - - } - - @Test - public void testAddIntObject() { - al.add("1"); - al.add(12); - al.add("wang"); - - al.add(1, 13); - } - - @Test - public void testGet() { - al.add("1"); - al.add(12); - al.add("wang"); - - al.get(1); - } - - @Test - public void testRemove() { - al.add("1"); - al.add(12); - al.add("wang"); - - al.remove(0); - } - - @Test - public void testSize() { - al.size(); - } - - - @Test - public void testIsEmpty() { - al.isEmpty(); - } - - @Test - public void testIterator() { - al.add("1"); - al.add(12); - al.add("wang"); - - Iterator iterator = al.iterator(); - while(iterator.hasNext()){ - System.out.println(iterator.next()); - } - - } - -} diff --git a/group04/349184132/Study/src/com/first/test/TestLinkedList.java b/group04/349184132/Study/src/com/first/test/TestLinkedList.java deleted file mode 100644 index 2131e580ff..0000000000 --- a/group04/349184132/Study/src/com/first/test/TestLinkedList.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.first.test; - -import org.junit.Test; - -import com.first.Iterator; -import com.first.LinkedList; - -public class TestLinkedList { - LinkedList link = new LinkedList(); - @Test - public void testAddObject() { - link.add(1); - link.add(2); - link.add(3); - } - - @Test - public void testAddIntObject() { - link.add(1); - link.add(2); - link.add(3); - - link.add(2,4); - } - - @Test - public void testGet() { - link.add(1); - link.add(2); - link.add(3); - link.get(1); - } - - @Test - public void testRemove() { - link.add(1); - link.add(2); - link.add(3); - - link.remove(1); - } - - @Test - public void testSize() { - link.size(); - } - - @Test - public void testIsEmpty() { - link.isEmpty(); - } - - @Test - public void testAddFirst() { - link.add(1); - link.add(2); - link.add(3); - - link.addFirst(9); - } - - @Test - public void testAddLast() { - link.add(1); - link.add(2); - link.add(3); - - link.addLast(0); - } - - @Test - public void testRemoveFirst() { - link.add(1); - link.add(2); - link.add(3); - - link.removeFirst(); - } - - @Test - public void testRemoveLast() { - link.add(1); - link.add(2); - link.add(3); - - link.removeLast(); - } - - @Test - public void testIterator() { - Iterator iterator = link.iterator(); - while(iterator.hasNext()){ - System.out.println(iterator.next()); - } - } - -} diff --git a/group04/349184132/Study/src/com/linked/Iterator.java b/group04/349184132/Study/src/com/linked/Iterator.java deleted file mode 100644 index b2397b9aa7..0000000000 --- a/group04/349184132/Study/src/com/linked/Iterator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.linked; - -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group04/349184132/Study/src/com/linked/LinkedList.java b/group04/349184132/Study/src/com/linked/LinkedList.java deleted file mode 100644 index 44aba236b4..0000000000 --- a/group04/349184132/Study/src/com/linked/LinkedList.java +++ /dev/null @@ -1,388 +0,0 @@ -package com.linked; - -import java.util.Objects; - - - -public class LinkedList implements List { - - private Node head; - - private int size = 0; - - public LinkedList(){ - this.head = new Node(null,null); - } - - public boolean add(T o){ - - if(head.next == null){ - Node element = new Node(o,null); - head.next = element; - size++; - return true; - } - - Node current = head.next; - while(current != null){ - if(current.next==null){ - Node element = new Node(o,null); - current.next = element; - size++; - return true; - } - current = current.next; - } - - return false; - } - - - private void rangeCheck(int index) { - if (index < -1 || index > size - 1) - throw new IndexOutOfBoundsException(" index "); - } - public boolean add(int index , T o){ - rangeCheck(index); - - Node node = getNode(index); - Node pre = getNode(index-1); - Node newNode = new Node(o,node); - pre.next = newNode; - size++; - return true; - } - - - private Node getNode(int index){ - rangeCheck(index); - Node current = head.next; - int count = 0; - while(current!=null){ - if(count==index){ - return current; - } - count++; - current = current.next; - } - return null; - } - - public T get(int index){ - Node node = getNode(index); - return (T)node.data; - } - public T remove(int index){ - rangeCheck(index); - - Node pre = getNode(index-1); - Node cur = getNode(index); - Node next = cur.next; - pre.next = next; - cur.next = null; - size--; - return (T)cur.data; - } - - - public T remove(T o) { - int index = 0; - for (Node x = head.next; x != null; x = x.next) { - if (Objects.deepEquals(x.data, o)) { - return remove(index); - } - index++; - } - size--; - - return null; - } - - @Override - public T set(int index, T element) { - Node node = getNode(index); - node.data = element; - - return (T)node.data; - } - - @Override - public boolean contains(Object o) { - - return indexOf(o)!=-1; - } - - @Override - public int indexOf(Object o) { - int index = 0; - - for (Node x = head.next; x != null; x = x.next) { - if (Objects.deepEquals(x.data, o)) - return index; - index++; - } - return -1; - } - - @Override - public Object[] toArray() { - Object[] result = new Object[size]; - int i = 0; - for(Node x = head.next; x != null; x = x.next){ - result[i++] = x.data; - } - return null; - } - - @Override - public void clear() { - for(Node cur = head.next;cur!=null;cur = cur.next){ - Node x = cur; - x.data = null; - x.next = null; - } - head = null; - size = 0; - } - - - public int size(){ - return size; - } - public boolean isEmpty() { - return size == 0; - } - public void addFirst(Object o){ - Node newFirst = new Node(o,null); - Node oldFirst = head.next; - head.next = newFirst; - newFirst.next = oldFirst; - size++; - } - public void addLast(Object o){ - Node last = getNode(size-1); - Node newLast = new Node(o,null); - last.next = newLast; - size++; - } - public T removeFirst(){ - Node oldFirst = head.next; - Node nextNode = oldFirst.next; - head.next = nextNode; - size--; - return (T)oldFirst; - } - public T removeLast(){ - Node x = getNode(size-2);//倒数第二个结点 - Node last = x.next; - x.next = null; - size--; - return (T)last; - } - public Iterator iterator(){ - return new LinkedListIterator(); - } - - private class LinkedListIterator implements Iterator { - int pos = 0; - - @Override - public boolean hasNext() { - return pos < size; - } - - @Override - public Object next() { - if (pos > size) - throw new IllegalArgumentException(); - return get(pos++); - } - } - - - - private static class Node{ - Object data; - Node next; - private Node(Object data, Node next) { - this.data = data; - this.next = next; - - } - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public Node reverseFor(Node head){ - if(head==null){ - return null; - } - Node pre = null; - Node curr = head; - Node next = head.next; - while(curr.next!=null){ - - head.next = pre; - pre = curr; - curr = curr.next; - next = next.next; - head = curr; - } - pre = null; - curr = null; - return head; - } - /** - * 递归写法 - * @param node - * @return - */ - public Node reverseRecursion(Node current){ - if(current == null || current.next == null){ - return current; - } - Node nextNode = current.next; - current = null; - Node reverseNode = reverseRecursion(current.next); - nextNode.next = current; - - - return reverseNode; - - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - int delectLength = size/2; - for(int i=0;isize-length){ - throw new IllegalArgumentException(i +" or "+length +" error"); - } - for(int j=i;j101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public int[] getElements(LinkedList list){ - if(list==null){ - throw new NullPointerException("List is null"); - } - int[] result = new int[list.size()]; - int index = 0; - for(Iterator iter = list.iterator();iter.hasNext();){ - int LinkIndex = (int)iter.next(); - result[index] = (int)get(LinkIndex); - } - return result; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在list中出现的元素 - - * @param list - */ - - public void subtract(LinkedList list){ - if(list == null){ - throw new NullPointerException("List is null"); - } - int index = 0; - for(Node cur = head.next ; cur !=null ; cur = cur.next){ - for(Node newList = list.head.next ; newList != null; newList = newList.next ){ - if(Objects.deepEquals(cur.data, newList.data)){ - remove(index); - } - } - index++; - } - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - for(Node current=head.next;current!=null;current=current.next){ - Node nextNode = current.next; - - if(current.data.equals(nextNode.data)){ - Node nextNodeNext = nextNode.next; - if(nextNodeNext==null){ - current.next = null; - }else{ - current.next = nextNodeNext; - nextNode.next = null; - } - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max) { - if (min + max > size && min == max) { - throw new IndexOutOfBoundsException("Arguement is Illegal"); - } - int index = 0; - for (Node curr = head.next; curr != null; curr = curr.next) { - if(((int)curr.data>min) && ((int)curr.data { - public boolean add(T o); - - public boolean add(int index, T o); - - public T get(int index); - - T set(int index, T element); - - public T remove(int index); - - public T remove(T o); - - public int size(); - - public boolean isEmpty(); - - public Iterator iterator(); - - public boolean contains(Object o); - - int indexOf(Object o); - - - Object[] toArray(); - - void clear(); - -} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/DownloadThread.java b/group04/349184132/Study/src/com/multiThreadDownload/DownloadThread.java new file mode 100644 index 0000000000..8e97a75d5e --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/DownloadThread.java @@ -0,0 +1,49 @@ +package com.multiThreadDownload; + +import com.multiThreadDownload.api.Connection; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +public class DownloadThread extends Thread { + Connection conn; + int startPos; + int endPos; + int threadId = 0; + CyclicBarrier barrier; + + public DownloadThread(CyclicBarrier barrier, Connection conn, int threadId, + int startPos, int endPos) { + this.barrier = barrier; + this.conn = conn; + this.threadId = threadId; + this.startPos = startPos; + this.endPos = endPos; + } + + public void run() { + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile("yunpan.exe", "rwd"); + + raf.seek(startPos); + + byte[] buffer = conn.read(startPos, endPos); + + raf.write(buffer, 0, buffer.length); + raf.close(); + barrier.await(); + System.out.println("threadId" + threadId +"download success !"); + + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (BrokenBarrierException e) { + e.printStackTrace(); + } + + } +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/FileDownloader.java b/group04/349184132/Study/src/com/multiThreadDownload/FileDownloader.java new file mode 100644 index 0000000000..54e6ccfc16 --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/FileDownloader.java @@ -0,0 +1,111 @@ +package com.multiThreadDownload; + +import com.multiThreadDownload.api.Connection; +import com.multiThreadDownload.api.ConnectionException; +import com.multiThreadDownload.api.ConnectionManager; +import com.multiThreadDownload.api.DownloadListener; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.net.URL; +import java.util.concurrent.CyclicBarrier; +public class FileDownloader { + + boolean isFinished = false; + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + private static final int THREAD_NUM = 3; + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute() { + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, + // endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, + // 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + + CyclicBarrier barrier = new CyclicBarrier(THREAD_NUM,new Runnable(){ + + @Override + public void run() { + listener.notifyFinished(); + } + + }); + + Connection conn = null; + try { + conn = cm.open(url); + + int length = conn.getContentLength(); + System.out.println("----文件总长度---- :" + length); + RandomAccessFile raf = new RandomAccessFile("yunpan.exe","rwd"); + + raf.setLength(length); + + int block = length / THREAD_NUM; + + for(int threadId = 0; threadId < THREAD_NUM; threadId++){ + int startPos = (threadId) * block; + int endPos = (threadId + 1 ) * block -1; + if(threadId-1 == THREAD_NUM){ + endPos = length; + } + System.out.println("---threadId--- :" + threadId + + "---startIndex---" + startPos + + "---endIndex---" + endPos); + //开启 线程 + URL u = new URL(url); + new DownloadThread(barrier,cm.open(url),threadId,startPos,endPos).start(); + } + + + } catch (ConnectionException e) { + + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally{ + if(conn!=null){ + conn.close(); + } + } + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm) { + this.cm = ucm; + } + + public DownloadListener getListener() { + return this.listener; + } + + +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/FileDownloaderTest.java b/group04/349184132/Study/src/com/multiThreadDownload/FileDownloaderTest.java new file mode 100644 index 0000000000..f8d8f8f69d --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/FileDownloaderTest.java @@ -0,0 +1,57 @@ +package com.multiThreadDownload; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.multiThreadDownload.api.*; +import com.multiThreadDownload.impl.*; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "http://down.360safe.com/yunpan/360wangpan_setup.exe"; + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + +// 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/api/Connection.java b/group04/349184132/Study/src/com/multiThreadDownload/api/Connection.java new file mode 100644 index 0000000000..bc7b267414 --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/api/Connection.java @@ -0,0 +1,23 @@ +package com.multiThreadDownload.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionException.java b/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionException.java new file mode 100644 index 0000000000..c490e9bc1e --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionException.java @@ -0,0 +1,10 @@ +package com.multiThreadDownload.api; + +public class ConnectionException extends Exception { + + public ConnectionException(String string) { + // TODO 自动生成的构造函数存根 + } + + +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionManager.java b/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionManager.java new file mode 100644 index 0000000000..38b13fde5b --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.multiThreadDownload.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/api/DownloadListener.java b/group04/349184132/Study/src/com/multiThreadDownload/api/DownloadListener.java new file mode 100644 index 0000000000..b902d38109 --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.multiThreadDownload.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionImpl.java b/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionImpl.java new file mode 100644 index 0000000000..b97263378c --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionImpl.java @@ -0,0 +1,49 @@ +package com.multiThreadDownload.impl; + +import com.multiThreadDownload.api.Connection; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +public class ConnectionImpl implements Connection{ + private HttpURLConnection conn ; + public ConnectionImpl(HttpURLConnection conn) { + this.conn = conn; + } + @Override + public byte[] read(int startPos, int endPos) throws IOException { + conn.setRequestMethod("GET"); + conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + conn.setConnectTimeout(5000); + + InputStream is = conn.getInputStream(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int length = 0; + byte[] buffer = new byte[1024]; + while(-1 != ( length = is.read(buffer))){ + bos.write(buffer,0,length); + } + bos.flush(); + is.close(); + bos.close(); + + + return bos.toByteArray(); + } + + @Override + public int getContentLength() { + + return conn.getContentLength(); + } + + @Override + public void close() { + if(conn!=null){ + conn = null; + } + } + +} diff --git a/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionManagerImpl.java b/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..97be6ca5ac --- /dev/null +++ b/group04/349184132/Study/src/com/multiThreadDownload/impl/ConnectionManagerImpl.java @@ -0,0 +1,37 @@ +package com.multiThreadDownload.impl; + +import com.multiThreadDownload.api.Connection; +import com.multiThreadDownload.api.ConnectionException; +import com.multiThreadDownload.api.ConnectionManager; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + @Override + public Connection open(String url) throws ConnectionException { + + URL u; + HttpURLConnection hc ; + try { + u = new URL(url); + hc = (HttpURLConnection) u.openConnection(); + Connection conn = new ConnectionImpl(hc);; + return conn; + } catch (MalformedURLException e) { + e.printStackTrace(); + + } catch (IOException e) { + e.printStackTrace(); + } + return null; + + + + + + } + +} diff --git a/group04/349184132/Study/src/com/parseStruts/LoginAction.java b/group04/349184132/Study/src/com/parseStruts/LoginAction.java new file mode 100644 index 0000000000..19eee013fa --- /dev/null +++ b/group04/349184132/Study/src/com/parseStruts/LoginAction.java @@ -0,0 +1,39 @@ +package com.parseStruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group04/349184132/Study/src/com/second/StringUtil.java b/group04/349184132/Study/src/com/parseStruts/StringUtil.java similarity index 97% rename from group04/349184132/Study/src/com/second/StringUtil.java rename to group04/349184132/Study/src/com/parseStruts/StringUtil.java index 21a3de8e67..85886be5db 100644 --- a/group04/349184132/Study/src/com/second/StringUtil.java +++ b/group04/349184132/Study/src/com/parseStruts/StringUtil.java @@ -1,4 +1,4 @@ -package com.second; +package com.parseStruts; public class StringUtil { public static String nameTogetName(String name){ diff --git a/group04/349184132/Study/src/com/parseStruts/Struts.java b/group04/349184132/Study/src/com/parseStruts/Struts.java new file mode 100644 index 0000000000..c979fc4ca8 --- /dev/null +++ b/group04/349184132/Study/src/com/parseStruts/Struts.java @@ -0,0 +1,124 @@ +package com.parseStruts; + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +public class Struts { + + @SuppressWarnings("unchecked") + public static View runAction(String actionName, + Map parameters) { + + /* + * + * 0. 读取配置文件struts.xml + * + * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" , + * "password"="1234") , 那就应该调用 setName和setPassword方法 + * + * 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + * + * 3. 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如 + * {"message": "登录成功"} , 放到View对象的parameters + * + * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + * 放到View对象的jsp字段中。 + */ + + View view = new View(); + try { + // 读取struts.xml 使用dom4j + SAXReader saxReader = new SAXReader(); + Document document = saxReader.read(new File( + "src/com/second/struts.xml")); + + String classpath = null; + Element actionEle = null; // 存放actionName对应的action元素 + // 获取根节点 + Element root = document.getRootElement(); + for (Iterator it = root.elementIterator(); it.hasNext();) { + Element action = it.next(); + if (actionName.equals(action.attributeValue("name"))) { + actionEle = action; + classpath = action.attributeValue("class"); + + } + } + + Class clazz = Class.forName(classpath); + + Object o = clazz.newInstance(); + + Set set = parameters.keySet(); + + for (Iterator name = set.iterator(); name.hasNext();) { + String para = name.next(); + + Method m = clazz.getDeclaredMethod( + StringUtil.nameTosetName(para), String.class); + + m.invoke(o, parameters.get(para)); + } + + // 调用execute + Method exectue = clazz.getDeclaredMethod("execute", null); + String exResult = (String) exectue.invoke(o, null); + + // 获取所有方法 + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + String methodName = method.getName(); + // 正则过滤 获取getter方法 + if (methodName.matches("get[a-zA-Z]+")) { + + // 字符串处理 getName --> name + parameters.put(StringUtil.getNameToName(methodName), + (String) method.invoke(o, null)); + + } + } + + for (Iterator iter = actionEle.elementIterator("result"); iter + .hasNext();) { + Element result = iter.next(); + String name = result.attributeValue("name"); + if (name.equals(exResult)) { + String jsp = result.getText(); + view.setJsp(jsp); // 放入View jsp字段中 + } + } + view.setParameters(parameters); + + } catch (DocumentException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + + return view; + + } + +} diff --git a/group04/349184132/Study/src/com/parseStruts/StrutsTest.java b/group04/349184132/Study/src/com/parseStruts/StrutsTest.java new file mode 100644 index 0000000000..4e4d271880 --- /dev/null +++ b/group04/349184132/Study/src/com/parseStruts/StrutsTest.java @@ -0,0 +1,42 @@ +package com.parseStruts; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group04/349184132/Study/src/com/parseStruts/View.java b/group04/349184132/Study/src/com/parseStruts/View.java new file mode 100644 index 0000000000..1034745161 --- /dev/null +++ b/group04/349184132/Study/src/com/parseStruts/View.java @@ -0,0 +1,24 @@ +package com.parseStruts; + + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group04/349184132/Study/src/com/second/Array/ArrayUtil.java b/group04/349184132/Study/src/com/second/Array/ArrayUtil.java deleted file mode 100644 index cd99e201ab..0000000000 --- a/group04/349184132/Study/src/com/second/Array/ArrayUtil.java +++ /dev/null @@ -1,257 +0,0 @@ -package com.second.Array; - -import java.util.Arrays; - -public class ArrayUtil { - - /** - * 给定一个整形数组a , 对该数组的值进行置换 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] 如果 a = - * [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * - * @param origin - * @return - */ - public static int[] reverseArray(int[] origin) { - for (int i = 0, j = origin.length - 1; i < origin.length / 2; i++, j--) { - int temp = origin[i]; - origin[i] = origin[j]; - origin[j] = temp; - } - return origin; - } - - /** - * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: {1,3,4,5,6,6,5,4,7,6,7,5} - * - * @param oldArray - * @return - */ - - public static int[] removeZero(int[] oldArray) { - int count = 0; - int[] newArray = new int[oldArray.length]; - for (int i = 0, j = 0; i < oldArray.length; i++) { - if (oldArray[i] == 0) { - count++; - continue; - } else - newArray[j++] = oldArray[i]; - } - int[] temp = new int[newArray.length-count]; - System.arraycopy(newArray, 0, temp, 0, temp.length); - newArray = temp; - return newArray; - } - - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 例如 a1 = - * [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - * - * @param array1 - * @param array2 - * @return - */ - // bug - public static int[] merge(int[] array1, int[] array2) { - int len1 = array1.length; - int len2 = array2.length; - int[] array3 = new int[len1 + len2]; - int len3 = len1 + len2; - int a1 = 0; - int a2 = 0; - int a3 = 0; - while (len3 > 0) { - if (a1 == len1 || a2 == len2) { - break; - } - if (array1[a1] < array2[a2]) { - array3[a3] = array1[a1]; - a1++; - a3++; - } else { - if (array1[a1] > array2[a2]) { - array3[a3] = array2[a2]; - a2++; - a3++; - } else { - array3[a3] = array1[a1]; - a1++; - a2++; - a3++; - } - } - len3--; - } - if (a1 == len1 && a2 == len2) { - return array3; - } - if (a1 == len1) { - for (int i = a2; i < len2; i++) { - array3[a3] = array2[a2]; - a3++; - } - } else { - for (int i = a1; i < len1; i++) { - array3[a3] = array1[a1]; - a3++; - } - } - int[] temp = new int[a3]; - System.arraycopy(array3, 0, temp, 0, temp.length); - array3 = temp; - return array3; - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * - * @param oldArray - * @param size - * @return - */ - public static int[] grow(int[] oldArray, int size) { - int[] newArray = new int[oldArray.length + size]; - for (int i = 0; i < oldArray.length; i++) { - newArray[i] = oldArray[i]; - } - return newArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 例如, max = 15 , - * 则返回的数组应该为 [1,1,2,3,5,8,13] max = 1, 则返回空数组 [] - * - * @param max - * @return - */ - public static int[] fibonacci(int max) { - if (max == 1) - return new int[0]; - else { - int[] arr = new int[max]; - arr[0] = 1; - arr[1] = 1; - - int val = 0; - int f1 = 1; - int f2 = 1; - - int index = 2; - - while (val < max) { - val = f1 + f2; - if(val>max){ - break; - } - f1 = f2; - f2 = val; - arr[index++] = val; - } - int[] temp = new int[index]; - System.arraycopy(arr, 0, temp, 0, temp.length); - arr = temp; - return arr; - } - } - - /** - * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public static int[] getPrimes(int max) { - int val = 2; // 数值增加 - int index = 0; // 数组索引 - int[] primes = new int[max]; // 存放素数数组 - boolean flag = true; - - while (val < max) { - - for (int i = 2; i parameters) { - - /* - * - * 0. 读取配置文件struts.xml - * - * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) - * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" , - * "password"="1234") , 那就应该调用 setName和setPassword方法 - * - * 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" - * - * 3. 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如 - * {"message": "登录成功"} , 放到View对象的parameters - * - * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, - * 放到View对象的jsp字段中。 - */ - - View view = new View(); - try { - // 读取struts.xml 使用dom4j - SAXReader saxReader = new SAXReader(); - Document document = saxReader.read(new File( - "src/com/second/struts.xml")); - - String classpath = null; - Element actionEle = null; // 存放actionName对应的action元素 - // 获取根节点 - Element root = document.getRootElement(); - for (Iterator it = root.elementIterator(); it.hasNext();) { - Element action = it.next(); - if (actionName.equals(action.attributeValue("name"))) { - actionEle = action; - classpath = action.attributeValue("class"); - - } - } - - Class clazz = Class.forName(classpath); - - Object o = clazz.newInstance(); - - Set set = parameters.keySet(); - - for (Iterator name = set.iterator(); name.hasNext();) { - String para = name.next(); - - Method m = clazz.getDeclaredMethod( - StringUtil.nameTosetName(para), String.class); - - m.invoke(o, parameters.get(para)); - } - - // 调用execute - Method exectue = clazz.getDeclaredMethod("execute", null); - String exResult = (String) exectue.invoke(o, null); - - // 获取所有方法 - Method[] methods = clazz.getDeclaredMethods(); - for (Method method : methods) { - String methodName = method.getName(); - // 正则过滤 获取getter方法 - if (methodName.matches("get[a-zA-Z]+")) { - - // 字符串处理 getName --> name - parameters.put(StringUtil.getNameToName(methodName), - (String) method.invoke(o, null)); - - } - } - - for (Iterator iter = actionEle.elementIterator("result"); iter - .hasNext();) { - Element result = iter.next(); - String name = result.attributeValue("name"); - if (name.equals(exResult)) { - String jsp = result.getText(); - view.setJsp(jsp); // 放入View jsp字段中 - } - } - view.setParameters(parameters); - - } catch (DocumentException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - - return view; - - } - -} diff --git a/group04/349184132/Study/src/com/second/StrutsTest.java b/group04/349184132/Study/src/com/second/StrutsTest.java deleted file mode 100644 index ff297c01ab..0000000000 --- a/group04/349184132/Study/src/com/second/StrutsTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.second; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import org.junit.Assert; -import org.junit.Test; - - - - - -public class StrutsTest { - - @Test - public void testLoginActionSuccess() { - - - String actionName = "login"; - - Map params = new HashMap(); - params.put("name","test"); - params.put("password","1234"); - - - View view = Struts.runAction(actionName,params); - Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); - Assert.assertEquals("login successful", view.getParameters().get("message")); - } - - @Test - public void testLoginActionFailed() { - String actionName = "login"; - Map params = new HashMap(); - params.put("name","test"); - params.put("password","123456"); //密码和预设的不一致 - - View view = Struts.runAction(actionName,params); - Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); - Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); - } -} diff --git a/group04/349184132/Study/src/com/second/View.java b/group04/349184132/Study/src/com/second/View.java deleted file mode 100644 index 647d88d5f0..0000000000 --- a/group04/349184132/Study/src/com/second/View.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.second; - -import java.util.Map; - -public class View { - private String jsp; - private Map parameters; - - public String getJsp() { - return jsp; - } - public View setJsp(String jsp) { - this.jsp = jsp; - return this; - } - public Map getParameters() { - return parameters; - } - public View setParameters(Map parameters) { - this.parameters = parameters; - return this; - } -} diff --git a/group04/349184132/Study/src/com/second/struts.xml b/group04/349184132/Study/src/com/second/struts.xml deleted file mode 100644 index 554dbbe227..0000000000 --- a/group04/349184132/Study/src/com/second/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git "a/group04/349184132/post/CPU\345\206\205\345\255\230\347\241\254\347\233\230\346\214\207\344\273\244.docx" "b/group04/349184132/post/CPU\345\206\205\345\255\230\347\241\254\347\233\230\346\214\207\344\273\244.docx" deleted file mode 100644 index 72f97352ac..0000000000 Binary files "a/group04/349184132/post/CPU\345\206\205\345\255\230\347\241\254\347\233\230\346\214\207\344\273\244.docx" and /dev/null differ diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/AttributeInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..bd6198e46f --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.attr; + +public class AttributeInfo { + public static final String ATTR_CODE = "Code"; + public static final String ATTR_LINE_NUMBER_TABLE = "LineNumberTable"; + public static final String ATTR_LOCAL_VARIABLE_TABLE = "LocalVariableTable"; + + private int attrNameIndex; + private int attrLength; + public int getAttrNameIndex() { + return attrNameIndex; + } + public void setAttrNameIndex(int attrNameIndex) { + this.attrNameIndex = attrNameIndex; + } + public int getAttrLength() { + return attrLength; + } + public void setAttrLength(int attrLength) { + this.attrLength = attrLength; + } + public AttributeInfo(int attrNameIndex, int attrLength) { + super(); + this.attrNameIndex = attrNameIndex; + this.attrLength = attrLength; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/CodeAttr.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..3211cac50c --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,102 @@ +package com.coderising.jvm.attr; + +import org.junit.Assert; + +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo{ + + private int maxStack ; + private int maxLocals ; + private int codeLength ; + private String code; + private LineNumberTable lineNumTable; + private LocalVariableTable localVariableTable; + private ByteCodeCommand[] cmds; + public void setCmds(ByteCodeCommand[] cmds) { + this.cmds = cmds; + } + public LocalVariableTable getLocalVariableTable() { + return localVariableTable; + } + public void setLocalVariableTable(LocalVariableTable localVariableTable) { + this.localVariableTable = localVariableTable; + } + public CodeAttr(int attrNameIndex, int attrLength) { + super(attrNameIndex, attrLength); + } + public int getMaxStack() { + return maxStack; + } + public void setMaxStack(int maxStack) { + this.maxStack = maxStack; + } + public int getMaxLocals() { + return maxLocals; + } + public void setMaxLocals(int maxLocals) { + this.maxLocals = maxLocals; + } + public int getCodeLength() { + return codeLength; + } + public void setCodeLength(int codeLength) { + this.codeLength = codeLength; + } + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } + public LineNumberTable getLineNumTable() { + return lineNumTable; + } + public void setLineNumTable(LineNumberTable lineNumTable) { + this.lineNumTable = lineNumTable; + } + public static CodeAttr parse(ByteCodeIterator it, ConstantPool constantPool) { + int attrNameIndex = it.next2ByteToInt(); + int attrLength = it.next4ByteToInt(); + int maxStack = it.next2ByteToInt(); + int maxLocals = it.next2ByteToInt(); + int codeLength = it.next4ByteToInt(); + String code = it.nextXByteToHexStr(codeLength); + ByteCodeCommand[] cmds = CommandParser.parse(constantPool, code); + + int exceptionTableLength = it.next2ByteToInt(); + Assert.assertEquals(0, exceptionTableLength); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLength); + codeAttr.setMaxStack(maxStack); + codeAttr.setMaxLocals(maxLocals); + codeAttr.setCodeLength(codeLength); + codeAttr.setCode(code); + codeAttr.setCmds(cmds); + + int subAttrCount = it.next2ByteToInt(); + while(subAttrCount > 0) { + int subAttrNameIndex = it.next2ByteToInt(); + String subAttrName = constantPool.getUTF8String(subAttrNameIndex); + if(AttributeInfo.ATTR_LINE_NUMBER_TABLE.equals(subAttrName)) { //LineNumberTable + it.back(2); + codeAttr.setLineNumTable(LineNumberTable.parse(it, constantPool)); + } else if (AttributeInfo.ATTR_LOCAL_VARIABLE_TABLE.equals(subAttrName)) { //LocalVariableTable + it.back(2); + codeAttr.setLocalVariableTable(LocalVariableTable.parse(it, constantPool)); + } else { + throw new RuntimeException("no implements attrName: " + subAttrName); + } + subAttrCount--; + } + return codeAttr; + } + + public ByteCodeCommand[] getCmds() { + return this.cmds; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LineNumberTable.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..655549cf1f --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + + +public class LineNumberTable extends AttributeInfo { + private List lineNumberItems = new ArrayList<>(); + + public LineNumberTable(int attrNameIndex, int attrLength) { + super(attrNameIndex, attrLength); + } + + 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 List getLineNumberItems() { + return lineNumberItems; + } + + public void addLineNumberItem(LineNumberItem item){ + this.lineNumberItems.add(item); + } + + + public static LineNumberTable parse(ByteCodeIterator it, ConstantPool constantPool) { + int attrNameIndex = it.next2ByteToInt(); + int attrLength = it.next4ByteToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLength); + int lineNumberTableLength = it.next2ByteToInt(); + while(lineNumberTableLength > 0) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(it.next2ByteToInt()); + item.setLineNum(it.next2ByteToInt()); + lineNumberTable.addLineNumberItem(item); + lineNumberTableLength--; + } + return lineNumberTable; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..a7d220d8a3 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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; + } + public LocalVariableItem(int startPc, int length, int nameIndex, int descIndex, int index) { + super(); + this.startPc = startPc; + this.length = length; + this.nameIndex = nameIndex; + this.descIndex = descIndex; + this.index = index; + } + public LocalVariableItem() { + super(); + // TODO Auto-generated constructor stub + } + + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..2a08a4e778 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + private List localVariableItems = new ArrayList<>(); + + public List getLocalVariableItems() { + return localVariableItems; + } + + public void addLocalVariableItem(LocalVariableItem localVariableItem) { + this.localVariableItems.add(localVariableItem); + } + + public LocalVariableTable(int attrNameIndex, int attrLength) { + super(attrNameIndex, attrLength); + } + + public static LocalVariableTable parse(ByteCodeIterator it, ConstantPool constantPool) { + int attrNameIndex = it.next2ByteToInt(); + int attrLength = it.next4ByteToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIndex, attrLength); + + int localVariableTableLength = it.next2ByteToInt(); + while(localVariableTableLength > 0) { + int startPc = it.next2ByteToInt(); + int length = it.next2ByteToInt(); + int nameIndex = it.next2ByteToInt(); + int descIndex = it.next2ByteToInt(); + int index = it.next2ByteToInt(); + localVariableTable.addLocalVariableItem(new LocalVariableItem(startPc, length, nameIndex, descIndex, index)); + localVariableTableLength--; + } + return localVariableTable; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/AccessFlag.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..cdb8f8859a --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassFile.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..f13a8d538c --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,95 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFile { + + private int minorVersion; + private int MajorVersion; + private ConstantPool constantPool; + private ClassIndex classIndex; + private AccessFlag accessFlag; + private List fields = new ArrayList (); + private List methods = new ArrayList (); + + public int getMinorVersion() { + return minorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + public int getMajorVersion() { + return MajorVersion; + } + + public void setMajorVersion(int majorVersion) { + MajorVersion = majorVersion; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + + public void print() { + // TODO Auto-generated method stub + throw new RuntimeException("no implement"); + } + + public ClassIndex getClzIndex() { + return classIndex; + } + + public void setClassIndex(ClassIndex classIndex) { + this.classIndex = classIndex; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public List getFields() { + return this.fields; + } + + public void addFiled(Field field) { + this.fields.add(field); + } + + public List getMethods() { + return this.methods; + } + + public void addMethod(Method method) { + this.methods.add(method); + } + + public Method getMethod(String methodName, String paramterType) { + for (Method method: this.methods) { + if(getConstantPool().getUTF8String(method.getNameIndex()).equals(methodName) + && getConstantPool().getUTF8String(method.getDescIndex()).equals(paramterType)) { + return method; + } + } + return null; + } + + public Method getMainMethod() { + return this.getMethod("main", "([Ljava/lang/String;)V"); + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassIndex.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..1beb4f390f --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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; + } + public ClassIndex(int thisClassIndex, int superClassIndex) { + super(); + this.thisClassIndex = thisClassIndex; + this.superClassIndex = superClassIndex; + } + + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/BiPushCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cbffcfc6a9 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class BiPushCmd extends OneOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/ByteCodeCommand.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..1f3c0fa0eb --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +public abstract class ByteCodeCommand { + private int offset; + private String opCode; + 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"); + } + + public int getOffset() { + return offset; + } + public void setOffset(int offset) { + this.offset = offset; + } + public String getOpCode() { + return opCode; + } + public void setOpCode(String opCode) { + this.opCode = opCode; + } + public String getReadableCodeText() { + String str = codeMap.get(this.opCode); + if(str == null) { + str = this.opCode; + } + return str; + } + + abstract public int getLength(); + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/CommandParser.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..884c5f856d --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,127 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +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(ConstantPool constantPool, String code) { + CommandIterator it = new CommandIterator(code); + List cmds = new ArrayList<>(); + while(it.hasNext()) { + String opCode = it.next2CharAsString().toUpperCase(); + if(aload_0.equalsIgnoreCase(opCode) || aload_1.equalsIgnoreCase(opCode) || aload_2.equalsIgnoreCase(opCode) + || voidreturn.equalsIgnoreCase(opCode) || dup.equalsIgnoreCase(opCode) || astore_1.equalsIgnoreCase(opCode) + || iload_1.equalsIgnoreCase(opCode) || iload_2.equalsIgnoreCase(opCode) || iload_3.equalsIgnoreCase(opCode)){ + NoOperandCmd cmd = new NoOperandCmd(); + cmd.setOpCode(opCode); + cmds.add(cmd); + } else if(invokespecial.equalsIgnoreCase(opCode)) { + addTwoOperandCmd(it, cmds, opCode, new InvokeSpecialCmd()); + } else if(putfield.equalsIgnoreCase(opCode)) { + addTwoOperandCmd(it, cmds, opCode, new PutFieldCmd()); + } else if(getstatic.equalsIgnoreCase(opCode)) { + addTwoOperandCmd(it, cmds, opCode, new GetStaticCmd()); + } else if(invokevirtual.equalsIgnoreCase(opCode)) { + addTwoOperandCmd(it, cmds, opCode, new InvokeVirtualCmd()); + } else if(new_object.equalsIgnoreCase(opCode)) { + addTwoOperandCmd(it, cmds, opCode, new NewObjectCmd()); + } else if(ldc.equalsIgnoreCase(opCode)) { + addOneOperandCmd(it, cmds, opCode, new LdcCmd()); + } else if(bipush.equalsIgnoreCase(opCode)) { + addOneOperandCmd(it, cmds, opCode, new BiPushCmd()); + } else { + throw new RuntimeException("no implements opCode : " + opCode); + } + } + calcuateOffset(cmds); + return cmds.toArray(new ByteCodeCommand[cmds.size()]); + } + + private static void addOneOperandCmd(CommandIterator it, List cmds, String opCode, OneOperandCmd cmd) { + cmd.setOpCode(opCode); + cmd.setOperand(it.next2CharAsInt()); + cmds.add(cmd); + } + + private static void addTwoOperandCmd(CommandIterator it, List cmds, String opCode, + TwoOperandCmd cmd) { + cmd.setIndex(it.next4CharAsInt()); + cmd.setOpCode(opCode); + cmds.add(cmd); + } + + private static void calcuateOffset(List cmds) { + int offset = 0; + for (ByteCodeCommand cmd : cmds) { + cmd.setOffset(offset); + offset += cmd.getLength(); + } + } + + private static class CommandIterator { + private String code; + private int index = 0; + public CommandIterator(String code) { + super(); + this.code = code; + } + public boolean hasNext() { + return index < code.length(); + } + public String next2CharAsString() { + String result = code.substring(index, index + 2); + index += 2; + return result; + } + public int next2CharAsInt() { + String str = this.next2CharAsString(); + return hexStrToInt(str); + } + public int next4CharAsInt() { + String s1 = this.next2CharAsString(); + String s2 = this.next2CharAsString(); + return ((hexStrToInt(s1) << 8) | hexStrToInt(s2)); + } + private int hexStrToInt(String s) { + return Integer.valueOf(s, 16).intValue(); + } + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/GetStaticCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/GetStaticCmd.java new file mode 100644 index 0000000000..f1cbe78121 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/GetStaticCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class GetStaticCmd extends TwoOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..c7c978ebe7 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class InvokeSpecialCmd extends TwoOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..37161c21a8 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class InvokeVirtualCmd extends TwoOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/LdcCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..1b89885043 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class LdcCmd extends OneOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NewObjectCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..18c04527e9 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class NewObjectCmd extends TwoOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NoOperandCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..35a279198a --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,10 @@ +package com.coderising.jvm.cmd; + +public class NoOperandCmd extends ByteCodeCommand { + + @Override + public int getLength() { + return 1; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/OneOperandCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..30f0ea3d80 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.cmd; + +public class OneOperandCmd extends ByteCodeCommand { + private int operand; + public int getOperand() { + return operand; + } + public void setOperand(int operand) { + this.operand = operand; + } + @Override + public int getLength() { + return 2; + } +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/PutFieldCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..378b0087c3 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.cmd; + +public class PutFieldCmd extends TwoOperandCmd { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/TwoOperandCmd.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..3bee83d23b --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.cmd; + +public class TwoOperandCmd extends ByteCodeCommand { + private int index; + public void setIndex(int index) { + this.index = index; + } + public int getIndex() { + return this.index; + } + @Override + public int getLength() { + return 3; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ClassInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..4cc095b23a --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo{ + + private int nameIndex; + private ConstantPool constantPool; + + public ClassInfo(int nameIndex, ConstantPool constantPool) { + super(); + this.nameIndex = nameIndex; + this.constantPool = constantPool; + } + + public int getUtf8Index() { + return this.nameIndex; + } + + public String getClassName() { + return ((UTF8Info)this.constantPool.getConstantInfo(this.nameIndex)).getValue(); + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..da5b29ee74 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.constant; + +public class ConstantInfo { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantPool.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..bc823181c5 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + public static final int C_UTF8_INFO = 1; + public static final int C_CLASS_INFO = 7; + public static final int C_STRING_INFO = 8; + public static final int C_FIELDREF_INFO = 9; + public static final int C_METHODREF_INFO = 10; + public static final int C_NAME_AND_TYPE_INFO = 12; + private int size; + private List constantInfosList = new ArrayList<>(); + + public void setSize(int size) { + this.size = size; + } + public int getSize() { + return this.size; + } + + public ConstantInfo getConstantInfo(int i) { + return this.constantInfosList.get(i); + } + + public void addConstantInfo(ConstantInfo constantInfo) { + this.constantInfosList.add(constantInfo); + } + public String getUTF8String(int index) { + return ((UTF8Info)getConstantInfo(index)).getValue(); + } +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..141d8ddbfa --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo { + private int classInfoIndex; + private int nameAndTypeIndex; + public FieldRefInfo(int classInfoIndex, int nameAndTypeIndex) { + super(); + this.classInfoIndex = classInfoIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + public int getClassInfoIndex() { + return classInfoIndex; + } + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..867c837e6c --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(int classInfoIndex, int nameAndTypeIndex) { + super(); + this.classInfoIndex = classInfoIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public int getClassInfoIndex() { + return this.classInfoIndex; + } + + public int getNameAndTypeIndex() { + return this.nameAndTypeIndex; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NULLConstantInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NULLConstantInfo.java new file mode 100644 index 0000000000..1fcba5f15d --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NULLConstantInfo.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.constant; + +public class NULLConstantInfo extends ConstantInfo { + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..8e1f2231ed --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo { + private int index1; + private int index2; + public NameAndTypeInfo(int index1, int index2) { + super(); + this.index1 = index1; + this.index2 = index2; + } + public int getIndex1() { + return index1; + } + public int getIndex2() { + return index2; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/StringInfo.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..7bc54c28d9 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo { + private int stringIndex; + + public StringInfo(int stringIndex) { + super(); + this.stringIndex = stringIndex; + } + + public int getStringIndex() { + return stringIndex; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/UTF8Info.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..c25bba86e3 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + private String value; + + public UTF8Info(String value) { + super(); + this.value = value; + } + + public String getValue() { + return this.value; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/field/Field.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..b6d47bf761 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/field/Field.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; + +public class Field { + + private int accessFlag; + private int nameIndex; + private int descIndex; + private ConstantPool constantPool; + public ConstantPool getConstantPool() { + return constantPool; + } + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + public int getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + 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; + } + + @Override + public String toString() { + String name = ((UTF8Info) this.constantPool.getConstantInfo(nameIndex)).getValue(); + String desc = ((UTF8Info) this.constantPool.getConstantInfo(descIndex)).getValue(); + return name + ":" + desc; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..ca87c3caab --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,83 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +public class ByteCodeIterator { + private byte[] codes; + private int index; + + public ByteCodeIterator(byte[] codes) { + super(); + this.codes = codes; + } + + + public void skip(int index) { + this.index = index; + } + + + public int next2ByteToInt() { + return converToInt(codes[index++], codes[index++]); + } + + public int next1ByteToInt() { + return converToInt(codes[index++]); + } + + public int next4ByteToInt() { + return converToInt(codes[index++], codes[index++], codes[index++], codes[index++]); + } + + /** + * big-endian + */ + private int converToInt(byte ... bs) { + int result = 0; + for(int size = bs.length, index = 0; size > 0; size--, index++) { + if(size == 1) { + result += bs[index] & 0xFF; //符号位 + } else { + result += bs[index] << ((size -1) * 8); + } + } + return result; + } + + + public String nextLengthByteToString(int length) { + byte[] bytes = Arrays.copyOfRange(codes, index, index + length); + String str = null; + try { + str = new String(bytes, "UTF-8"); + index += length; + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return str; + } + + public String nextXByteToHexStr(int length) { + byte[] bytes = Arrays.copyOfRange(codes, index, index + length); + StringBuffer buffer = new StringBuffer(); + for(int i=0;i 0) { - baos.write(b, 0, len); - } - return baos.toByteArray(); + return IOUtils.toByteArray(fis); } catch (Exception e) { - new RuntimeException(e); + e.printStackTrace(); } finally { - close(baos); - close(fis); + IOUtils.closeQuietly(fis); } return EMPTY_BYTES; } - - private void close(Closeable stream) { - if(stream != null ) { - try { - stream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - public void addClassPath(String path) { clzPaths.add(path); } public String getClassPath(){ - StringBuilder builder = new StringBuilder(); - for (String path : clzPaths) { - builder.append(path).append(";"); - } - if(builder.length() > 0) { - builder = builder.deleteCharAt(builder.length() - 1); - } - return builder.toString(); + return StringUtils.join(clzPaths, ";"); + } + + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); } } diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ClassFileParser.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..798c5b1826 --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,160 @@ +package com.coderising.jvm.loader; + +import org.junit.Assert; + +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NULLConstantInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + if(codes == null || codes.length == 0){ + throw new RuntimeException("illegality byteCode"); + } + ByteCodeIterator it = new ByteCodeIterator(codes); + ClassFile clzFile = new ClassFile(); + it.skip(4); //CAFE BABE + clzFile.setMinorVersion(it.next2ByteToInt()); + clzFile.setMajorVersion(it.next2ByteToInt()); + + //constant_pool + clzFile.setConstantPool(parseConstantPool(it)); + + //access_flag + clzFile.setAccessFlag(parseAccessFlag(it)); + + //classIndex + clzFile.setClassIndex(parseClassInfex(it)); + + //interfaces TODO + int interfaceCount = it.next2ByteToInt(); + Assert.assertEquals("no have ", 0, interfaceCount); + + //fields + parseField(it, clzFile); + + //methods + parseMethod(it, clzFile); + + return clzFile; + } + + private void parseMethod(ByteCodeIterator it, ClassFile clzFile) { + int methodCount = it.next2ByteToInt(); + while(methodCount > 0) { + Method method = new Method(); + int accessFlag = it.next2ByteToInt(); + int nameIndex = it.next2ByteToInt(); + int descIndex = it.next2ByteToInt(); + int attrCount = it.next2ByteToInt(); + method.setAccessFlag(accessFlag); + method.setNameIndex(nameIndex); + method.setDescIndex(descIndex); + method.setConstantPool(clzFile.getConstantPool()); + while(attrCount > 0) { + int attrNameIndex = it.next2ByteToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + if(AttributeInfo.ATTR_CODE.equals(attrName)) { //code + it.back(2); + CodeAttr codeAttr = CodeAttr.parse(it, clzFile.getConstantPool()); + method.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("no implements attributeName: " + attrName); + } + attrCount--; + } + clzFile.addMethod(method); + methodCount--; + } + } + + private void parseField(ByteCodeIterator it, ClassFile clzFile) { + int fieldCount = it.next2ByteToInt(); + while(fieldCount > 0) { + Field field = new Field(); + int accessFlag = it.next2ByteToInt(); + int nameIndex = it.next2ByteToInt(); + int descIndex = it.next2ByteToInt(); + int attrCount = it.next2ByteToInt(); + Assert.assertEquals("no have ", 0, attrCount); //TODO + field.setAccessFlag(accessFlag); + field.setNameIndex(nameIndex); + field.setDescIndex(descIndex); + field.setConstantPool(clzFile.getConstantPool()); + clzFile.addFiled(field); + fieldCount--; + } + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + int value = iter.next2ByteToInt(); + AccessFlag accessFlag = new AccessFlag(value); + return accessFlag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + int thisClassIndex = iter.next2ByteToInt(); + int superClassIndex = iter.next2ByteToInt(); + ClassIndex classIndex = new ClassIndex(thisClassIndex, superClassIndex); + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int poolCount = iter.next2ByteToInt() - 1; + ConstantPool constantPool = new ConstantPool(); + constantPool.setSize(poolCount); + constantPool.addConstantInfo(new NULLConstantInfo()); + while(poolCount > 0) { + int tag = iter.next1ByteToInt(); + if(tag == ConstantPool.C_CLASS_INFO) { + int nameIndex = iter.next2ByteToInt(); + ClassInfo classInfo = new ClassInfo(nameIndex, constantPool); + constantPool.addConstantInfo(classInfo); + } else if(tag == ConstantPool.C_UTF8_INFO) { + int length = iter.next2ByteToInt(); + String str = iter.nextLengthByteToString(length); + UTF8Info utf8Info = new UTF8Info(str); + constantPool.addConstantInfo(utf8Info); + } else if(tag == ConstantPool.C_METHODREF_INFO) { + int classInfoIndex = iter.next2ByteToInt(); + int nameAndTypeIndex = iter.next2ByteToInt(); + MethodRefInfo methodRefInfo = new MethodRefInfo(classInfoIndex, nameAndTypeIndex); + constantPool.addConstantInfo(methodRefInfo); + } else if(tag == ConstantPool.C_NAME_AND_TYPE_INFO) { + int index1 = iter.next2ByteToInt(); + int index2 = iter.next2ByteToInt(); + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(index1 , index2); + constantPool.addConstantInfo(nameAndTypeInfo); + } else if(tag == ConstantPool.C_FIELDREF_INFO) { + int classInfoIndex = iter.next2ByteToInt(); + int nameAndTypeIndex = iter.next2ByteToInt(); + FieldRefInfo fieldRefInfo = new FieldRefInfo(classInfoIndex, nameAndTypeIndex) ; + constantPool.addConstantInfo(fieldRefInfo); + } else if(tag == ConstantPool.C_STRING_INFO) { + int index = iter.next2ByteToInt(); + StringInfo stringInfo = new StringInfo(index); + constantPool.addConstantInfo(stringInfo); + } else { + throw new RuntimeException("no implement tag = " + tag); + } + poolCount--; + } + return constantPool; + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/method/Method.java b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..1ce4b51c2c --- /dev/null +++ b/group04/498654356/mini-jvm/jvm/src/main/java/com/coderising/jvm/method/Method.java @@ -0,0 +1,47 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; + +public class Method { + private int accessFlag; + private int nameIndex; + private int descIndex; + private ConstantPool constantPool; + private CodeAttr codeAttr; + public int getAccessFlag() { + return accessFlag; + } + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + 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 ConstantPool getConstantPool() { + return constantPool; + } + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + public CodeAttr getCodeAttr() { + return codeAttr; + } + public void setCodeAttr(CodeAttr codeAttr) { + this.codeAttr = codeAttr; + } + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + +} diff --git a/group04/498654356/mini-jvm/jvm/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java b/group04/498654356/mini-jvm/jvm/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java index 3f4a585db7..7174e88414 100644 --- a/group04/498654356/mini-jvm/jvm/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group04/498654356/mini-jvm/jvm/src/test/java/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,24 +1,45 @@ package com.coderising.jvm.test; +import java.util.List; + import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; - - - - +import com.coderising.jvm.method.Method; public class ClassFileloaderTest { + private static final String TEST_EMPLOYEE_V1_CLASS = "com.coderising.jvm.test.EmployeeV1"; private static final String CAFEBABE = "cafebabe"; static String path1 = "D:\\Dev\\git_repository\\coding2017\\group04\\498654356\\mini-jvm\\jvm\\target\\test-classes"; static String path2 = "C:\\temp"; + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = TEST_EMPLOYEE_V1_CLASS; + clzFile = loader.loadClass(className); +// clzFile.print(); //TODO + } @Before public void setUp() throws Exception { @@ -47,7 +68,7 @@ public void testClassFileLength() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = TEST_EMPLOYEE_V1_CLASS; byte[] byteCodes = loader.readBinaryCode(className); @@ -61,7 +82,7 @@ public void testClassFileLength() { public void testMagicNumber(){ ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; + String className = TEST_EMPLOYEE_V1_CLASS; byte[] byteCodes = loader.readBinaryCode(className); byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; @@ -71,16 +92,11 @@ public void testMagicNumber(){ 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()); + } + + @Test + public void testAccessFlag() { + AccessFlag accessFlag = clzFile.getAccessFlag(); + Assert.assertEquals(true, accessFlag.isPublicClass()); + Assert.assertEquals(false, accessFlag.isFinalClass()); + } + + /*** + * third ------------------------------------------------------------------------------------------------------------ + */ + + @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.getDescIndex()); + 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/group04/498654356/one/pom.xml b/group04/498654356/one/pom.xml index b74298d33f..222814666f 100644 --- a/group04/498654356/one/pom.xml +++ b/group04/498654356/one/pom.xml @@ -40,6 +40,11 @@ dom4j 1.6.1 - + + + org.apache.commons + commons-lang3 + 3.4 + \ No newline at end of file diff --git a/group04/498654356/one/src/org/coding/five/StackUtil.java b/group04/498654356/one/src/org/coding/five/StackUtil.java new file mode 100644 index 0000000000..5df8131893 --- /dev/null +++ b/group04/498654356/one/src/org/coding/five/StackUtil.java @@ -0,0 +1,152 @@ +package org.coding.five; + +import java.util.Arrays; + +import org.coding.one.Stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * *** 使用中间变量和长度来完成 + */ + public static void reverse(Stack s) { + if(isEmpty(s)) { + return; + } + Stack temp = new Stack(); + int size = s.size(); + int count = 0; + while(count < size) { + Object pop = s.pop(); + for(int i = count + 1; i < size; i++) { + temp.push(s.pop()); + } + s.push(pop); + move(temp, s); + count++; + } + } + + // ***递归,通过每一个函数栈存放一个元素 + public static void reverse2(Stack s) { + if(isEmpty(s)) { + return; + } + Stack temp = new Stack(); + move(s, temp); + addTop(temp.pop(), temp, s); + } + + + private static void addTop(Object pop, Stack temp, Stack s) { + if(!temp.isEmpty()) { + addTop(temp.pop(), temp, s); + } + s.push(pop); + } + + private static boolean isEmpty(Stack s) { + return s == null || s.isEmpty(); + } + + private static void move(Stack source, Stack dest) { + while(!source.isEmpty()) { + dest.push(source.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(isEmpty(s) || o == null) { + return; + } + Stack temp = new Stack(); + while(!s.isEmpty()) { + Object dest = s.pop(); + if(!o.equals(dest)) { + temp.push(dest); + } + } + move(temp, s); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if(isEmpty(s) || len < 1) { + return null; + } + Object[] result = new Object[len]; + int count = 0; + Stack temp = new Stack(); + while(!s.isEmpty() && count < len) { + Object v = s.pop(); + result[count] = v; + temp.push(v); + count++; + } + move(temp, s); + return Arrays.copyOf(result, count); + } + /** + * 字符串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){ + if(s== null || s.isEmpty()) { + return false; + } + char a = '('; + char b = '['; + char c = '{'; + char a2 = ')'; + char b2 = ']'; + char c2 = '}'; + Stack stack = new Stack(); + for(int i = 0, length = s.length(); i < length; i++) { + char charAt = s.charAt(i); + if(charAt == a) { + stack.push(a); + } else if(charAt == b){ + stack.push(b); + } else if(charAt == c){ + stack.push(c); + } else if(charAt == a2){ + if(!isEqualStackTopValue(a, stack)) { + return false; + } + } else if(charAt == b2){ + if(!isEqualStackTopValue(b, stack)) { + return false; + } + } else if(charAt == c2){ + if(!isEqualStackTopValue(c, stack)) { + return false; + } + } + } + + return true; + } + + private static boolean isEqualStackTopValue(char a2, Stack stack) { + return (char) stack.pop() == a2; + } + + +} diff --git a/group04/498654356/one/src/org/coding/four/lru/LRUPageFrame.java b/group04/498654356/one/src/org/coding/four/lru/LRUPageFrame.java index 1113e39e7a..8f6b187273 100644 --- a/group04/498654356/one/src/org/coding/four/lru/LRUPageFrame.java +++ b/group04/498654356/one/src/org/coding/four/lru/LRUPageFrame.java @@ -37,38 +37,46 @@ public LRUPageFrame(int capacity) { * @return */ public void access(int pageNum) { + Node node = findNode(pageNum); + if(node == null) { + addNode(pageNum); + } else { + moveExistNode(node); + } + } + + private void moveExistNode(Node node) { + if(node == first) { + return ; + } + if(node == last) { + removeLastNode(); + node.next = first; + first.prev = node; + first = node; + return; + } + node.prev.next = node.next; + node.next.prev = node.prev; + node.prev = null; + node.next = first; + first = node; + } + + private void addNode(int pageNum) { if(first == null) { first = new Node(); first.pageNum = pageNum; last = first; - } else { - if(isFull()) { - Node node = findNode(pageNum); - if(node == null) { // not found - removeLastNode(); - push(pageNum); - } else { - if(node == first) { - return ; - } - if(node == last) { - removeLastNode(); - node.next = first; - first.prev = node; - first = node; - return; - } - node.prev.next = node.next; - node.next.prev = node.prev; - node.prev = null; - node.next = first; - first = node; - } - } else { + }else { + if(isFull()) { + removeLastNode(); + push(pageNum); + }else { push(pageNum); } } - + } private boolean isFull() { @@ -91,6 +99,9 @@ private void push(int pageNum) { private Node findNode(int pageNum) { + if(first == null) { + return null; + } if(first.pageNum == pageNum) { return first; } @@ -122,7 +133,6 @@ public String toString(){ Node node = first; while(node != null){ buffer.append(node.pageNum); - node = node.next; if(node != null){ buffer.append(","); diff --git a/group04/498654356/one/test/org/coding/five/StackUtilTest.java b/group04/498654356/one/test/org/coding/five/StackUtilTest.java new file mode 100644 index 0000000000..bb5dc80813 --- /dev/null +++ b/group04/498654356/one/test/org/coding/five/StackUtilTest.java @@ -0,0 +1,85 @@ +package org.coding.five; + +import org.coding.one.Stack; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class StackUtilTest { + Stack s ; + + @Before + public void setUp() throws Exception { + s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + } + + @After + public void tearDown() throws Exception { + s = null; + } + + @Test + public void testReverse() { + StackUtil.reverse(s); + Assert.assertEquals(5, s.size()); + Assert.assertEquals(1, s.pop()); + Assert.assertEquals(2, s.pop()); + Assert.assertEquals(3, s.pop()); + Assert.assertEquals(4, s.pop()); + Assert.assertEquals(5, s.pop()); + } + @Test + public void testReverse2() { + StackUtil.reverse2(s); + Assert.assertEquals(5, s.size()); + Assert.assertEquals(1, s.pop()); + Assert.assertEquals(2, s.pop()); + Assert.assertEquals(3, s.pop()); + Assert.assertEquals(4, s.pop()); + Assert.assertEquals(5, s.pop()); + } + @Test + public void testRemove() { + StackUtil.remove(s, 1); + Assert.assertEquals(4, s.size()); + Assert.assertEquals(5, s.pop()); + Assert.assertEquals(4, s.pop()); + Assert.assertEquals(3, s.pop()); + Assert.assertEquals(2, s.pop()); + Assert.assertEquals(0, s.size()); + } + + @Test + public void testGetTop() { + Object[] top = StackUtil.getTop(s, 2); + Assert.assertEquals(5, top[0]); + Assert.assertEquals(4, top[1]); + + Assert.assertEquals(5, s.size()); + Assert.assertEquals(5, s.pop()); + Assert.assertEquals(4, s.pop()); + Assert.assertEquals(3, s.pop()); + Assert.assertEquals(2, s.pop()); + Assert.assertEquals(1, s.pop()); + Assert.assertEquals(0, s.size()); + } + + @Test + public void testIsValidPairs() { + String s = "([e{d}f])"; + boolean v = StackUtil.isValidPairs(s); + Assert.assertEquals(true, v); + s = "([b{x]y})"; + v = StackUtil.isValidPairs(s); + Assert.assertEquals(false, v); + + } + +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/DownloadThread.java b/group04/844028312/data-structure/src/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..580da85576 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/DownloadThread.java @@ -0,0 +1,48 @@ +package com.coderising.download; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String url; + public DownloadThread(CyclicBarrier barrier, String url, int startPos, int endPos){ + this.barrier=barrier; + //this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.url=url; + } + public void run(){ + try { + ConnectionManager cm = new ConnectionManagerImpl(); + conn=cm.open(url); + + byte[] b=conn.read(startPos, endPos); + + RandomAccessFile randomFile = new RandomAccessFile("D://test.zip", "rw"); + write(randomFile,b); + barrier.await(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + public synchronized void write(RandomAccessFile randomFile ,byte[] b) throws IOException{ + randomFile.seek(startPos); + randomFile.write(b); + randomFile.close(); + } +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/FileDownloader.java b/group04/844028312/data-structure/src/com/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..9d81ef03be --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/FileDownloader.java @@ -0,0 +1,86 @@ +package com.coderising.download; + +import java.util.concurrent.CyclicBarrier; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + + CyclicBarrier cb = new CyclicBarrier(4, new Runnable() { + @Override + public void run() { + // TODO Auto-generated method stub + listener.notifyFinished(); + + } + }); + conn=cm.open(url); + int length = conn.getContentLength(); + new DownloadThread(cb,url,0,length/4).start(); + new DownloadThread(cb,url,length/4+1,(length/4)*2).start(); + new DownloadThread(cb,url,(length/4)*2+1,(length/4)*3).start(); + new DownloadThread(cb,url,(length/4)*3+1,length-1).start(); + + + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/FileDownloaderTest.java b/group04/844028312/data-structure/src/com/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..b1cc492c33 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/FileDownloaderTest.java @@ -0,0 +1,115 @@ +package com.coderising.download; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + private static Integer pages=1; // 网页数 + + private static boolean exeFlag=true; // 执行标识 + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url="http://mirrors.hust.edu.cn/apache/tomcat/tomcat-8/v8.0.41/bin/apache-tomcat-8.0.41-windows-x64.zip"; + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + //Thread.sleep(5000); + } catch (Exception e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + + //http://image.so.com/v?ie=utf-8&src=hao_360so&q=%E9%AB%98%E5%9C%86%E5%9C%86&correct=%E9%AB%98%E5%9C%86%E5%9C%86&fromurl=http%3A%2F%2Fwww.cesiu.org.cn%2Fomdsj%2F2010674.html&gsrc=1#multiple=0&dataindex=57&id=537876d111c8adfec7fbda2b80a4f67b + @Test + public void testOpen() throws ConnectionException { + + + + ExecutorService executorService=Executors.newFixedThreadPool(10); // 创建ExecutorService 连接池创建固定的10个初始线程 + + while(exeFlag){ + if(pages<=100){ +// executorService.execute(new Runnable(){ +// +// @Override +// public void run() { +// // TODO Auto-generated method stub +// System.out.println(Thread.currentThread().getName()); +// System.out.println("爬取了第"+pages+"网页..."); +// pages++; +// } +// +// }); + new Runnable(){ + + @Override + public void run() { + // TODO Auto-generated method stub + System.out.println(Thread.currentThread().getName()); + System.out.println("爬取了第"+pages+"网页..."); + pages++; + } + + }.run();; + + }else{ + if(((ThreadPoolExecutor)executorService).getActiveCount()==0){ // 活动线程是0 + executorService.shutdown(); // 结束所有线程 + exeFlag=false; + System.out.println("爬虫任务已经完成"); + } + } + try { + // Thread.sleep(2000); // 线程休息0.1秒 + } catch (Exception e) { + e.printStackTrace(); + } + + } + + } +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/api/Connection.java b/group04/844028312/data-structure/src/com/coderising/download/api/Connection.java new file mode 100644 index 0000000000..0957eaf7f4 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionException.java b/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..c3ed7396e7 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionManager.java b/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..ce045393b1 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/api/DownloadListener.java b/group04/844028312/data-structure/src/com/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..bf9807b307 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group04/844028312/data-structure/src/com/coderising/download/impl/ConnectionImpl.java b/group04/844028312/data-structure/src/com/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..4849434761 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,54 @@ +package com.coderising.download.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.Arrays; + +import com.coderising.download.api.Connection; + +public class ConnectionImpl implements Connection{ + HttpURLConnection urlConnection; + + + + public HttpURLConnection getUrlConnection() { + return urlConnection; + } + + public void setUrlConnection(HttpURLConnection urlConnection) { + this.urlConnection = urlConnection; + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + byte[] buffer = new byte[endPos-startPos+1]; + int count=0; + urlConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + InputStream ips=urlConnection.getInputStream(); + //ips.skip(startPos); + while(count action=new HashMap(); + private boolean find=false; + public static View runAction(String actionName, Map parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + View v=new View(); + //创建SAXReader对象 + SAXReader reader = new SAXReader(); + Struts struts=new Struts(); + File file=new File(Struts.class.getResource("struts.xml").getFile()); + Document document; + try { + document = reader.read(file); + Element root=document.getRootElement(); + struts.listNodes("login",root); + if(struts.getAction().size()!=0){ + try { + String className=struts.getAction().get("class"); + Class c=Class.forName(className); + Object obj = c.newInstance(); + Method[] methods = c.getDeclaredMethods(); + Iterator iter = parameters.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + Object key = entry.getKey(); + Object val = entry.getValue(); + for(Method m:methods){ + String sName=m.getName().substring(0, 3); + String eName=m.getName().substring(3, m.getName().length()).toLowerCase(); + + if("set".equals(sName)&&key.equals(eName)){ + m.invoke(obj, val); + break; + } + } + } + Method exectue= c.getDeclaredMethod("execute"); + String key=(String) exectue.invoke(obj, null); + String jsp; + if(key!=null&&!"".equals(key)){ + jsp=struts.getAction().get(key); + v.setJsp(jsp); + } + Map map=new HashMap<>(); + for(Method m:methods){ + String sName=m.getName().substring(0, 3); + + if("get".equals(sName)){ + String key2=m.getName().substring(3, m.getName().length()).toLowerCase(); + String values=(String) m.invoke(obj, null); + map.put(key2, values); + } + } + v.setParameters(map); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } catch (DocumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + return v; + } + public Map getAction() { + return action; + } + public void setAction(Map action) { + this.action = action; + } + public Map listNodes(String actionName,Element node){ + String name=node.getName(); //节点名字 + if("action".equals(name)){ + List attributes=node.attributes();//获取节点属性 + for(Attribute attribute:attributes){ + String aName=attribute.getName(); + if("name".equals(aName)&&attribute.getValue().equals(actionName)){ + for(Attribute attribute2:attributes){ + String cName=attribute2.getName(); + if("class".equals(cName)){ + action.put(cName, attribute2.getValue()); + Iterator iterator=node.elementIterator(); + while(iterator.hasNext()){ + Element rNode=iterator.next(); + String result=rNode.getName(); + if("result".equals(result)){ + List attributes3=rNode.attributes(); + for(Attribute attribute3:attributes3){ + String rName=attribute3.getName(); + if("name".equals(rName)){ + String rValue=attribute3.getValue(); + action.put(rValue, rNode.getTextTrim()); + break; + } + } + + + } + else{ + break; + } + } + break; + } + } + find=true; + break; + } + } + } + Iterator iterator=node.elementIterator(); + while(iterator.hasNext()&&!find){ + listNodes(actionName,iterator.next()); + } + return null; + } + + +} diff --git a/group04/844028312/data-structure/src/com/coderising/litestruts/StrutsTest.java b/group04/844028312/data-structure/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..6511d77741 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,50 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } + @Test + public void test() { + String actionName = "login"; + Map params = new HashMap(); + + View view = Struts.runAction(actionName,params); + + } +} diff --git a/group04/844028312/data-structure/src/com/coderising/litestruts/View.java b/group04/844028312/data-structure/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/group04/844028312/data-structure/src/com/coderising/litestruts/View.java @@ -0,0 +1,23 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/BinaryTreeNode.java b/group04/844028312/data-structure/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..d6a4c888c1 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/BinaryTreeNode.java @@ -0,0 +1,145 @@ +package com.coding.basic; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + if(data==null){ //жϸڵǷΪ + data=o; + left=null; + right=null; + } + else{ + int insertData=(int) o; + int nowData=(int) data; + if(left==null || right==null){ //1.left==null right==null,2.left!=null,right==null,3.left==null.right!=null + if(nowData>=insertData && left==null){ //жϲСһڵ,left==null + left=new BinaryTreeNode(); + left.data=o; + left.left=null; + left.right=null; + } + else if(insertData>nowData && right==null){ //жϲһڵ,==null + right=new BinaryTreeNode(); + right.data=o; + right.left=null; + right.right=null; + } + else{ + BinaryTreeNode treeNode=null; //¼ȽϽڵ + if(nowData>=insertData ){ //ǰڵݴ + treeNode=left; //ȽϽڵΪڵ + } + else{ + treeNode=right; //Ϊҽڵ + } + BinaryTreeNode tempNode=null; //ʱڵ㣬ڼ¼ȽϽڵڵҽڵΪʱ¼ȽϽڵ + while(treeNode!=null){ + nowData=(int) treeNode.data; //ĵǰֵ + if(insertData<=nowData){ //ǰڵݴ + tempNode=treeNode.left; //ʱڵΪڵ + } + else{ + tempNode=treeNode.right; //Ϊҽڵ + } + if(tempNode==null){ + tempNode=treeNode; //¼ȽϽڵ + if(insertData<=nowData){ //ǰڵݴ + treeNode=treeNode.left; //ȽϽڵΪڵ + } + else{ + treeNode=treeNode.right; //Ϊҽڵ + } + } + else{ + treeNode=tempNode; //ʱڵ㲻ΪʱȽϽڵ㸳ֵΪʱڵ + } + } + if(treeNode==null){ //ȽϽڵΪʱ + treeNode=new BinaryTreeNode(); //½ڵ + treeNode.data=o; + treeNode.left=null; + treeNode.right=null; + int upData=(int) tempNode.data; + if(insertData<=upData){ //һڵݴڲڵʱ + tempNode.left=treeNode; //һڵڵ㸳ڵ + } + else{ + tempNode.right=treeNode; + } + } + } + } + else{ //left!=null&&right!=null + BinaryTreeNode treeNode=null; //жһ + if(nowData>=insertData ){ + treeNode=left; + } + else{ + treeNode=right; + } + BinaryTreeNode tempNode=null; + while(treeNode!=null){ + nowData=(int) treeNode.data; + if(insertData<=nowData){ + tempNode=treeNode.left; + } + else{ + tempNode=treeNode.right; + } + if(tempNode==null){ + tempNode=treeNode; + if(insertData<=nowData){ + treeNode=treeNode.left; + } + else{ + treeNode=treeNode.right; + } + } + else{ + treeNode=tempNode; + } + } + if(treeNode==null){ + treeNode=new BinaryTreeNode(); + treeNode.data=o; + treeNode.left=null; + treeNode.right=null; + int upData=(int) tempNode.data; + if(insertData<=upData){ + tempNode.left=treeNode; + } + else{ + tempNode.right=treeNode; + } + } + } + } + return this; + } + + + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/Iterator.java b/group04/844028312/data-structure/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/Iterator.java @@ -0,0 +1,7 @@ +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/List.java b/group04/844028312/data-structure/src/com/coding/basic/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/List.java @@ -0,0 +1,9 @@ +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/Queue.java b/group04/844028312/data-structure/src/com/coding/basic/Queue.java new file mode 100644 index 0000000000..36e516e266 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/Queue.java @@ -0,0 +1,19 @@ +package com.coding.basic; + +public class Queue { + + public void enQueue(Object o){ + } + + public Object deQueue(){ + return null; + } + + public boolean isEmpty(){ + return false; + } + + public int size(){ + return -1; + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/Stack.java b/group04/844028312/data-structure/src/com/coding/basic/Stack.java new file mode 100644 index 0000000000..459ec560b4 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/Stack.java @@ -0,0 +1,24 @@ +package com.coding.basic; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + } + + public Object pop(){ + return null; + } + + public Object peek(){ + return null; + } + public boolean isEmpty(){ + return false; + } + public int size(){ + return -1; + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/array/ArrayList.java b/group04/844028312/data-structure/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..ee05b19081 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,100 @@ +package com.coding.basic.array; + +import java.util.Arrays; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class ArrayList implements List { + + private int size = 0; + private static final int DEFAULT_CAPACITY = 10; + private Object[] elementData = new Object[100]; + /** + * ���Ԫ�� + */ + public void add(Object o){ + + if(size=0 && index<=size){ //�ж� index�Ƿ���size��Χ�� 1 2 3 4 + if(size+1array2[j]){ + newArray[count++]=array2[j++]; + + } + if(array1[i]2){ + a=new int[max]; + int record=2; + do{ + a[0]=1; + a[1]=1; + a[record]=a[record-2]+a[record-1]; + record++; + }while(a[record-1]=2){ + while(n1;i--){ + if(n%i==0){ + isPrime=false; + break; + } + + } + if(isPrime){ + primes[record]=n; + record++; + } + n++; + } + } + + return Arrays.copyOf(primes, record); + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + int min=6; + int[] perfect=new int[10]; + int record=0; + if(max>=min){ + while(min0;i--){ + if(min%i==0){ + sum=sum+i; + } + } + if(sum==min){ + perfect[record]=min; + record++; + } + min++; + + } + } + return Arrays.copyOf(perfect, record); + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator){ + StringBuffer sb=new StringBuffer(); + for(int i=0;i=0&&index7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node temp1=last; + for(int i=size-2;i>=0;i--){ + Node temp2=indexOf(i); + temp1.next=temp2; + temp1=temp2; + } + head.next=null; + temp1=head; + head=last; + last=temp1; + } + + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + if(size>1){ + Node index=indexOf(size/2-1); + index.next=null; + last=index; + size=size-size/2; + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){//1 2 3 4 5 + if( i=0){ + int len=length+i>size? size-i:length; + int j=0; + while(j0 && i>=0){ + Node before=indexOf(i-1); + Node after=indexOf(length+i); + if(before==null&&after==null){ + head=null; + last=null; + size=0; + } + else if(before==null&&after!=null){ + head=after; + size=size-length; + } + else if(before!=null&&after==null){ + before.next=null; + last=before; + size=size-length; + } + else{ + before.next=after; + size=size-length; + } + }*/ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + if(list==null){ + return null; + } + int size=list.size; + int jude=0; + int [] newInt=new int[size]; + while(jude0){ + int index=(int) list.get(jude); + if(index>=0&&index0){ + int index=(int) list.get(jude); + for(int i=0;imin){ + start=i; + } + if((int)temp.data>=max){ + end=i; + break; + } + i++; + temp=temp.next; + } + if(start==-1){ + start=0; + } + if(end==-1){ + end=size; + } + this.remove(start,end-start); + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + if(list==null){ + return null; + } + int i=0; + int j=0; + LinkedList c=new LinkedList(); + while(i(int)list.get(j)){ + j++; + } + else{ + i++; + } + } + return c; + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/queue/CircleQueue.java b/group04/844028312/data-structure/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..48bcbd01f5 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,43 @@ +package com.coding.basic.queue; + +public class CircleQueue { + private int size; + private int real; + private int front; + private Object[] object; + public CircleQueue(int size){ + this.size=size+1; + object=new Object[this.size]; + this.real=0; + this.front=0; + } + public boolean isEmpty(){ + return real==front; + } + public int size(){ + if(isEmpty()) + return 0; + else + return real; + } + public Object deQueue(){ + if(!isEmpty()){ + + Object o=object[front]; + object[front]=null; + front=(front+1)%size; + return o; + } + return null; + } + public void enQueue(Object o){ + if(!queueFull()){ + object[real]=o; + real=(real+1)%size; + } + } + private boolean queueFull(){ + + return (real+1)%size==front; + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/queue/Josephus.java b/group04/844028312/data-structure/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..46defa87cc --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,80 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +import com.coding.basic.Queue; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死,直到最后一个人留下来 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + List list=new ArrayList(); + Queue queue1=new Queue(); + Queue queue2=new Queue(); + for(int i=0;i1){ + int tag = 1; + int i=0; + while(tag1) + reset(queue1,queue2); + else{ + if(!queue1.isEmpty()) + list.add((Integer) queue1.deQueue()); + if(!queue2.isEmpty()) + list.add((Integer) queue2.deQueue()); + } + } + + return list; + } + private static void reset(Queue queue1,Queue queue2){ + if(queue1.isEmpty()){ + while(!queue2.isEmpty()){ + queue1.enQueue(queue2.deQueue()); + } + } + else{ + while(!queue1.isEmpty()){ + queue2.enQueue(queue1.deQueue()); + } + while(!queue2.isEmpty()){ + queue1.enQueue(queue2.deQueue()); + } + } + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/queue/JosephusTest.java b/group04/844028312/data-structure/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..8806a7b615 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,26 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/queue/Queue.java b/group04/844028312/data-structure/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..cd69fde72a --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,26 @@ +package com.coding.basic.queue; + +import com.coding.basic.linklist.LinkedList; + +public class Queue { + private LinkedList linkedList=new LinkedList(); + + public void enQueue(Object o){ + linkedList.addLast(o); + } + + public Object deQueue(){ + return linkedList.removeFirst(); + } + + public boolean isEmpty(){ + if(linkedList.size()>0){ + return false; + } + return true; + } + + public int size(){ + return linkedList.size(); + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group04/844028312/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..37c181b022 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,53 @@ +package com.coding.basic.queue; + +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + + + public int size() { + return stack1.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + E item; + while(!stack1.isEmpty()){ + if(stack1.size()==1){ + item=stack1.pop(); + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + return item; + } + else{ + stack2.push(stack1.pop()); + } + } + return null; + } + + + } + diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/Stack.java b/group04/844028312/data-structure/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..6079d67598 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,30 @@ +package com.coding.basic.stack; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); //��ջ��ѹ��Ԫ�� + } + + public Object pop(){ + Object o=elementData.get(elementData.size()-1); //ջ��Ԫ�أ���Ϊջ�Ƚ��� + elementData.remove(elementData.size()-1); //�Ƴ�ջ��Ԫ�� + return o; + } + + public Object peek(){ + return elementData.get(elementData.size()-1); //��ȡջ��Ԫ�� + } + public boolean isEmpty(){ + if(elementData.size()==0){ //���elementData.size�ж��Ƿ�Ϊ�� + return true; + } + return false; + } + public int size(){ + return elementData.size(); + } +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/StackUtil.java b/group04/844028312/data-structure/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..569b217b4c --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,135 @@ +package com.coding.basic.stack; +import java.util.Stack; +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(isEmpty(s)){ + return ; + } + Stack help=new Stack(); + int size=0; + while(!s.isEmpty()){ + Object o=s.pop(); + help.push(o); + size++; + } + Object[] o=new Object[size]; + int i=0; + while(!help.isEmpty()){ + o[i]=help.pop(); + i++; + } + for(int j=0;j s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..3028e168c5 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,207 @@ +package com.coding.basic.stack.expr; + +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.coding.basic.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + if(expr==null|| expr.equals("")){ + return 0.0f; + } + Stack numStack=new Stack(); + Stack opoStack=new Stack(); + int num = 0; + StringTokenizer st = new StringTokenizer(expr,"+,-,*,/",true); + + while(st.hasMoreElements()){ + String s=(String) st.nextElement(); + if("+".equals(s) || "*".equals(s) || "-".equals(s)|| "/".equals(s)){ + if(opoStack.isEmpty()){ + opoStack.push(s); + } + else{ + num=opoPush(opoStack,numStack,s); + } + } + else { +// if(num!=0){ +// Stack temp=new Stack(); +// while(!numStack.isEmpty()){ +// temp.push(numStack.pop()); +// } +// String top = null; +// String a = null; +// int j=0; +// while(!temp.isEmpty()){ +// top=(String) temp.pop(); +// if(j==num){ +// a=top; +// numStack.push(s); +// } +// else{ +// numStack.push(top); +// } +// j++; +// } +// numStack.push(a); +// } +// else{ +// numStack.push(s); +// } + numStack.push(s); + } + } + float result = 0; + if(!opoStack.isEmpty()){ + String opoOne=(String) opoStack.pop(); + String opoTwo=(String) opoStack.pop(); + opoStack.push(opoTwo); + opoStack.push(opoOne); + if(("*".equals(opoOne)||"/".equals(opoOne))&&("*".equals(opoTwo)||"/".equals(opoTwo))){ + + } + else if("*".equals(opoOne)||"/".equals(opoOne)){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + String opo=(String) opoStack.pop(); + if("-".equals(opo)){ + result=two-one; + } + else if("+".equals(opo)){ + result=one+two; + } + else if("/".equals(opo)){ + result=two/one; + } + else { + result=two*one; + } + numStack.push(result+""); + } + } + Stack revOpo=new Stack(); + Stack revNum=new Stack(); + + while(!opoStack.isEmpty()){ + revOpo.push(opoStack.pop()); + } + while(!numStack.isEmpty()){ + revNum.push(numStack.pop()); + } + while(!revOpo.isEmpty()){ + float one= Float.parseFloat((String) revNum.pop()) ; + float two= Float.parseFloat((String) revNum.pop()); + String opo=(String) revOpo.pop(); + if("-".equals(opo)){ + result=one-two; + } + else if("+".equals(opo)){ + result=one+two; + } + else if("/".equals(opo)){ + result=one/two; + } + else { + result=two*one; + } + revNum.push(result+""); + } + return Float.parseFloat((String) revNum.pop()); + } + //2+3*4+5 5-2-2+3--> 5+3-2 75/3/5*5 15*5/3 + private int opoPush(Stack opoStack,Stack numStack,Object opo){ + int num=0;//记录减号的最深位置 + if("+".equals(opo)){ + if(!opoStack.isEmpty()){ + if("*".equals(opoStack.peek())||"/".equals(opoStack.peek())){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + float result; + if("*".equals(opoStack.peek())){ + opoStack.pop(); + result=two*one; + } + else{ + result=two/one; + } + numStack.push(result+""); + } + } +// Stack temp=new Stack(); +// boolean flag=false; //记录是否转移位置 +// while(!opoStack.isEmpty()){ +// temp.push(opoStack.pop()); +// } +// int i=0; +// while(!temp.isEmpty()){ +// String top= (String) temp.pop(); +// if("-".equals(top)&&!flag){ +// num=i+1; +// opoStack.push("+"); +// flag=true; +// } +// opoStack.push(top); +// i++; +// } +// if(!flag){ +// opoStack.push("+"); +// } + opoStack.push("+"); + } + else if("-".equals(opo)){ + if(!opoStack.isEmpty()){ + if("*".equals(opoStack.peek())||"/".equals(opoStack.peek())){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + float result; + if("*".equals(opoStack.peek())){ + opoStack.pop(); + result=one*two; + } + else{ + result=one/two; + } + numStack.push(result+""); + } + } + opoStack.push("-"); + } + else if("*".equals(opo)){ +// Stack temp=new Stack(); +// boolean flag=false; //记录是否转移位置 +// while(!opoStack.isEmpty()){ +// temp.push(opoStack.pop()); +// } +// int i=0; +// while(!temp.isEmpty()){ +// String top=(String) temp.pop(); +// if("/".equals(top)&&!flag){ +// num=i+1; +// opoStack.push("*"); +// flag=true; +// } +// opoStack.push(top); +// i++; +// } +// if(!flag){ +// opoStack.push("*"); +// } + opoStack.push("*"); + } + else if("/".equals(opo)){ + opoStack.push("/"); + } + return num; + } + + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..25a26547e9 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,60 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("5-2+3"); + Assert.assertEquals(6.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr(" 5-2-2+3");//5+3-2-2 + Assert.assertEquals(4, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("75/3/5*5"); //75*5/3/5 0.6 + Assert.assertEquals(25.0, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..bf1c0052a5 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,35 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + + +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser parser=new TokenParser(); + List exprs=parser.parse(expr); + List numStack=new ArrayList(); + Stack ope=new Stack(); + for(Token token:exprs){ + if(token.isOperator()){ + if(!ope.isEmpty()&&!token.hasHigherPriority(ope.peek())){ + numStack.add(ope.pop()); + } + ope.push(token); + } + else if(token.isNumber()){ + numStack.add(token); + } + } + while(!ope.isEmpty()){ + numStack.add(ope.pop()); + } + return numStack; + } + + + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..c9febad48b --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser=new TokenParser(); + List tokens=tokenParser.parse(expr); + Stack stack=new Stack(); + for(Token token:tokens){ + if(token.isNumber()){ + stack.push(new Float(token.getIntValue())); + } + else{ + float one =(float) stack.pop(); + float two=(float) stack.pop(); + float result = 0; + String ope=token.toString(); + if(ope.equals("-")){ + result=two-one; + } + else if(ope.equals("*")){ + result=two*one; + } + else if(ope.equals("/")){ + result=two/one; + } + else if(ope.equals("+")){ + result=two+one; + } + stack.push(result); + } + } + return (float) stack.pop(); + } + + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c4e3ca2dae --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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 9 2 3 * + 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/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..f3879f31f6 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,91 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +import com.coding.basic.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser=new TokenParser(); + List tokens=tokenParser.parse(expr); + Stack stack=new Stack(); + for(Token token:tokens){ + if(token.isNumber()){ + float result = 0; + if(!(stack.peek().equals("-")||stack.peek().equals("*")||stack.peek().equals("/")||stack.peek().equals("+"))){ + float one = new Float( (float)stack.pop()); + float two =token.getIntValue(); + String ope=(String) stack.pop(); + if(ope.equals("-")){ + result=one-two; + } + else if(ope.equals("*")){ + result=two*one; + } + else if(ope.equals("/")){ + result=one/two; + } + else if(ope.equals("+")){ + result=two+one; + } + + while(!("-".equals(stack.peek())||"*".equals(stack.peek())||"/".equals(stack.peek())||"+".equals(stack.peek()))&&!stack.isEmpty()){ + one =new Float( (float)stack.pop()); + + ope=(String) stack.pop(); + if(ope.equals("-")){ + result=one-result; + } + else if(ope.equals("*")){ + result=result*one; + } + else if(ope.equals("/")){ + result=one/result; + } + else if(ope.equals("+")){ + result=result+one; + } + + } + stack.push(result); + } + else + stack.push(new Float((float)token.getIntValue())); + + } + else if(token.isOperator()){ + + stack.push(token.toString()); + } + } + while(stack.size()>1){ + float one = new Float( (float)stack.pop()); + float two = new Float( (float)stack.pop()); + float result = 0; + String ope=(String) stack.pop(); + if(ope.equals("-")){ + result=two-one; + } + else if(ope.equals("*")){ + result=two*one; + } + else if(ope.equals("/")){ + result=two/one; + } + else if(ope.equals("+")){ + result=two+one; + } + stack.push(result); + + } + return (float) stack.pop() ; + } + + +} diff --git a/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..03e6bcaaab --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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");// -++66 + 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/group04/844028312/data-structure/src/com/coding/basic/stack/expr/Token.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParser.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d3b0f167e1 --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.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/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/group04/844028312/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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"); + + 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/group04/844028312/min-jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group04/844028312/min-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group04/844028312/min-jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e8b0da8f82 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,96 @@ +package com.coderising.jvm.attr; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; +import com.coderising.jvm.util.Util; + + +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; + } + + public void setCmds(ByteCodeCommand[] cmds) { + this.cmds = 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 attrNameIndex=iter.nextU2toInt(); + int attrLen=iter.nextU4toInt(); + int maxStack=iter.nextU2toInt(); + int maxLocals=iter.nextU2toInt(); + int codeLen=iter.nextU4toInt(); + byte[] codes=iter.getByte(codeLen); + String code = null; + try { + code=Util.byteToHexString(codes); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + CodeAttr codeAttr=new CodeAttr(attrNameIndex,attrLen,maxStack,maxLocals,codeLen,code); + + int exceNum=iter.nextU2toInt(); + System.out.println("exception num"+exceNum); + //如果有exception要实现 + int arrtNum=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(ByteCodeIterator iter){ + int attrNameIndex=iter.nextU2toInt(); + int attrLen=iter.nextU4toInt(); + int itemNum=iter.nextU2toInt(); + LineNumberTable lineTable=new LineNumberTable(attrNameIndex,attrLen); + for(int i=0;i items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + int attrNameIndex=iter.nextU2toInt(); + int attrLen=iter.nextU4toInt(); + int itemNum=iter.nextU2toInt(); + LocalVariableTable localTable=new LocalVariableTable(attrNameIndex,attrLen); + for(int i=0;i 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 method:methods){ + if(pool.getUTF8String(method.getNameIndex()).equals(methodName)&&pool.getUTF8String(method.getDescriptorIndex()).equals(paramAndReturnType)){ + return method; + } + } + + return null; + } + public Method getMainMethod(){ + + return getMethod("main","([Ljava/lang/String;)V"); + } +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group04/844028312/min-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..1f34615ef5 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.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/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..d61049b77e --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + public void visistNullConstant(NullConstantInfo info); + } + +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..93506b1e20 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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/group04/844028312/min-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..6970072491 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,59 @@ +package com.coderising.jvm.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/group04/844028312/min-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..2dabecf630 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,61 @@ +package com.coderising.jvm.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/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..abf55fbd51 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.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) { + // TODO Auto-generated method stub + visitor.visitNameAndType(this); + } +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..ced0c8fc8b --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + visitor.visistNullConstant(this); + } + +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..408557de2c --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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) { + // TODO Auto-generated method stub + visitor.visitString(this); + } + +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..6e67ca727d --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.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) { + // TODO Auto-generated method stub + visitor.visistUTF8(this); + } + + + +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/field/Field.java b/group04/844028312/min-jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..87d22a2485 --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + Field field=new Field(iter.nextU2toInt(),iter.nextU2toInt(),iter.nextU2toInt(),pool); + int attrNum=iter.nextU2toInt(); + System.out.println("attrNum:" + attrNum); + + // TODO : 如果field有属性个数, 这里需要解析 + return field; + } + + public String toString(){ + String nameIndex=this.pool.getUTF8String(this.nameIndex); + String descriptorIndex=this.pool.getUTF8String(this.descriptorIndex); + return nameIndex+":"+descriptorIndex; + + } + +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group04/844028312/min-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..e6080bbb3d --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,43 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + private byte[] codes; + private int pos; + public ByteCodeIterator(byte[] codes){ + this.codes=codes; + this.pos=0; + } + public byte[] getByte(int len){ + byte[] b=new byte[len]; + if(pos+len>codes.length){ + + } + for(int i=0;i 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[] loadClassFile2(String clzFileName) { + + File f = new File(clzFileName); + +// try { +// +// return null;//IOUtils.toByteArray(new FileInputStream(f)); +// +// } catch (IOException e) { +// e.printStackTrace(); +// return null; +// } + return null; + } + + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); + + } + + + + public String getClassPath2(){ + // return StringUtils.join(this.clzPaths,";"); + return null; + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + + + // ------------------------------backup------------------------ + public String getClassPath(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i getParams(){ + List params=new ArrayList(); + MethodRefInfo methodInfo=(MethodRefInfo) this.clzFile.getConstantPool().getConstantInfo(descriptorIndex); + + String paramAndReturnType=methodInfo.getParamAndReturnType(); + //(Ljava/lang/String;I)V + int frist=paramAndReturnType.indexOf("("); + int last=paramAndReturnType.lastIndexOf(")"); + String param=paramAndReturnType.substring(frist+1, last); + if(null==param|| param.equals("")){ + return null; + } + int pos=0; + while(!param.equals("")){ + if(param.charAt(pos)=='L'){ + int end=param.indexOf(";"); + if(end==0){ + new Exception("not find this object"); + } + params.add(param.substring(pos+1, end)); + pos=end+1; + } + else if(param.charAt(pos)=='F'){ + params.add("F"); + pos++; + + } + else if(param.charAt(pos)=='I'){ + params.add("I"); + pos++; + } + param.substring(pos); + } + return params; + } +} diff --git a/group04/844028312/min-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group04/844028312/min-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..46e3ed36da --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,354 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + + + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "F:/workspace/min-jvm/bin"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.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 = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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/group04/844028312/min-jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group04/844028312/min-jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group04/844028312/min-jvm/src/com/coderising/jvm/util/Util.java b/group04/844028312/min-jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group04/844028312/min-jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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;i7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExpr.java b/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..9b30d29928 --- /dev/null +++ b/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,208 @@ +package com.coding.basic.stack.expr; + +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.coding.basic.Stack; +import com.coding.basic.StackUtil; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + if(expr==null|| expr.equals("")){ + return 0.0f; + } + Stack numStack=new Stack(); + Stack opoStack=new Stack(); + int num = 0; + StringTokenizer st = new StringTokenizer(expr,"+,-,*,/",true); + + while(st.hasMoreElements()){ + String s=(String) st.nextElement(); + if("+".equals(s) || "*".equals(s) || "-".equals(s)|| "/".equals(s)){ + if(opoStack.isEmpty()){ + opoStack.push(s); + } + else{ + num=opoPush(opoStack,numStack,s); + } + } + else { +// if(num!=0){ +// Stack temp=new Stack(); +// while(!numStack.isEmpty()){ +// temp.push(numStack.pop()); +// } +// String top = null; +// String a = null; +// int j=0; +// while(!temp.isEmpty()){ +// top=(String) temp.pop(); +// if(j==num){ +// a=top; +// numStack.push(s); +// } +// else{ +// numStack.push(top); +// } +// j++; +// } +// numStack.push(a); +// } +// else{ +// numStack.push(s); +// } + numStack.push(s); + } + } + float result = 0; + if(!opoStack.isEmpty()){ + String opoOne=(String) opoStack.pop(); + String opoTwo=(String) opoStack.pop(); + opoStack.push(opoTwo); + opoStack.push(opoOne); + if(("*".equals(opoOne)||"/".equals(opoOne))&&("*".equals(opoTwo)||"/".equals(opoTwo))){ + + } + else if("*".equals(opoOne)||"/".equals(opoOne)){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + String opo=(String) opoStack.pop(); + if("-".equals(opo)){ + result=two-one; + } + else if("+".equals(opo)){ + result=one+two; + } + else if("/".equals(opo)){ + result=two/one; + } + else { + result=two*one; + } + numStack.push(result+""); + } + } + Stack revOpo=new Stack(); + Stack revNum=new Stack(); + + while(!opoStack.isEmpty()){ + revOpo.push(opoStack.pop()); + } + while(!numStack.isEmpty()){ + revNum.push(numStack.pop()); + } + while(!revOpo.isEmpty()){ + float one= Float.parseFloat((String) revNum.pop()) ; + float two= Float.parseFloat((String) revNum.pop()); + String opo=(String) revOpo.pop(); + if("-".equals(opo)){ + result=one-two; + } + else if("+".equals(opo)){ + result=one+two; + } + else if("/".equals(opo)){ + result=one/two; + } + else { + result=two*one; + } + revNum.push(result+""); + } + return Float.parseFloat((String) revNum.pop()); + } + //2+3*4+5 5-2-2+3--> 5+3-2 75/3/5*5 15*5/3 + private int opoPush(Stack opoStack,Stack numStack,Object opo){ + int num=0;//记录减号的最深位置 + if("+".equals(opo)){ + if(!opoStack.isEmpty()){ + if("*".equals(opoStack.peek())||"/".equals(opoStack.peek())){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + float result; + if("*".equals(opoStack.peek())){ + opoStack.pop(); + result=two*one; + } + else{ + result=two/one; + } + numStack.push(result+""); + } + } +// Stack temp=new Stack(); +// boolean flag=false; //记录是否转移位置 +// while(!opoStack.isEmpty()){ +// temp.push(opoStack.pop()); +// } +// int i=0; +// while(!temp.isEmpty()){ +// String top= (String) temp.pop(); +// if("-".equals(top)&&!flag){ +// num=i+1; +// opoStack.push("+"); +// flag=true; +// } +// opoStack.push(top); +// i++; +// } +// if(!flag){ +// opoStack.push("+"); +// } + opoStack.push("+"); + } + else if("-".equals(opo)){ + if(!opoStack.isEmpty()){ + if("*".equals(opoStack.peek())||"/".equals(opoStack.peek())){ + float one= Float.parseFloat((String) numStack.pop()) ; + float two= Float.parseFloat((String) numStack.pop()); + float result; + if("*".equals(opoStack.peek())){ + opoStack.pop(); + result=one*two; + } + else{ + result=one/two; + } + numStack.push(result+""); + } + } + opoStack.push("-"); + } + else if("*".equals(opo)){ +// Stack temp=new Stack(); +// boolean flag=false; //记录是否转移位置 +// while(!opoStack.isEmpty()){ +// temp.push(opoStack.pop()); +// } +// int i=0; +// while(!temp.isEmpty()){ +// String top=(String) temp.pop(); +// if("/".equals(top)&&!flag){ +// num=i+1; +// opoStack.push("*"); +// flag=true; +// } +// opoStack.push(top); +// i++; +// } +// if(!flag){ +// opoStack.push("*"); +// } + opoStack.push("*"); + } + else if("/".equals(opo)){ + opoStack.push("/"); + } + return num; + } + + +} diff --git a/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExprTest.java b/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..25a26547e9 --- /dev/null +++ b/group04/844028312/one/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,60 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("5-2+3"); + Assert.assertEquals(6.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr(" 5-2-2+3");//5+3-2-2 + Assert.assertEquals(4, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("75/3/5*5"); //75*5/3/5 0.6 + Assert.assertEquals(25.0, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java index 0e0e46f925..c14103ffab 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.coderising.jvm.attr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.loader.ByteCodeIterator; import com.sun.org.apache.bcel.internal.classfile.Attribute; @@ -15,21 +17,24 @@ public String getCode() { return code; } - //private ByteCodeCommand[] cmds ; - //public ByteCodeCommand[] getCmds() { - // return cmds; - //} + 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*/) { + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code, ByteCodeCommand[] cmds) { super(attrNameIndex, attrLen); this.maxStack = maxStack; this.maxLocals = maxLocals; this.codeLen = codeLen; this.code = code; - //this.cmds = cmds; + this.cmds = cmds; } public void setLineNumberTable(LineNumberTable t) { @@ -49,7 +54,10 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ String code = iter.nextUxToHexString(codeLen); System.out.println("code:" + code); - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, cmds); int exceptionTableLen = iter.nextU2toInt(); if (exceptionTableLen > 0) { diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java index e38d3091e4..17fb2d2ec0 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -1,11 +1,12 @@ package com.coderising.jvm.clz; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; -import com.coding.basic.ArrayList; -import com.coding.basic.List; public class ClassFile { private int minorVersion; @@ -15,17 +16,17 @@ public class ClassFile { private ClassIndex clzIndex; private ConstantPool pool; - private List fields = new ArrayList(); - private List methods = new ArrayList(); + private List fields = new ArrayList(); + private List methods = new ArrayList(); public void addField(Field f) { fields.add(f); } - public List getFields() { + public List getFields() { return fields; } - public List getMethods() { + public List getMethods() { return methods; } public ClassIndex getClzIndex() { @@ -78,12 +79,12 @@ public void print(){ } - 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(); } @@ -91,4 +92,25 @@ private String getSuperClassName(){ public void addMethod(Method m) { methods.add(m); } + + public Method getMethod(String methodName, String paramAndReturnType){ + + for(Method m : methods) { + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + + if (name.equals(methodName) && desc.equals(paramAndReturnType)) { + return m; + } + } + + return null; + } + public Method getMainMethod(){ + return getMethod("main", "([Ljava/lang/String;)V"); + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..2b7a52240a --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +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(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..820b3d6002 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,169 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + + + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..c04d14ef3b --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,149 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +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) { + + codes = codes.toUpperCase(); + CommandIterator iter = new CommandIterator(codes); + ArrayList cmds = new ArrayList(); + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if(new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); + } + + } + + 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/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..80a11e67c3 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..232b053643 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..a7c6cca5e7 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,46 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + } + + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..24cb38789a --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,88 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } + + + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..8870f8fa65 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +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; + + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..b40c77754f --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..4f3ab0fb5e --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,147 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..6b1b8c284c --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..aab9c27c2f --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,43 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..334eec9f98 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java index 92ae6bd6f6..fdf965b579 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -21,4 +21,9 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } + } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java index 2e3bef0a4e..d6abf114c9 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -27,4 +27,17 @@ public ConstantInfo getConstantInfo(int index){ return this.constantPool.getConstantInfo(index); } + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visitUTF8(UTF8Info info); + + } + } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java index 0e940b78d0..805de5cd39 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -23,7 +23,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java index 7ff9d5fb77..d9fe4126f4 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -51,4 +51,8 @@ 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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java index 0feffa65b5..cc54887ddf 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -49,6 +49,11 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java index dcac7f97c4..c9b987ceaa 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -42,4 +42,9 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java index fa90d110fe..cfc52f5582 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -9,5 +9,8 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java index d01065fd53..139406d085 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -22,5 +22,10 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java index b7407d146f..cf6409676f 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -26,7 +26,9 @@ public String getValue() { public void setValue(String value) { this.value = value; } - - + @Override + public void accept(Visitor visitor) { + visitor.visitUTF8(this); + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutionResult.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..87ae484b01 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutorEngine.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..982ccff5fa --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,73 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.isEmpty()) { + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()) { + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + } else { + stack.pop(); + } + } + } + + + /** + * 将操作数栈中的操作数load到下一个方法栈的局部变量表中 + * @param currentFrame + * @param nextFrame + */ + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + List paramList = nextMethod.getParameterList(); + //要把this也传递进去 + int paramNum = paramList.size() + 1; + + ArrayList values = new ArrayList(); + + while(paramNum>0) { + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //倒序排列vlaues + ArrayList params = new ArrayList(); + + for(int i = values.size()-1; i>=0; i--) { + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/Heap.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..7df6548625 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/JavaObject.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..be6d3470be --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MethodArea.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..fab7f88878 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,87 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MiniJVM.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..9b7e92ebdc --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/method/Method.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/method/Method.java index 13a8e41994..0c7b13bd3e 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/method/Method.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/method/Method.java @@ -1,6 +1,10 @@ package com.coderising.jvm.method; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; + +import java.util.ArrayList; +import java.util.List; import javax.management.RuntimeErrorException; @@ -77,4 +81,68 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return m; } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + + private String getParamAndReturnType(){ + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } + } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..b6dc906db9 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.print; + +import java.util.Formatter; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; + +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.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.getMajorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "E:\\practise\\group05\\1094051862\\mini-jvm\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..d56de1e8be --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,89 @@ +package com.coderising.jvm.print; + +import java.util.Formatter; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantInfo.Visitor; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + Formatter formatter = new Formatter(System.out); + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8"); + formatter.format("%-15s %-10s\n", + "UTF8",info.getValue()); + } + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("#").append(info.getIndex()); + formatter.format("%-15s %-10s %-10s\n", + "String", buffer, "// "+pool.getUTF8String(info.getIndex())); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("#").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + + formatter.format("%-15s %-10s %-10s\n", + "NameAndType", buffer, + "// "+pool.getUTF8String(info.getIndex1())+":"+pool.getUTF8String(info.getIndex2())); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("#").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + formatter.format("%-15s %-10s %-10s\n", + "MethodRef", buffer, + "// "+info.getClassName()+"."+info.getMethodName()+":"+info.getParamAndReturnType()); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("#").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + formatter.format("%-15s %-10s %-10s\n", + "FieldRef", buffer, + "// "+info.getClassName()+"."+info.getFieldName()+":"+info.getFieldType()); + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("#").append(info.getUtf8Index()); + formatter.format("%-15s %-10s %-10s\n", + "Class", buffer, "// "+info.getClassName()); + } + }; + + for(int i = 1; i <= pool.getSize(); i++) { + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.printf("%8s", "#" + i + " = ");//左对齐,8个空格 + constantInfo.accept(visitor); + } + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java index db02c29132..61c83b4224 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,6 +1,7 @@ package com.coderising.jvm.test; import java.io.IOException; +import java.util.List; import org.junit.After; import org.junit.Assert; @@ -9,6 +10,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; @@ -17,7 +22,6 @@ import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; import com.coderising.jvm.method.Method; -import com.coding.basic.List; @@ -274,4 +278,79 @@ private void assertMethodEquals(ConstantPool pool,Method m , String expectedName 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/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/MiniJVMTest.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..842420f827 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "E:\\practise\\group05\\1094051862\\mini-jvm\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/queue/CircleQueue.java b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..40ca7613d9 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,69 @@ +package com.coding.basic.queue; + +/** + * 用数组实现循环队列 + * 没有牺牲一个元素空间,所以判断队空,队满需要取数据验证。 + * @author zhaohongxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + + return elementData[front]==null; + + } + + public int size() { + if (isFull()) { + return DEFAULT_SIZE; + } else if (isEmpty()) { + return 0; + } else if (front < rear) { + return rear - front; + } else { + return rear + DEFAULT_SIZE -front; + } + } + + public void enQueue(E data) { + if (isFull()) { + throw new RuntimeException("queue is full"); + } + elementData[rear] = data; + if (rear == DEFAULT_SIZE ) { + rear = 0; + } else { + rear++; + } + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("queue is empty"); + } + E a = (E) elementData[front]; + elementData[front] = null; + if (front == DEFAULT_SIZE ) { + front = 0; + } else { + front++; + } + return a; + } + + public boolean isFull() { + return !isEmpty() && front==rear; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Josephus.java b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..cea71edd88 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,33 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +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){ + Queue queue = new Queue(); + Queue q = new Queue(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + List list = new ArrayList(); + int count = 1; + while(queue.size()>0) { + if (count%m==0) { + list.add((Integer) queue.deQueue()); + } else { + queue.enQueue(queue.deQueue()); + } + count ++; + } + return list; + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/queue/JosephusTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7f0f2a9078 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Queue.java b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..1430d84f7c --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group05/1094051862/mini-jvm/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..ad467b9c02 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,55 @@ +package com.coding.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() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size()+stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("queue is empty"); + } + while(stack2.isEmpty()) { + while(!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + return stack2.pop(); + } + + + + } + diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/QuickMinStack.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..e93820f486 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,38 @@ +package com.coding.basic.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + Stack s = new Stack(); + Stack m = new Stack(); + public void push(int data){ + s.push(data); + if(m.isEmpty()) { + m.push(data); + } + else if (data <= (int)m.peek()) { + m.push(data); + } + } + public int pop(){ + if (m.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + int x = (int) m.pop(); + if (x==(int)m.peek()) { + m.pop(); + } + return x; + } + public int findMin(){ + if (m.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + return (int) m.peek(); + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtil.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtil.java index cdb09886fa..a5e4f7623d 100644 --- a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtil.java +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtil.java @@ -1,5 +1,4 @@ package com.coding.basic.stack; - public class StackUtil { @@ -7,7 +6,7 @@ public class StackUtil { * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 */ - public static void reverse(Stack s) { + public static void reverseV1(Stack s) { if (s == null || s.size() == 0) { return; } @@ -24,6 +23,38 @@ private static void reverseTo(Stack s, Stack s1) { s1.push(s.pop()); } } + /** + * 递归实现 + * @param s + */ + public static void reverse(Stack s) { + if (s == null || s.size() == 0) { + return; + } + + Stack temp = new Stack(); + while(!s.isEmpty()){ + temp.push(s.pop()); + } + + while (!temp.isEmpty()) { + Object pop = temp.pop(); + addToBottom(s,pop); + } + + } + + private static void addToBottom(Stack s, Object o) { + + if (s.isEmpty()) { + s.push(o); + } else { + Object pop = s.pop(); + addToBottom(s, o); + s.push(pop); + } + + } /** * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackWithTwoQueues.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..6b4fafaf6a --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,31 @@ +package com.coding.basic.stack; + +import com.coding.basic.queue.Queue; + +public class StackWithTwoQueues { + + private Queue q1 = new Queue(); + private Queue q2 = new Queue(); + + public void push(int data) { + q1.enQueue(data); + } + + public boolean isEmpty() { + return q1.isEmpty() && q2.isEmpty(); + } + + public int pop() { + if (isEmpty()) { + throw new RuntimeException("stack is empty"); + } + if (q2.isEmpty()) { + while(!q1.isEmpty()) { + q2.enQueue(q1.deQueue()); + } + } + return (int) q2.deQueue(); + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/TwoStackInOneArray.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..6ea653e7f3 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,109 @@ +package com.coding.basic.stack; + +import java.util.Arrays; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + + private int capacity = 10; + Object[] data = new Object[capacity]; + + private int DEFAULT_DILATATION = capacity/2; + + private int index1 = -1; + private int index2 = capacity; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if(isFull()) { + dilatation(); + } + data[index1++] = o; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if (stack1IsEmppty()) { + throw new RuntimeException("stack1 is empty"); + } + Object o = data[index1]; + data[index1--] = null; + return o; + } + public boolean stack1IsEmppty() { + return index1==-1; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if (stack1IsEmppty()) { + throw new RuntimeException("stack1 is empty"); + } + return data[index1]; + } + /** + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if(isFull()) { + dilatation(); + } + data[--index2] = o; + + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if (stack2IsEmpty()) { + throw new RuntimeException("stack2 is empty"); + } + Object o = data[index2]; + data[index2++] = null; + return o; + } + public boolean stack2IsEmpty() { + return index2==capacity; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if (stack2IsEmpty()) { + throw new RuntimeException("stack2 is empty"); + } + return data[index2]; + } + + public boolean isFull() { + return (index1+1) == index2; + } + private void dilatation() { + int newcapacity = DEFAULT_DILATATION + capacity; + int newindex2 = newcapacity; + Object[] temp = Arrays.copyOfRange(data, 0, index1); + temp = Arrays.copyOf(temp, newcapacity); + + for (int i = capacity-1; i >= index2; i-- ) { + temp[--newindex2] = data[i]; + } + index2 = newindex2; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExpr.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExpr.java index dc51c6adf3..453120c9c3 100644 --- a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExpr.java +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExpr.java @@ -1,9 +1,7 @@ package com.coding.basic.stack.expr; import java.util.List; - -import com.coding.basic.stack.Stack; -import com.coding.basic.stack.StackUtil; +import java.util.Stack; public class InfixExpr { String expr = null; @@ -25,31 +23,30 @@ public float evaluate() { if (opStack.isEmpty()) { opStack.push(t); } else { - Token topOperator = (Token) opStack.peek(); - if (t.comparePriority(topOperator) >= 0) { - opStack.push(t); - } else { - Float f1 = (Float) numStack.pop(); - Float f2 = (Float) numStack.pop(); - numStack.push(calculate(topOperator.getValue(), f2, f1)); - opStack.pop(); - opStack.push(t); + while(!opStack.isEmpty() + && !t.hasHigherPriority(opStack.peek())) { + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1, f2); + + numStack.push(result); } + opStack.push(t); + } - } else if (t.isDigit()) { - numStack.push(Float.valueOf(t.getValue())); + } + if (t.isDigit()) { + numStack.push(new Float(t.getIntValue())); } } - /*StackUtil.reverse(numStack); - StackUtil.reverse(opStack);*/ while (!opStack.isEmpty()) { - Float f1 = (Float) numStack.pop(); - Float f2 = (Float) numStack.pop(); - Token opr = (Token) opStack.pop(); + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + Token opr = opStack.pop(); numStack.push(calculate(opr.getValue(), f2, f1)); } - return (Float) numStack.pop(); - //return 0.0f; + return numStack.pop(); } private Float calculate(String op, Float f1, Float f2) { @@ -68,7 +65,7 @@ private Float calculate(String op, Float f1, Float f2) { System.out.println("-"); return f1 - f2; } - return 0.0f; + throw new RuntimeException(op + " is not supported"); } } diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExprTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExprTest.java index a6c3d24012..92d130cddd 100644 --- a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExprTest.java +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -44,11 +44,5 @@ public void testEvaluate() { } } - @Test - public void test0001() { - InfixExpr expr = new InfixExpr("2+3*4+5"); - String s = "23+3*4+5"; - new TokenParser().parse(s); - } } diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..efb6daf9b3 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,46 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static Token[] convert(String expr) { + TokenParser parser = new TokenParser(); + List infix = parser.parse(expr); + + Stack postfix = new Stack(); + Stack op = new Stack(); + for (Token token : infix) { + if (token.isDigit()) { + postfix.push(token); + } /*else if (token.getValue().equals("(")) { + op.push(token); + } else if (token.getValue().equals(")")) { + while (!op.isEmpty() && !op.peek().getValue().equals("(")) { + postfix.push(op.pop()); + } + op.pop(); + }*/ else if (token.isOperator()){ + if (op.isEmpty()) { + op.push(token); + } /*else if (op.peek().getValue().equals("(")) { + op.push(token); + } */else if (token.hasHigherPriority(op.peek())) { + op.push(token); + } else { + while (!op.isEmpty()/* &&! op.peek().getValue().equals("(")*/ && !token.hasHigherPriority(op.peek())) { + postfix.push(op.pop()); + } + op.push(token); + } + } + } + while (!op.isEmpty()) { + postfix.push(op.pop()); + } + Token[] result = new Token[postfix.size()]; + return postfix.toArray(result); + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExpr.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..fd8afaa24d --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +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 opStack = new Stack(); + Stack numStack = new Stack(); + + Stack exprs = new Stack(); + + for(int i = tokens.size()-1; i >= 0; i--) { + exprs.push(tokens.get(i)); + } + + while(!exprs.isEmpty()) { + Token token = exprs.pop(); + if (token.isDigit()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(token.toString(), f2, f1)); + } + } + + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..54ad44afa7 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,47 @@ +package com.coding.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+(8-2*3)*3+10/2 + PostfixExpr expr = new PostfixExpr("9 8 2 3*-3*+ 10 2/+"); + Assert.assertEquals(20, expr.evaluate(),0.0f); + } + + { + //10-2*3+50*5 + PostfixExpr expr = new PostfixExpr("10 2 3 * - 50 +"); + Assert.assertEquals(54, expr.evaluate(),0.0f); + } + } + @Test + public void testInfixToPostfix() { + PostfixExpr expr = new PostfixExpr("9 8 2 3*-3*+ 10 2/+"); + Token[] convert = InfixToPostfix.convert("10-2*3+50*5"); + System.out.println(convert); + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExpr.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..223441200a --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,59 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +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); + + Stack opStack = new Stack(); + Stack numStack = new Stack(); + + Stack exprs = new Stack(); + for(Token token : tokens) { + exprs.push(token); + } + + while(!exprs.isEmpty()) { + Token token = exprs.pop(); + if (token.isDigit()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + } + + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + System.out.println(f1 + "=====" +f2); + switch (op) { + case "*": + System.out.println(" * "); + return f1 * f2; + case "/": + System.out.println("/"); + return f1 / f2; + case "+": + System.out.println("+"); + return f1 + f2; + case "-": + System.out.println("-"); + return f1 - f2; + } + throw new RuntimeException(op + " is not supported"); + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..b8ac42cee5 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,49 @@ +package com.coding.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); + System.out.println("================1"); + } + { + // 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); + System.out.println("================2"); + } + { + //(3+4)*5-6 + PrefixExpr expr = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29, expr.evaluate(),0.001f); + System.out.println("================3"); + } + { + //1+((2+3)*4)-5 + PrefixExpr expr = new PrefixExpr("- + 1 * + 2 3 4 5"); + Assert.assertEquals(16, expr.evaluate(),0.001f); + System.out.println("================4"); + } + + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java index b8abf39546..5afe37fe7d 100644 --- a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java @@ -1,42 +1,59 @@ package com.coding.basic.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); + } public static final int OPRATOR = 0; public static final int NUMBER = 1; - private int signal; - private String value; + int type; + String value; - public Token(int signal, String digit) { - this.signal = signal; - this.value = digit; + public Token(int type, String value) { + this.type = type; + this.value = value; } public boolean isOperator() { - return this.signal == Token.OPRATOR; + return this.type == Token.OPRATOR; } public boolean isDigit() { - return this.signal == Token.NUMBER; + return this.type == Token.NUMBER; } - public int getSignal() { - return signal; + public int getType() { + return type; } - public void setSignal(int signal) { - this.signal = signal; + public void setType(int type) { + this.type = type; } public String getValue() { return value; } - public void setValue(String value) { - this.value = value; + public String toString() { + return value; } - + + public int getIntValue() { + return Integer.valueOf(value).intValue(); + } + public int comparePriority(Token topOperator) { int topOptrPriority = 0; int optPriority = 0; @@ -57,5 +74,11 @@ public int comparePriority(Token topOperator) { return optPriority - topOptrPriority; } + 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; + } } diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/TokenParser.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/TokenParser.java index 447894d7f4..4073ebe6df 100644 --- a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/TokenParser.java +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/TokenParser.java @@ -23,30 +23,33 @@ public List parse(String expr) { 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++; } - System.out.println(c); } return tokens; } - private int indexOfNextOperator(int nowIndex, String expr) { - for (int i = nowIndex; i < expr.length(); i++) { - char c = expr.charAt(i); - if (charIsOperator(c)) { - return i; + private int indexOfNextOperator(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; } } - return expr.length();//如果后面没有操作符,返回字符串长度,用于截取数字 + return i; } private boolean charIsDigit(char c) { + //return Character.isDigit(c); return c>='0' && c<='9'; } private boolean charIsOperator(char c) { - - return c=='+' || c=='-' || c=='*' || c=='/'; + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); } } diff --git a/group05/578505552/dataStruct/src/com/coderising/download/DownloadThread.java b/group05/578505552/dataStruct/src/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..0e3e0d8a40 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/DownloadThread.java @@ -0,0 +1,47 @@ +package com.coderising.download; + +import com.coderising.download.api.DownloadListener; +import com.coderising.download.api.Connection; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + File targetFile; + DownloadListener listener; + + public DownloadThread(Connection conn, int startPos, int endPos, File targetFile, DownloadListener listener){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.targetFile = targetFile; + this.listener = listener; + } + public void run(){ + try { + System.out.println("线程" + this.getName() + "正在下载" + startPos + "--" + endPos + "的数据"); + + byte[] content = conn.read(startPos, endPos); + RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "rw"); + randomAccessFile.seek(startPos); + randomAccessFile.write(content, 0, endPos - startPos + 1); + randomAccessFile.close(); + + System.out.println("线程" + this.getName() + "完成" + startPos + "--" + endPos + "数据的下载"); + + if (FileDownloader.isDownLoadFinished()){ + listener.notifyFinished(); + System.out.println(">>>>>>>>>>>>>>线程" + this.getName() + "完成了最终的下载"); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + conn.close(); + } + } +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/DownloadThreadTest.java b/group05/578505552/dataStruct/src/com/coderising/download/DownloadThreadTest.java new file mode 100644 index 0000000000..4c3116a2c3 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/DownloadThreadTest.java @@ -0,0 +1,46 @@ +package com.coderising.download; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; + +/** + * Created by songbao.yang on 2017/3/11. + */ +public class DownloadThreadTest { + + private DownloadThread downloadThread; + private final String url = "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=9bb90992550fd9f9bf17536f152cd42b/9a504fc2d5628535959cf4cf94ef76c6a6ef63db.jpg"; + private final String path = "D:"; + DownloadListener listener; + + @Before + public void setUp() throws Exception { + String threadName = "DownloadThreadTest"; + ConnectionManagerImpl connectionManager = new ConnectionManagerImpl(); + Connection connection = connectionManager.open(url); + File file = new File(path + File.separator + "meinv.jpg"); + int contentLength = connection.getContentLength(); + System.out.println(contentLength); + + Connection conn = connectionManager.open(url); + downloadThread = new DownloadThread(conn, 0, contentLength, file, listener); + downloadThread.setName(threadName); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void run() throws Exception { + downloadThread.run(); + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coderising/download/FileDownloader.java b/group05/578505552/dataStruct/src/com/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..47c8940809 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/FileDownloader.java @@ -0,0 +1,66 @@ +package com.coderising.download; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.api.ConnectionException; + +import java.io.File; + +public class FileDownloader { + + String url; + DownloadListener listener; + ConnectionManager cm; + public static final int threadCount = 5; + private static int threadFinished; + + public FileDownloader(String _url) { + this.url = _url; + } + + public void execute(){ + try { + Connection conn = cm.open(this.url); + int length = conn.getContentLength(); + + File targetFile = new File("D:" + File.separator + getFileName()); + System.out.println("总长度:" + length); + + int temp = length / threadCount; + for (int i = 0; i < threadCount; i++) { + int startPos = i * temp; + int endPos = startPos + temp - 1; + if (i == threadCount - 1){ + endPos = length; + } + String threadName = "DownloadThread" + String.valueOf(i); + Connection connection = cm.open(url); + DownloadThread downloadThread = new DownloadThread(connection, startPos, endPos, targetFile, listener); + downloadThread.setName(threadName); + downloadThread.start(); + } + } catch (ConnectionException e) { + e.printStackTrace(); + } finally{ + + } + } + + public String getFileName(){ + return "meinv.jpg"; + } + + public synchronized static boolean isDownLoadFinished(){ + threadFinished++; + return threadFinished == threadCount; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/FileDownloaderTest.java b/group05/578505552/dataStruct/src/com/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..f2eaeed26e --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/FileDownloaderTest.java @@ -0,0 +1,49 @@ +package com.coderising.download; + +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import com.coderising.download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class FileDownloaderTest { + boolean downloadFinished = false; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=9bb90992550fd9f9bf17536f152cd42b/9a504fc2d5628535959cf4cf94ef76c6a6ef63db.jpg"; + + FileDownloader downloader = new FileDownloader(url); + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + downloader.setListener(new DownloadListener() { + public void notifyFinished() { + downloadFinished = true; + } + }); + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + } + +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/api/Connection.java b/group05/578505552/dataStruct/src/com/coderising/download/api/Connection.java new file mode 100644 index 0000000000..494c713b27 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionException.java b/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..5954d22409 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,20 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception { + + public ConnectionException() { + } + + public ConnectionException(String message) { + super(message); + } + + public ConnectionException(String message, Throwable cause) { + super(message, cause); + } + + public ConnectionException(Throwable cause) { + super(cause); + } + +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionManager.java b/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..ce045393b1 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/api/DownloadListener.java b/group05/578505552/dataStruct/src/com/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..bf9807b307 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImpl.java b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..0561318d7a --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,49 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +public class ConnectionImpl implements Connection{ + + private HttpURLConnection conn; + + public ConnectionImpl(HttpURLConnection urlConnection) { + this.conn = urlConnection; + } + + public byte[] read(int startPos, int endPos) throws IOException { + conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + if (conn.getResponseCode() == 206){ + InputStream inputStream = conn.getInputStream(); + byte[] temp = new byte[endPos - startPos + 1]; + while ((inputStream.read(temp)) != -1){ + + } + return temp; + } + return new byte[0]; + } + + public int getContentLength() { + try { + if (conn.getResponseCode() == 200){ + return conn.getContentLength(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + this.close(); + } + return 0; + } + + public void close() { + if (conn != null){ + conn.disconnect(); + conn = null; + } + } +} diff --git a/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImplTest.java b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImplTest.java new file mode 100644 index 0000000000..36d2205096 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionImplTest.java @@ -0,0 +1,44 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by songbao.yang on 2017/3/11. + */ +public class ConnectionImplTest { + + private Connection connection; + private final String URL = "https://ss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/image/h%3D200/sign=8e07ecabb7fb4316051f7d7a10a54642/5882b2b7d0a20cf482c772bf73094b36acaf997f.jpg"; + + @Before + public void setUp() throws Exception { + ConnectionManagerImpl connectionManager = new ConnectionManagerImpl(); + this.connection = connectionManager.open(URL); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void read() throws Exception { + byte[] read = connection.read(0, 100); + System.out.println(read); + } + + @Test + public void getContentLength() throws Exception { + int contentLength = connection.getContentLength(); + System.out.println(contentLength); + } + + @Test + public void close() throws Exception { + + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..3ea9a95517 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,25 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; + +import java.net.HttpURLConnection; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + public Connection open(String url) throws ConnectionException { + + try { + URL urlObject = new URL(url); + HttpURLConnection urlConnection = (HttpURLConnection)urlObject.openConnection(); + urlConnection.setRequestMethod("GET"); + urlConnection.setReadTimeout(5000); + return new ConnectionImpl(urlConnection); + } catch (java.io.IOException e) { + throw new ConnectionException("连接失败"); + } + } + +} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/Action.java similarity index 93% rename from group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java rename to group05/578505552/dataStruct/src/com/coderising/litestruts/Action.java index 1c9ad259ad..9248c3eac4 100644 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/Action.java @@ -1,4 +1,4 @@ -package dataStruct.com.coderising.litestruts; +package com.coderising.litestruts; import java.util.Map; diff --git a/group05/578505552/dataStruct/src/com/coderising/litestruts/Configuration.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/Configuration.java new file mode 100644 index 0000000000..90d8a0c6a1 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/Configuration.java @@ -0,0 +1,7 @@ +package com.coderising.litestruts; + +/** + * Created by songbao.yang on 2017/3/10. + */ +public class Configuration { +} diff --git a/group05/578505552/dataStruct/src/com/coderising/litestruts/LoginAction.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/LoginAction.java new file mode 100644 index 0000000000..0d1956992b --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/LoginAction.java @@ -0,0 +1,38 @@ +package com.coderising.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/ReflectUtils.java similarity index 81% rename from group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java rename to group05/578505552/dataStruct/src/com/coderising/litestruts/ReflectUtils.java index cb35e59963..c11c5632f3 100644 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/ReflectUtils.java @@ -1,4 +1,4 @@ -package dataStruct.com.coderising.litestruts; +package com.coderising.litestruts; import java.lang.reflect.Method; diff --git a/group05/578505552/dataStruct/src/com/coderising/litestruts/Struts.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/Struts.java new file mode 100644 index 0000000000..1bfbefbbe1 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/Struts.java @@ -0,0 +1,131 @@ +package com.coderising.litestruts; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class Struts { + + public static View runAction(String actionName, Map parameters) { + +// 0. 读取配置文件struts.xml + Action action = matchAction(parseXml("/com/coderising/litestruts/struts.xml"), actionName); + try { + +// 1. 根据actionName找到相对应的class, 通过反射实例化(创建对象), +// 根据parameters中的数据,调用对象的setter方法 + Class clazz = Class.forName(action.getClassName()); + Object instance = clazz.newInstance(); + for (String key : parameters.keySet()){ + try { + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(key, clazz); + Method setMethod = propertyDescriptor.getWriteMethod(); + setMethod.invoke(instance, parameters.get(key)); + } catch (IntrospectionException e) { + e.printStackTrace(); + } + } + +// 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + Method exectueMethod = null; + String result = null; + try { + exectueMethod = clazz.getMethod("execute"); + result = (String)exectueMethod.invoke(instance); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + +// 3. 通过反射找到对象的所有getter方法(例如 getMessage), +// 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , +// 放到View对象的parameters + Map hashMap = new HashMap(); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields){ + String name = field.getName(); + try { + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, clazz); + Method getMethod = propertyDescriptor.getReadMethod(); + Object res = getMethod.invoke(instance); + hashMap.put(name, res); + } catch (IntrospectionException e) { + e.printStackTrace(); + } + } + +// 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, +// 放到View对象的jsp字段中。 + View view = new View(); + view.setJsp((String)action.getResults().get(result)); + view.setParameters(hashMap); + return view; + + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + + return null; + } + + private static Element parseXml(String resourcePath){ + + InputStream resourceAsStream = Struts.class.getResourceAsStream(resourcePath); + SAXReader saxReader = new SAXReader(); + try { + Document document = saxReader.read(resourceAsStream); + Element rootElement = document.getRootElement(); + return rootElement; + } catch (DocumentException e) { + e.printStackTrace(); + } + + throw new RuntimeException("fail to parse xml"); + } + + private static Action matchAction(Element rootElement, String actionName){ + + List actions = rootElement.elements("action"); + Iterator iterator = actions.iterator(); + Action action = new Action(); + while (iterator.hasNext()){ + Element actionElement = (Element) iterator.next(); + String nameAttributeValue = actionElement.attributeValue("name"); + if (actionName.equals(nameAttributeValue)){ + action.setName(nameAttributeValue); + action.setClassName(actionElement.attributeValue("class")); + List results = actionElement.elements("result"); + Map resultMap = new HashMap(); + Iterator it = results.iterator(); + while (it.hasNext()){ + Element resultElement = (Element)it.next(); + resultMap.put(resultElement.attributeValue("name"), (String)resultElement.getData()); + } + action.setResults(resultMap); + } + } + + return action; + } + + + + +} diff --git a/group05/578505552/dataStruct/src/com/coderising/litestruts/StrutsTest.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..972e0e63ca --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,40 @@ +package com.coderising.litestruts; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group05/578505552/dataStruct/src/com/coderising/litestruts/View.java b/group05/578505552/dataStruct/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coderising/litestruts/View.java @@ -0,0 +1,23 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNode.java b/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..3a36db4031 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNode.java @@ -0,0 +1,60 @@ +package com.coding.basic; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public class BinaryTreeNode { + + private Integer data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Integer data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Integer o){ + if (o == null){ + throw new IllegalArgumentException("can not insert null"); + } + + BinaryTreeNode newNode = new BinaryTreeNode(); + newNode.data = o; + newNode.left = null; + newNode.right = null; + + BinaryTreeNode cursor = this; + BinaryTreeNode pre = cursor; + while (cursor != null){ + pre = cursor; + if (o.compareTo(cursor.data) < 0){ + cursor = cursor.left; + } else { + cursor = cursor.right; + } + } + + if (o.compareTo(pre.data) < 0){ + pre.left = newNode; + } else { + pre.right = newNode; + } + return this; + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNodeTest.java b/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..9bdfaa5afe --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/BinaryTreeNodeTest.java @@ -0,0 +1,36 @@ +package com.coding.basic; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by songbao.yang on 2017/2/28. + * + */ +public class BinaryTreeNodeTest { + + private BinaryTreeNode node; + + @Before + public void setUp() throws Exception { + node = new BinaryTreeNode(); + node.setData(100); + node.setLeft(null); + node.setRight(null); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void insert() throws Exception { + + for (int i = 0; i < 100; i++) { + int ele = (int)Math.floor(Math.random() * 200); + node.insert(ele); + } + } +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/Iterator.java b/group05/578505552/dataStruct/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..4ac23f28c0 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/Iterator.java @@ -0,0 +1,11 @@ +package com.coding.basic; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/List.java b/group05/578505552/dataStruct/src/com/coding/basic/List.java new file mode 100644 index 0000000000..aadf216958 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/List.java @@ -0,0 +1,14 @@ +package com.coding.basic; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public interface List { + public void add(T o); + public void add(int index, T o); + public T get(int index); + public T remove(int index); + public int size(); + public Iterator iterator(); +} diff --git a/group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java b/group05/578505552/dataStruct/src/com/coding/basic/ListTest.java similarity index 96% rename from group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java rename to group05/578505552/dataStruct/src/com/coding/basic/ListTest.java index 9196c37f4c..4962248170 100644 --- a/group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java +++ b/group05/578505552/dataStruct/src/com/coding/basic/ListTest.java @@ -1,5 +1,6 @@ -package dataStruct.com.coding.basic; +package com.coding.basic; +import com.coding.basic.linklist.LinkedList; import org.junit.After; import org.junit.Assert; import org.junit.Before; diff --git a/group05/578505552/dataStruct/src/com/coding/basic/Queue.java b/group05/578505552/dataStruct/src/com/coding/basic/Queue.java new file mode 100644 index 0000000000..ac5f506eff --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/Queue.java @@ -0,0 +1,90 @@ +package com.coding.basic; + +import java.util.NoSuchElementException; + +/** + * Created by songbao.yang on 2017/2/22. + * + */ +public class Queue { + + private Object[] elementData; + private int head; //对头的位置 + private int tail; //队尾的位置 + private int size; //队列中元素的个数 + private static final int MIN_INITIAL_CAPACITY = 10; + + public Queue() { + this.elementData = new Object[MIN_INITIAL_CAPACITY]; + this.head = 0; + this.tail = 0; + this.size = 0; + } + + public Queue(int initCapcacity) { + if (initCapcacity < MIN_INITIAL_CAPACITY){ + initCapcacity = MIN_INITIAL_CAPACITY; + } + this.elementData = new Object[initCapcacity]; + this.head = 0; + this.tail = 0; + this.size = 0; + } + + public void enQueue(Object o){ + ensureCapacity(size+1); + if(size != 0){ + tail++; + } + if(tail == elementData.length){ + tail = 0; + } + elementData[tail] = o; + size++; + } + + private void ensureCapacity(int minCapcacity){ + if(minCapcacity <= elementData.length){ + return; + } + + int newCapcacity = elementData.length << 1; + if (newCapcacity < elementData.length){ + newCapcacity = Integer.MAX_VALUE; + } + + Object[] newData = new Object[newCapcacity]; + if(size != 0){ + if(tail >= head){ + System.arraycopy(elementData, head, newData, 0, size); + } else { + System.arraycopy(elementData, head, newData, 0, elementData.length - head); + System.arraycopy(elementData, 0, newData, elementData.length - head, tail + 1); + } + elementData = newData; + head = 0; + tail = this.size - 1; + } + } + + public Object deQueue(){ + if (isEmpty()){ + throw new NoSuchElementException("empty queue"); + } + Object ele = elementData[head]; + size--; + head++; + if(head == elementData.length){ + head = 0; + } + return ele; + } + + public boolean isEmpty(){ + return size == 0; + } + + public int size(){ + return size; + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/QueueTest.java b/group05/578505552/dataStruct/src/com/coding/basic/QueueTest.java new file mode 100644 index 0000000000..9fe34fbd0e --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/QueueTest.java @@ -0,0 +1,75 @@ +package com.coding.basic; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by songbao.yang on 2017/2/24. + */ +public class QueueTest { + + private static final int SIZE = 2000; + private Queue queue; + + @Before + public void setUp() throws Exception { + queue = new Queue(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void enQueue() throws Exception { + for (int i = 0; i < SIZE; i++) { + queue.enQueue(i); + assertEquals(i+1, queue.size()); + } + } + + @Test + public void deQueue1() throws Exception { + enQueue(); + + int i = 0; + int startSize = queue.size(); + while (!queue.isEmpty()) { + assertEquals(startSize - i, queue.size()); + Object o = queue.deQueue(); + assertEquals(SIZE - i - 1, queue.size()); + Assert.assertEquals(i, o); + i++; + } + } + + @Test + public void deQueue2() throws Exception { + enQueue(); + int startSize = queue.size(); + + for (int i = 0; i < startSize; i++) { + queue.deQueue(); + assertEquals(startSize - 1, queue.size()); + queue.enQueue(i+1000); + assertEquals(startSize, queue.size()); + } + + } + + @Test + public void isEmpty() throws Exception { + + } + + @Test + public void size() throws Exception { + + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayList.java b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..e7f58cbced --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,106 @@ +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +import java.util.NoSuchElementException; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public class ArrayList implements List { + + private int size = 0; + private Object[] elementData; + private static final int MIN_CAPACITY = 10; + + public ArrayList(int size) { + if (size < 0){ + throw new IllegalArgumentException("illega size: " + size); + } + this.elementData = new Object[size]; + } + + public ArrayList() { + this.elementData = new Object[0]; + } + + public void add(T o){ + ensureCapacity(size + 1); + elementData[size++] = o; + } + + private void ensureCapacity(int minCapacity){ + if (minCapacity < 0 ){ + throw new OutOfMemoryError(); + } + + int newCapcity = size; + if(minCapacity < MIN_CAPACITY){ + newCapcity = MIN_CAPACITY; + } else if(minCapacity > elementData.length){ + int tmp = elementData.length << 1; + newCapcity = tmp > elementData.length ? tmp : Integer.MAX_VALUE; + } + + newCapcity = minCapacity; + Object[] newData = new Object[newCapcity]; + System.arraycopy(elementData, 0, newData, 0, size); + elementData = newData; + } + + public void add(int index, T o){ + indexCheck(index); + ensureCapacity(size+1); + System.arraycopy(elementData, index, elementData, index+1, size-index); + elementData[index] = o; + size++; + } + + public T get(int index){ + indexCheck(index); + return (T) elementData[index]; + } + + private void indexCheck(int index){ + if(index < 0){ + throw new IllegalArgumentException("illegal index: " + index); + } + if(index >= size){ + throw new IndexOutOfBoundsException(); + } + } + + public T remove(int index){ + indexCheck(index); + Object rm = elementData[index]; + System.arraycopy(elementData, index+1, elementData, index, size-index-1); + size--; + return (T) rm; + } + + public int size(){ + return size; + } + + public Iterator iterator(){ + return new Itr(); + } + + //静态内部类的访问权限不同有何区别?? + private class Itr implements Iterator { + private int cursor = 0; + + public boolean hasNext() { + return cursor != size; + } + + public Object next() { + if (hasNext()){ + return elementData[cursor++]; + } + throw new NoSuchElementException(); + } + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtil.java b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..3d70dc8f40 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,263 @@ +package com.coding.basic.array; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin){ + + if(origin == null){ + return; + } + int length = origin.length; + int i = 0; + int j = length - 1; + while (i < j){ + int tmp = origin[i]; + origin[i] = origin[j]; + origin[j] = tmp; + i++; + j--; + } + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray){ + int length = oldArray.length; + int[] newArray = new int[length]; + int j = 0; + for (int i = 0; i < length; i++) { + if (oldArray[i] != 0){ + newArray[j++] = oldArray[i]; + } + } + int[] res = new int[j]; + System.arraycopy(newArray, 0, res, 0, j); + return res; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + + if(array1 == null && array2 == null){ + return new int[0]; + } + + if (array1 == null){ + return array2; + } + + if (array2 == null){ + return array1; + } + + int length1 = array1.length; + int length2 = array2.length; + int i = 0; + int j = 0; + + int[] res = new int[length1 + length2]; + int k = 0; + while (i < length1 || j < length2){ + int next = Integer.MIN_VALUE; + if (i < length1 && j < length2){ + if (array1[i] == array2[j]){ + next = array1[i]; + i++; + j++; + } else if (array1[i] < array2[j]){ + next = array1[i++]; + } else { + next = array2[j++]; + } + } else if (i < length1){ + next = array1[i++]; + } else { + next = array2[j++]; + } + + if (k == 0){ + res[k++] = next; + } else if (next > res[k-1]){ + res[k++] = next; + } + } + + int[] merged = new int[k]; + System.arraycopy(res, 0, merged, 0, k); + return merged; + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + if (size < 0){ + throw new IllegalArgumentException("illegal size"); + } + int newLength = oldArray.length + size; + int[] newArray = new int[newLength]; + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); + return newArray; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + + if (max <= 1){ + return new int[0]; + } + + int[] res = new int[max]; + int i = 1; + int j = 1; + int k = 0; + res[k++] = 1; + res[k++] = 1; + + int tmp = i + j; + while (tmp < max){ + res[k++] = tmp; + i = j; + j = tmp; + tmp = i + j; + } + + int[] result = new int[k]; + System.arraycopy(res, 0, result, 0, k); + return result; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + if (max < 3){ + return new int[0]; + } + int[] res = new int[max]; + int k = 0; + for (int i = 2; i < max; i++) { + if (isPrime(i)){ + res[k++] = i; + } + } + int[] result = new int[k]; + System.arraycopy(res, 0, result, 0, k); + return result; + } + + private boolean isPrime(int num){ + + if (num < 1){ + return false; + } + for (int i = 2; i <= num / 2; i++) { + if (num % i == 0){ + return false; + } + + } + return true; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + + if (max < 0){ + return new int[0]; + } + int[] res = new int[max]; + int k = 0; + for (int i = 0; i < max; i++) { + if (isPerfectNumbers(i)){ + res[k++] = i; + } + } + int[] result = new int[k]; + System.arraycopy(res, 0, result, 0, k); + return result; + } + + private boolean isPerfectNumbers(int num){ + + return num == getFactorSum(num); + } + + private int getFactorSum(int num){ + if (num == 0 || num == 1){ + return -1; + } + int sum = 0; + for (int i = 1; i <= num / 2; i++) { + if (num % i == 0){ + sum += i; + } + } + return sum; + } + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param separator + * @return + */ + public String join(int[] array, String separator){ + + if (array == null || array.length <= 0){ + return ""; + } + + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < array.length - 1; i++) { + stringBuffer.append(String.valueOf(array[i])).append(separator); + } + stringBuffer.append(String.valueOf(array[array.length-1])); + return stringBuffer.toString(); + } + + public static void main(String[] args) { + ArrayUtil arrayUtil = new ArrayUtil(); + System.out.println("-------------------------"); + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtilTest.java b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtilTest.java new file mode 100644 index 0000000000..b1bdd59cbd --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/array/ArrayUtilTest.java @@ -0,0 +1,209 @@ +package com.coding.basic.array; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +/** + * Created by songbao.yang on 2017/3/2. + * + */ +public class ArrayUtilTest { + + private ArrayUtil arrayUtil; + + @Before + public void setUp() throws Exception { + arrayUtil = new ArrayUtil(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void reverseArray() throws Exception { + + int[][] actualAndExpected = { + {}, {}, {0}, {0}, + {1,2,3,4,5,6}, {6,5,4,3,2,1}, + {7,9,30,3,4}, {4,3,30,9,7} + }; + + for (int i = 0; i < actualAndExpected.length; i += 2) { + int[] acutal = actualAndExpected[i]; + int[] expected = actualAndExpected[i+1]; + arrayUtil.reverseArray(acutal); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, acutal)); + } + } + + @Test + public void removeZero() throws Exception { + int[][] actualAndExpected = { + {}, {}, {0}, {}, + {1,0,3,0,5,0}, {1,3,5}, + {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}, {1,3,4,5,6,6,5,4,7,6,7,5} + }; + + for (int i = 0; i < actualAndExpected.length; i += 2) { + int[] acutal = actualAndExpected[i]; + int[] expected = actualAndExpected[i+1]; + int[] ints = arrayUtil.removeZero(acutal); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, ints)); + } + } + + @Test + public void merge() throws Exception { + int[][] actualAndExpected = { + {}, {}, {}, + {}, {0}, {0}, + {3,5,7,8}, {4,5,6,7},{3,4,5,6,7,8}, + {1,2,3,4,5,}, {6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} + }; + + for (int i = 0; i < actualAndExpected.length; i += 3) { + int[] array1 = actualAndExpected[i]; + int[] array2 = actualAndExpected[i+1]; + int[] expected = actualAndExpected[i+2]; + int[] result = arrayUtil.merge(array1, array2); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, result)); + } + + } + + @Test + public void grow() throws Exception { + int[][] actualAndExpected = { + {}, {}, + {1}, {}, + {5}, {0,0,0,0,0}, + {0},{2,3,6}, + {3}, {2,3,6,0,0,0} + }; + + for (int i = 0; i < actualAndExpected.length; i += 3) { + int[] oldArray = actualAndExpected[i]; + int size = actualAndExpected[i+1][0]; + int[] expected = actualAndExpected[i+2]; + int[] newArray = arrayUtil.grow(oldArray, size); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, newArray)); + } + } + + @Test + public void fibonacci() throws Exception { + int[][] actualAndExpected = { + {0}, {}, + {1}, {}, + {2}, {1,1}, + {3}, {1,1,2}, + {4}, {1,1,2,3}, + {15}, {1,1,2,3,5,8,13}, + }; + + for (int i = 0; i < actualAndExpected.length; i += 2) { + int max = actualAndExpected[i][0]; + int[] expected = actualAndExpected[i+1]; + int[] actual = arrayUtil.fibonacci(max); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); + } + } + + @Test + public void getPrimes() throws Exception { + int[][] actualAndExpected = { + {-1}, {}, + {0}, {}, + {1}, {}, + {2}, {}, + {3}, {2}, + {4}, {2,3}, + {23}, {2,3,5,7,11,13,17,19}, + }; + + for (int i = 0; i < actualAndExpected.length; i += 2) { + int max = actualAndExpected[i][0]; + int[] expected = actualAndExpected[i+1]; + int[] actual = arrayUtil.getPrimes(max); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); + } + } + + @Test + public void getPerfectNumbers() throws Exception { + int[][] actualAndExpected = { + {-1}, {}, + {0}, {}, + {1}, {}, + {2}, {}, + {7}, {6}, + {30}, {6,28}, + {500}, {6,28,496}, + {10000}, {6,28,496,8128} + }; + + for (int i = 0; i < actualAndExpected.length; i += 2) { + int max = actualAndExpected[i][0]; + int[] expected = actualAndExpected[i+1]; + int[] actual = arrayUtil.getPerfectNumbers(max); + Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); + } + } + + @Test + public void join() throws Exception { + int[][] arrays = { + {}, + {3,8,9}, + {1}, + {0,0,0,0,0}, + {1,2,3,4,5} + }; + String[] separators = {"", "-", "+", "*", "00"}; + String[] expecteds = { + "", + "3-8-9", + "1", + "0*0*0*0*0", + "1002003004005" + }; + for (int i = 0; i < arrays.length; i++) { + int[] array = arrays[i]; + String separator = separators[i]; + String expected = expecteds[i]; + String actual = arrayUtil.join(array, separator); + Assert.assertTrue("wrong index: " + String.valueOf(i), expected.equals(actual)); + } + } + + private boolean isArrayEqual(int[] expected, int[] actual){ + if (expected.length != actual.length){ + System.out.println("expected.length != actual.length"); + System.out.println("expected: " + Arrays.toString(expected)); + System.out.println("actual: " + Arrays.toString(actual)); + return false; + } + + for (int i = 0; i < expected.length; i++) { + if (expected[i] != actual[i]){ + System.out.println("expected[i] != actual[i]"); + System.out.println("expected: " + Arrays.toString(expected)); + System.out.println("actual: " + Arrays.toString(actual)); + return false; + } + } + + return true; + } + + public static void main(String[] args) { + System.out.println("----------"); + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrame.java b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..f7addeedbb --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,105 @@ +package com.coding.basic.linklist; + +/** + * 用双向链表实现LRU算法 + * @author songbao.yang + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + private int size; + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + this.size = 0; + first = null; + last = null; + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @return + */ + public void access(int pageNum) { + + Node newNode = new Node(); + newNode.pageNum = pageNum; + + //往链表头部加入元素 + if (size == 0){ + first = newNode; + last = newNode; + } else { + newNode.next = first; + if (first == null){ + System.out.println("fuck"); + } + first.prev = newNode; + first = newNode; + } + size++; + + //去重 + Node node = first.next; + while (node != null){ + if (node.pageNum == pageNum){ + node.prev.next = node.next; + + if (node == last){ + last = node.prev; + } else { + node.next.prev = node.prev; + } + + Node tmp = node; + node = node.next; + tmp.next = null; + tmp.prev = null; + size--; + } else { + node = node.next; + } + } + + //调整容量 + if (size > capacity){ + last = last.prev; + last.next.prev = null; + last.next = null; + size--; + } + } + + 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/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..2127d16eea --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + } + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/linklist/LinkedList.java b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..7bca51587d --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/linklist/LinkedList.java @@ -0,0 +1,393 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +import java.util.NoSuchElementException; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public class LinkedList implements List { + + private Node head; + private int elementCount; + + //head作为一个节点,其next的值指向List中真正的第一个节点 + public LinkedList() { + head = new Node(); + head.next = null; + head.data = null; + elementCount = 0; + } + + public void add(T o){ + Node newNode = new Node(); + newNode.data = o; + newNode.next = null; + + Node cursor = head; + while (cursor.next != null){ + cursor = cursor.next; + } + cursor.next = newNode; + elementCount++; + } + + + public void add(int index , T o){ + indexRangeCheck(index); + Node newNode = new Node(); + newNode.data = o; + + Node cursor = head; + for (int i = 0; i < index; i++) { + cursor = cursor.next; //将cursor移动到index-1节点处; + } + + newNode.next = cursor.next; //将新节点指向原index处的节点 + cursor.next = newNode;//将原index-1处的节点指向新节点 + elementCount++; + } + + private void indexRangeCheck(int index){ + if (index < 0 || index >= size()){ + throw new IndexOutOfBoundsException(); + } + } + + public T get(int index){ + indexRangeCheck(index); + Node cursor = head; + for (int i = 0; i < index; i++) { + cursor = cursor.next; + } + return (T) cursor.next.data; + } + + public T remove(int index){ + indexRangeCheck(index); + Node cursor = head; + for (int i = 0; i < index; i++) { + cursor = cursor.next; + } + Node indexNode = cursor.next; + cursor.next = indexNode.next; + elementCount--; + return (T) indexNode; + } + + public int size(){ + return elementCount; + } + + public void addFirst(T o){ + Node node = new Node(); + node.data = o; + node.next = head.next; + head.next = node; + elementCount++; + } + + public void addLast(T o){ + + Node cursor = head; + while (cursor.next != null){ + cursor = cursor.next; + } + Node newNode = new Node(); + newNode.data = o; + newNode.next = null; + cursor.next = newNode; + elementCount++; + } + + public T removeFirst(){ + + if (size() == 0){ + throw new RuntimeException("no element in list"); + } + Node firstNode = head.next; + head.next = head.next.next; + elementCount--; + return (T) firstNode; + } + + public T removeLast(){ + if (size() == 0){ + throw new RuntimeException("no element in list"); + } + + Node cursor = head; + for (int i = 0; i < size() - 1; i++) { + cursor = cursor.next; + } + + Node lastNode = cursor.next; + cursor.next = null; + elementCount--; + + return (T) lastNode; + } + + public Iterator iterator(){ + return new Itr(); + } + + private class Itr implements Iterator { + + private Node itrCursor = head; + + public boolean hasNext() { + + return itrCursor.next != null; + } + + public Object next() { + if (hasNext()){ + return itrCursor.next; + } + throw new NoSuchElementException(); + } + } + + private static class Node{ + T data; + Node next; + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + if (elementCount <= 1){ + return; + } + + Node first = head.next; + Node second = head.next.next; + + first.next = null; + while (second != null){ + Node temp = second.next; + second.next = first; + first = second; + second = temp; + } + head.next = first; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + Node cousor = head.next; + for (int i = 0; i < elementCount / 2; i++) { + Node temp = cousor; + cousor = cousor.next; + temp.data = null; + temp.next = null; + } + head.next = cousor; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + if (i < 0 || length < 0){ + return; + } + if (i > elementCount - 1){ + throw new IndexOutOfBoundsException("index i is too big"); + } + + Node beforei = head; + for (int j = 0; j < i; j++) { + beforei = beforei.next; + } + Node cursor = beforei.next; + for (int j = 0; j < length; j++) { + if (cursor != null){ + Node temp = cursor; + cursor = cursor.next; + temp.data = null; + temp.next = null; + }else { + break; + } + } + beforei.next = cursor; + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + + int[] result = new int[list.size()]; + int i = 0; + int pre = 0; + Node cousor = head.next; + Iterator YIterator = list.iterator(); + while (YIterator.hasNext()){ + int index = (Integer) YIterator.next(); + if (index > elementCount - 1){ + break; + } + moveForwardNIndex(cousor, index - pre); + result[i++] = (Integer) cousor.data; + pre = index; + } + + int[] ints = new int[result.length]; + System.arraycopy(result, 0, ints, 0, result.length); + return ints; + } + + private void moveForwardNIndex(Node index, int n){ + for (int i = 0; i < n; i++) { + if (index == null){ + break; + } + index = index.next; + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + Node pre = head; + Node node = head.next; + while (node != null){ + if (list.contains(node.data)){ + pre.next = node.next; + node = node.next; + } else { + pre = node; + node = node.next; + } + } + } + + public boolean contains(T data){ + + Node cursor = this.head.next; + while (cursor != null){ + if (cursor.data.equals(data)){ + return true; + } + } + return false; + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + if (elementCount <= 1){ + return; + } + Node pre = head.next; + Node node = pre.next; + while (node != null){ + if (node.data.equals(pre.data)){ + pre.next = node.next; + node = node.next; + } else { + pre = node; + node = node.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + //TODO 这个泛型的比较没搞明白, 为什么会出现cast的问题,不应该都是T类型吗 + public void removeRange(T min, T max){ + if (min.compareTo(max) > 0){ + return; + } + if (size() == 0){ + return; + } + Node beforeMin = head; + //泛型化 + while (beforeMin.next != null && beforeMin.next.data.compareTo(min) <= 0){ + beforeMin = beforeMin.next; + } + Node afterMax = beforeMin.next; + while (afterMax != null && afterMax.data.compareTo(max) < 0){ + afterMax = afterMax.next; + } + beforeMin.next = afterMax; + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection(LinkedList list){ + + if (list == null || list.size() == 0 || this.size() == 0){ + return new LinkedList(); + } + + Node cursorA = this.head.next; + Node cursorB = list.head.next; + LinkedList listC = new LinkedList(); + + while (cursorA != null && cursorB != null){ + if (cursorA.data.compareTo(cursorB.data) == 0){ + listC.add((T)cursorA.data); + } else if (cursorA.data.compareTo(cursorB.data) < 0){ + cursorA = cursorA.next; + } else { + cursorB = cursorB.next; + } + } + return listC; + } + + public void addAfter(Node node, T o){ + if (node == null){ + return; + } + Node newNode = new Node(); + newNode.data = o; + addAfter(node, newNode); + } + + public void addAfter(Node node, Node newNode){ + if (node == null || newNode == null){ + return; + } + newNode.next = node.next; + node.next = newNode; + } +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/Stack.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..33b414baaa --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,77 @@ +package com.coding.basic.stack; + + +import java.util.EmptyStackException; + +/** + * Created by songbao.yang on 2017/2/22. + * + */ +public class Stack { + + private Object[] elementData; + private static final int MIN_INITIAL_CAPACITY = 10; + private int cursor; + + public Stack() { + elementData = new Object[MIN_INITIAL_CAPACITY]; + cursor = -1; + } + + public void push(Object o) { + ensureCapacity(size() + 1); + cursor = cursor + 1; + System.out.println(cursor); + elementData[cursor] = o; + } + + private void ensureCapacity(int minCapacity) { + if (minCapacity <= elementData.length) { + return; + } + + int newSize = elementData.length << 1; + if (newSize < elementData.length) { + newSize = Integer.MAX_VALUE; + } + + Object[] newDataArray = new Object[newSize]; + System.arraycopy(elementData, 0, newDataArray, 0, size()); + elementData = newDataArray; + } + + + public Object pop() { + Object ele = peek(); + cursor--; + return ele; + } + + public Object peek() { + if (isEmpty()) { + throw new EmptyStackException(); + } + return elementData[this.cursor]; + } + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return this.cursor + 1; + } + + @Override + public String toString() { + + StringBuffer stringBuffer = new StringBuffer(); + while (!isEmpty()){ + stringBuffer.append(pop()); + if (!isEmpty()){ + stringBuffer.append(','); + } + } + return stringBuffer.toString(); + } +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/StackTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackTest.java new file mode 100644 index 0000000000..92b0a07176 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackTest.java @@ -0,0 +1,76 @@ +package com.coding.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by songbao.yang on 2017/2/24. + * + */ +public class StackTest { + + private Stack stack; + + public static final int SIZE = 100; + + @Before + public void setUp() throws Exception { + stack = new Stack(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void push() throws Exception { + for (int i = 0; i < SIZE; i++) { + stack.push(i); + assertEquals(i+1, stack.size()); + } + System.out.println(); + } + + @Test + public void pop() throws Exception { + push(); + int beginSize = stack.size(); + for (int i = 0; i < beginSize; i++) { + Object ele = stack.pop(); + assertEquals(beginSize-i-1, stack.size()); + Assert.assertEquals(beginSize-i-1, ele); + } + } + + @Test + public void peek() throws Exception { + + } + + @Test + public void isEmpty() throws Exception { + + } + + @Test + public void size() throws Exception { + + } + + @Test + public void testToString(){ + + stack.push(1); + stack.push(2); + stack.push(3); + + System.out.println(stack.toString()); + + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtil.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..dde9770cab --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,94 @@ +package com.coding.basic.stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + + Stack stack = new Stack(); + while (!s.isEmpty()){ + stack.push(s.pop()); + } + s = stack; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + + Stack stack = new Stack(); + while (!s.isEmpty()){ + Object peek = s.peek(); + if (peek.equals(o)){ + s.pop(); + while (!stack.isEmpty()){ + s.push(stack.pop()); + } + } else { + stack.push(s.pop()); + } + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + + Object[] topN = new Object[len]; + Stack stack = new Stack(); + for (int i = 0; i < len; i++){ + if (!s.isEmpty()){ + Object pop = s.pop(); + topN[i] = pop; + stack.push(pop); + } else { + break; + } + } + + while (!stack.isEmpty()){ + s.push(stack.pop()); + } + + return topN; + } + /** + * 字符串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 stack = new Stack(); + + for (int i = 0; i < s.length(); i++) { + + char c = s.charAt(i); + if (c == '{' || c == '[' || c == '('){ + stack.push(c); + } + + if (c == '}' || c == ']' || c == ')'){ + if (stack.isEmpty() || c != (Character) stack.pop()){ + return false; + } + } + } + return true; + } + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtilTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..f6073b6106 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,61 @@ +package com.coding.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * r + * Created by songbao.yang on 2017/4/11. + */ +public class StackUtilTest { + + StackUtil stackUtil; + Stack stack; + + @Before + public void setUp() throws Exception { + stackUtil = new StackUtil(); + stack = new Stack(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void reverse() throws Exception { + + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + + StackUtil.reverse(stack); + + String reverse = stack.toString(); + + Assert.assertEquals("1,2,3,4,5", reverse); + } + + @Test + public void remove() throws Exception { + + } + + @Test + public void getTop() throws Exception { + + } + + @Test + public void isValidPairs() throws Exception { + + } + +} \ No newline at end of file diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExpr.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..4201398137 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,115 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + + if (!check(tokens)){ + throw new RuntimeException("illegal expression"); + } + + Stack operatorStack = new Stack(); + Stack numberStack = new Stack(); + + for (Token token : tokens){ + + if (token.isNumber()){ + numberStack.push(token); + } + + if (token.isOperator()){ + + if (operatorStack.isEmpty() || token.hasHigherPriority(operatorStack.peek())){ + operatorStack.push(token); + + } else { + popOneOperator(operatorStack, numberStack); + + if (operatorStack.isEmpty() || token.hasHigherPriority(operatorStack.peek())){ + operatorStack.push(token); + + } else { + popOneOperator(operatorStack, numberStack); + operatorStack.push(token); + } + } + } + } + + while (!operatorStack.isEmpty()){ + + popOneOperator(operatorStack, numberStack); + } + + return Float.valueOf(numberStack.pop().toString()); + } + + private void popOneOperator(Stack operatorStack, Stack numberStack){ + + Token operator = operatorStack.pop(); + Token num1 = numberStack.pop(); + Token num2 = numberStack.pop(); + float res = evaluateTwo(num2, num1, operator); + numberStack.push(new Token(Token.NUMBER, String.valueOf(res))); + } + + private float evaluateTwo(Token num1, Token num2, Token o){ + + Float s1 = Float.valueOf(num1.toString()); + Float s2 = Float.valueOf(num2.toString()); + + if (o.toString().equals("+")){ + return s1 + s2; + + } else if (o.toString().equals("-")){ + return s1 - s2; + + } else if (o.toString().equals("*")){ + return s1 * s2; + + } else if (o.toString().equals("/")){ + return s1 / s2; + } + + throw new RuntimeException("unsupported operator [" + o.toString() + "]"); + } + + private boolean check(List tokens) { + + if (tokens == null || tokens.isEmpty()){ + return false; + } + + int i = 0; + for (Token token : tokens){ + if (token.isNumber()){ + i++; + if ( i != 1){ + return false; + } + } + + if (token.isOperator()){ + i--; + if ( i != 0){ + return false; + } + } + } + return i == 1; + } + + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExprTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20e34e8852 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..96a2194a67 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,14 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + + return null; + } + + + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExpr.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..3854996ebf --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,15 @@ +package com.coding.basic.stack.expr; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..2f8c48fc70 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,40 @@ +package com.coding.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/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExpr.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..d6d90d32dc --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,15 @@ +package com.coding.basic.stack.expr; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/Token.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..ade4e96c24 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,51 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParser.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..5d655167b6 --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.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/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParserTest.java b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..66402e1f3c --- /dev/null +++ b/group05/578505552/dataStruct/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.coding.basic.stack.expr; + +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/group05/578505552/miniJvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group05/578505552/miniJvm/src/com/coderising/jvm/attr/CodeAttr.java b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..9ab4480643 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,114 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; +import org.w3c.dom.Attr; + + +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 attrNameIndex = iter.nextU2ToInt(); + String name = clzFile.getConstantPool().getUTF8String(attrNameIndex); + + int attrLength = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLength = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLength); + System.out.println("code: " + code); + + ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLength, maxStack, maxLocals, codeLength, code, cmds); + + int exceptionTableLength = iter.nextU2ToInt(); + + if (exceptionTableLength > 0){ + System.out.println(iter.nextUxToHexString(exceptionTableLength)); + //TODO parse exception + System.out.println("just ignore exception!!"); + } + + int subAttrCount = iter.nextU2ToInt(); + for (int i = 0; i < subAttrCount; i++) { + + int subAttrNameIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrNameIndex); + iter.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equals(subAttrName)){ + codeAttr.setLineNumberTable(LineNumberTable.parse(iter)); + + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(subAttrName)){ + codeAttr.setLocalVariableTable(LocalVariableTable.parse(iter)); + + } else if (AttributeInfo.STACK_MAP_TABLE.equals(subAttrName)){ + codeAttr.setStackMapTable(StackMapTable.parse(iter)); + + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + } + + return codeAttr; + } + + + 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 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 attrNameIndex = iter.nextU2ToInt(); + int attrLenght = iter.nextU4ToInt(); + + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLenght); + + int lineNumberTableLenght = iter.nextU2ToInt(); + for (int i = 0; i < lineNumberTableLenght; i++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.nextU2ToInt()); + lineNumberItem.setLineNum(iter.nextU2ToInt()); + } + + return lineNumberTable; + } + + 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/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..9561e904a9 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,49 @@ +package com.coderising.jvm.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/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..435322a1a4 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.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 attrNameIndex = iter.nextU2ToInt(); + int attrLenght = iter.nextU4ToInt(); + + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIndex, attrLenght); + + int localVariableTableLen = iter.nextU2ToInt(); + for (int i = 0; i < localVariableTableLen; i++) { + LocalVariableItem localVariableItem = new LocalVariableItem(); + localVariableItem.setStartPC(iter.nextU2ToInt()); + localVariableItem.setLength(iter.nextU2ToInt()); + localVariableItem.setNameIndex(iter.nextU2ToInt()); + localVariableItem.setDescIndex(iter.nextU2ToInt()); + localVariableItem.setIndex(iter.nextU2ToInt()); + localVariableTable.addLocalVariableItem(localVariableItem); + } + + return localVariableTable; + } + + + 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/group05/578505552/miniJvm/src/com/coderising/jvm/attr/StackMapTable.java b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..0814041fc6 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.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/group05/578505552/miniJvm/src/com/coderising/jvm/clz/AccessFlag.java b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..67e378085f --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.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/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassFile.java b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..9d32f49239 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,100 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.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){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassIndex.java b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..23d3214e90 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + + private int thisClassIndex; + private int 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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..d93515a002 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..533345deb7 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,133 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.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 this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + public static ByteCodeCommand[] parse(ClassFile clzFile, String code){ + + return null; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/CommandParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..e48ab7c091 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,84 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; + +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) { + + + return null; + } + + 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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..beb16e5cda --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e5c00c29de --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..cdcdf7ff31 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..b8ab36c150 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..4a62b18a49 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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 = (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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..f7d8e92bdb --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..faf5c7f3e6 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..f7898f8a42 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..1b99558a3e --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..8bd2dbe59e --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,63 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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)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/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ClassInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..52303f2488 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + + public static final Integer UTF8_INFO = 1; + public static final Integer INTEGER_INFO = 3; + public static final Integer FLOAT_INFO = 4; + public static final Integer LONG_INFO = 5; + public static final Integer DOUBLE_INFO = 6; + public static final Integer CLASS_INFO = 7; + public static final Integer STRING_INFO = 8; + public static final Integer FIELDREF_INFO = 9; + public static final Integer METHODREF_INFO = 10; + public static final Integer INTERFACE_METHODREF_INFO = 11; + public static final Integer NAMEANDTYPE_INFO = 12; + public static final Integer METHODHANDLE_INFO = 15; + public static final Integer METHODTYPE_INFO = 16; + public static final Integer INVOKEDYNAMIC_INFO = 18; + + 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); + } + +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantPool.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..f94f00426d --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.FIELDREF_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(); + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..44ddf169f2 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHODREF_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(); + } + + + +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..7eae6e4ec1 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAMEANDTYPE_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()+")"; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/StringInfo.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/constant/UTF8Info.java b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7e80c58a86 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.constant; + +public class UTF8Info extends ConstantInfo{ + + private int type = 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; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value +")]"; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/field/Field.java b/group05/578505552/miniJvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..72d268c6ca --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + String name = pool.getUTF8String(nameIndex); + System.out.println("field <" + name + "> 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/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..99a6c22608 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +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 = new byte[len]; + System.arraycopy(codes, pos, data, 0, 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/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..049fbb3cde --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,88 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.clz.ClassFile; + +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 : clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + } + + public void addClassPath(String path) { + if(clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + public String getClassPath(){ + + StringBuffer buffer = new StringBuffer(); + + for(int i = 0;i < clzPaths.size(); i++){ + buffer.append(clzPaths.get(i)); + if(i < clzPaths.size() - 1){ + buffer.append(";"); + } + } + + return buffer.toString(); + } + + private byte[] loadClassFile(String clzFileName) { + + BufferedInputStream bis = null; + try { + File f = new File(clzFileName); + bis = new BufferedInputStream(new FileInputStream(f)); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + byte[] buffer = new byte[1024]; + int length = -1; + + while((length = bis.read(buffer)) != -1){ + bos.write(buffer, 0, length); + } + byte [] codes = bos.toByteArray(); + return codes; + + } catch(IOException e){ + e.printStackTrace(); + + } finally{ + if(bis != null){ + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + + } + +} \ No newline at end of file diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..19201bd175 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,125 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; +import com.coderising.jvm.parser.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ClassFileParser { + + private static final Map constantPoolParserMap = new HashMap(); + + static { + constantPoolParserMap.put(ConstantInfo.UTF8_INFO, new UTF8InfoParser()); +// constantPoolParserMap.put(ConstantInfo.INTEGER_INFO, new IntegerInfoParser()); +// constantPoolParserMap.put(ConstantInfo.FLOAT_INFO, new FloatInfoParser()); +// constantPoolParserMap.put(ConstantInfo.LONG_INFO, new LongInfoParser()); +// constantPoolParserMap.put(ConstantInfo.DOUBLE_INFO, new DoubleInfoParser()); + constantPoolParserMap.put(ConstantInfo.CLASS_INFO, new ClassInfoParser()); + constantPoolParserMap.put(ConstantInfo.STRING_INFO, new StringInfoParser()); + constantPoolParserMap.put(ConstantInfo.FIELDREF_INFO, new FieldRefInfoParser()); + constantPoolParserMap.put(ConstantInfo.METHODREF_INFO, new MethodRefInfoParser()); +// constantPoolParserMap.put(ConstantInfo.INTERFACE_METHODREF_INFO, new InterfaceMethodrefInfoParser()); + constantPoolParserMap.put(ConstantInfo.NAMEANDTYPE_INFO, new NameAndTypeInfoParser()); +// constantPoolParserMap.put(ConstantInfo.METHODHANDLE_INFO, new MethodHandleInfoParser()); +// constantPoolParserMap.put(ConstantInfo.METHODTYPE_INFO, new MethodTypeInfoParser()); +// constantPoolParserMap.put(ConstantInfo.INVOKEDYNAMIC_INFO, new InvokeDynamicInfoParser()); + } + + public ClassFile parse(byte[] codes) { + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + + String magicNum = iterator.nextU4ToHexString(); + if (!"cafebabe".equals(magicNum)){ + return null; + } + + ClassFile clzFile = new ClassFile(); + + clzFile.setMinorVersion(iterator.nextU2ToInt()); + clzFile.setMajorVersion(iterator.nextU2ToInt()); + clzFile.setConstPool(parseConstantPool(iterator)); + clzFile.setAccessFlag(parseAccessFlag(iterator)); + clzFile.setClassIndex(parseClassInfex(iterator)); + + parseInterfaces(iterator); + + parseFileds(clzFile, iterator); + parseMethods(clzFile, iterator); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + return new AccessFlag(iter.nextU2ToInt()); + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextU2ToInt()); + classIndex.setSuperClassIndex(iter.nextU2ToInt()); + + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int constantPoolCount = iter.nextU2ToInt(); + + ConstantPool constantPool = new ConstantPool(); + constantPool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i < constantPoolCount; i++) { + + int tag = iter.nextU1toInt(); + ConstantInfoParser parser = constantPoolParserMap.get(tag); + if (parser == null){ + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); + } + constantPool.addConstantInfo(parser.parser(constantPool, iter)); + } + + return constantPool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + +// throw new RuntimeException("interfaceParse has not been implemented"); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { + + int fieldCount = iter.nextU2ToInt(); + for (int i = 0; i < fieldCount; i++) { + clzFile.addField(Field.parse(clzFile.getConstantPool(), iter)); + } + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + + int methodCount = iter.nextU2ToInt(); + + for (int i = 0; i < methodCount; i++) { + clzFile.addMethod(Method.parse(clzFile, iter)); + } + } + +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/method/Method.java b/group05/578505552/miniJvm/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..98b2042c11 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,99 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private CodeAttr codeAttr; + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + + + public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + + int accessFlags = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attributesCount = iter.nextU2ToInt(); + + String name = clzFile.getConstantPool().getUTF8String(nameIndex); + System.out.println("method <" + name + "> attribute count : "+ attributesCount); + + String descriptor = clzFile.getConstantPool().getUTF8String(descriptorIndex); + System.out.println("method <" + name + "> descriptor :" + descriptor); + + Method method = new Method(clzFile, accessFlags, nameIndex, descriptorIndex); + for (int i = 0; i < attributesCount; i++) { + + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if (AttributeInfo.CODE.equals(attrName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + } else { + throw new RuntimeException(attrName + " attribute has not been implemented"); + } + } + + return method; + } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ClassInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ClassInfoParser.java new file mode 100644 index 0000000000..bed605c354 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ClassInfoParser.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class ClassInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + ClassInfo classInfo = new ClassInfo(constantPool); + int index = iterator.nextU2ToInt(); + classInfo.setUtf8Index(index); + + return classInfo; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ConstantInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ConstantInfoParser.java new file mode 100644 index 0000000000..f437a54a4a --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/ConstantInfoParser.java @@ -0,0 +1,14 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public abstract class ConstantInfoParser { + + public abstract ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator); +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/DoubleInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/DoubleInfoParser.java new file mode 100644 index 0000000000..6563e68861 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/DoubleInfoParser.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class DoubleInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FieldRefInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FieldRefInfoParser.java new file mode 100644 index 0000000000..316e0fcd4d --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FieldRefInfoParser.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class FieldRefInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + + return fieldRefInfo; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FloatInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FloatInfoParser.java new file mode 100644 index 0000000000..6162eb798f --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/FloatInfoParser.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class FloatInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/IntegerInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/IntegerInfoParser.java new file mode 100644 index 0000000000..a97a0fa9a4 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/IntegerInfoParser.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class IntegerInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InterfaceMethodrefInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InterfaceMethodrefInfoParser.java new file mode 100644 index 0000000000..06f301cf9a --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InterfaceMethodrefInfoParser.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class InterfaceMethodrefInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InvokeDynamicInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InvokeDynamicInfoParser.java new file mode 100644 index 0000000000..f008c4a9b7 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/InvokeDynamicInfoParser.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class InvokeDynamicInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/LongInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/LongInfoParser.java new file mode 100644 index 0000000000..000ff4e841 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/LongInfoParser.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class LongInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodHandleInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodHandleInfoParser.java new file mode 100644 index 0000000000..679f2e52d9 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodHandleInfoParser.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class MethodHandleInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodRefInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodRefInfoParser.java new file mode 100644 index 0000000000..5bfdb1364b --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodRefInfoParser.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class MethodRefInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + + return methodRefInfo; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodTypeInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodTypeInfoParser.java new file mode 100644 index 0000000000..c155ef8d5c --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/MethodTypeInfoParser.java @@ -0,0 +1,15 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class MethodTypeInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + return null; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/NameAndTypeInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/NameAndTypeInfoParser.java new file mode 100644 index 0000000000..6376966e68 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/NameAndTypeInfoParser.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class NameAndTypeInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(iterator.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iterator.nextU2ToInt()); + + return nameAndTypeInfo; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/StringInfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/StringInfoParser.java new file mode 100644 index 0000000000..6f576e83ef --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/StringInfoParser.java @@ -0,0 +1,20 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.loader.ByteCodeIterator; + +/** + * Created by songbao.yang on 2017/4/19. + */ +public class StringInfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(iterator.nextU2ToInt()); + + return stringInfo; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/parser/UTF8InfoParser.java b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/UTF8InfoParser.java new file mode 100644 index 0000000000..566bab3ce6 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/parser/UTF8InfoParser.java @@ -0,0 +1,34 @@ +package com.coderising.jvm.parser; + +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + +import java.io.UnsupportedEncodingException; + +/** + * + * Created by songbao.yang on 2017/4/19. + */ +public class UTF8InfoParser extends ConstantInfoParser { + + public ConstantInfo parser(ConstantPool constantPool, ByteCodeIterator iterator) { + + int lenght = iterator.nextU2ToInt(); + byte[] bytes = iterator.getBytes(lenght); + + String value = null; + try { + value = new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Info = new UTF8Info(constantPool); + utf8Info.setLength(lenght); + utf8Info.setValue(value); + + return utf8Info; + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/print/ClassFilePrinter.java b/group05/578505552/miniJvm/src/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..ee6a99daa6 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.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 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java b/group05/578505552/miniJvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..c1a9700884 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group05/578505552/miniJvm/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..7b93641e63 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,331 @@ +package com.coderising.jvm.test; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; +import com.coderising.jvm.constant.*; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; +import com.coderising.jvm.util.Util; +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 = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "D:\\project\\Learn\\coding2017\\group05\\578505552\\miniJvm\\src"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.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 = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = Util.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + /** + * ---------------------------------------------------------------------- + */ + + + @Test + public void testVersion(){ + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool(){ + + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", 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/group05/578505552/miniJvm/src/com/coderising/jvm/test/EmployeeV1.java b/group05/578505552/miniJvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..f49176c686 --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.test; + +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){ + com.coderising.jvm.test.EmployeeV1 p = new com.coderising.jvm.test.EmployeeV1("Andy",29); + p.sayHello(); + + } +} \ No newline at end of file diff --git a/group05/578505552/miniJvm/src/com/coderising/jvm/util/Util.java b/group05/578505552/miniJvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group05/578505552/miniJvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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 res[k-1]){ - res[k++] = next; - } - } - - int[] merged = new int[k]; - System.arraycopy(res, 0, merged, 0, k); - return merged; - } - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * @param oldArray - * @param size - * @return - */ - public int[] grow(int [] oldArray, int size){ - if (size < 0){ - throw new IllegalArgumentException("illegal size"); - } - int newLength = oldArray.length + size; - int[] newArray = new int[newLength]; - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); - return newArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - * @param max - * @return - */ - public int[] fibonacci(int max){ - - if (max <= 1){ - return new int[0]; - } - - int[] res = new int[max]; - int i = 1; - int j = 1; - int k = 0; - res[k++] = 1; - res[k++] = 1; - - int tmp = i + j; - while (tmp < max){ - res[k++] = tmp; - i = j; - j = tmp; - tmp = i + j; - } - - int[] result = new int[k]; - System.arraycopy(res, 0, result, 0, k); - return result; - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * @param max - * @return - */ - public int[] getPrimes(int max){ - if (max < 3){ - return new int[0]; - } - int[] res = new int[max]; - int k = 0; - for (int i = 2; i < max; i++) { - if (isPrime(i)){ - res[k++] = i; - } - } - int[] result = new int[k]; - System.arraycopy(res, 0, result, 0, k); - return result; - } - - private boolean isPrime(int num){ - - if (num < 1){ - return false; - } - for (int i = 2; i <= num / 2; i++) { - if (num % i == 0){ - return false; - } - - } - return true; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * @param max - * @return - */ - public int[] getPerfectNumbers(int max){ - - if (max < 0){ - return new int[0]; - } - int[] res = new int[max]; - int k = 0; - for (int i = 0; i < max; i++) { - if (isPerfectNumbers(i)){ - res[k++] = i; - } - } - int[] result = new int[k]; - System.arraycopy(res, 0, result, 0, k); - return result; - } - - private boolean isPerfectNumbers(int num){ - - return num == getFactorSum(num); - } - - private int getFactorSum(int num){ - if (num == 0 || num == 1){ - return -1; - } - int sum = 0; - for (int i = 1; i <= num / 2; i++) { - if (num % i == 0){ - sum += i; - } - } - return sum; - } - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" - * @param array - * @param separator - * @return - */ - public String join(int[] array, String separator){ - - if (array == null || array.length <= 0){ - return ""; - } - - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < array.length - 1; i++) { - stringBuffer.append(String.valueOf(array[i])).append(separator); - } - stringBuffer.append(String.valueOf(array[array.length-1])); - return stringBuffer.toString(); - } - - public static void main(String[] args) { - ArrayUtil arrayUtil = new ArrayUtil(); - System.out.println("-------------------------"); - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/DownloadThread.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/DownloadThread.java deleted file mode 100644 index c837e08f8b..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/DownloadThread.java +++ /dev/null @@ -1,47 +0,0 @@ -package dataStruct.com.coderising.download; - -import dataStruct.com.coderising.download.api.Connection; -import dataStruct.com.coderising.download.api.DownloadListener; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -public class DownloadThread extends Thread{ - - Connection conn; - int startPos; - int endPos; - File targetFile; - DownloadListener listener; - - public DownloadThread(Connection conn, int startPos, int endPos, File targetFile, DownloadListener listener){ - this.conn = conn; - this.startPos = startPos; - this.endPos = endPos; - this.targetFile = targetFile; - this.listener = listener; - } - public void run(){ - try { - System.out.println("线程" + this.getName() + "正在下载" + startPos + "--" + endPos + "的数据"); - - byte[] content = conn.read(startPos, endPos); - RandomAccessFile randomAccessFile = new RandomAccessFile(targetFile, "rw"); - randomAccessFile.seek(startPos); - randomAccessFile.write(content, 0, endPos - startPos + 1); - randomAccessFile.close(); - - System.out.println("线程" + this.getName() + "完成" + startPos + "--" + endPos + "数据的下载"); - - if (FileDownloader.isDownLoadFinished()){ - listener.notifyFinished(); - System.out.println(">>>>>>>>>>>>>>线程" + this.getName() + "完成了最终的下载"); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - conn.close(); - } - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/FileDownloader.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/FileDownloader.java deleted file mode 100644 index 324ba4d29d..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/FileDownloader.java +++ /dev/null @@ -1,66 +0,0 @@ -package dataStruct.com.coderising.download; - -import dataStruct.com.coderising.download.api.Connection; -import dataStruct.com.coderising.download.api.ConnectionException; -import dataStruct.com.coderising.download.api.ConnectionManager; -import dataStruct.com.coderising.download.api.DownloadListener; - -import java.io.File; - -public class FileDownloader { - - String url; - DownloadListener listener; - ConnectionManager cm; - public static final int threadCount = 5; - private static int threadFinished; - - public FileDownloader(String _url) { - this.url = _url; - } - - public void execute(){ - try { - Connection conn = cm.open(this.url); - int length = conn.getContentLength(); - - File targetFile = new File("D:" + File.separator + getFileName()); - System.out.println("总长度:" + length); - - int temp = length / threadCount; - for (int i = 0; i < threadCount; i++) { - int startPos = i * temp; - int endPos = startPos + temp - 1; - if (i == threadCount - 1){ - endPos = length; - } - String threadName = "DownloadThread" + String.valueOf(i); - Connection connection = cm.open(url); - DownloadThread downloadThread = new DownloadThread(connection, startPos, endPos, targetFile, listener); - downloadThread.setName(threadName); - downloadThread.start(); - } - } catch (ConnectionException e) { - e.printStackTrace(); - } finally{ - - } - } - - public String getFileName(){ - return "meinv.jpg"; - } - - public synchronized static boolean isDownLoadFinished(){ - threadFinished++; - return threadFinished == threadCount; - } - - public void setListener(DownloadListener listener) { - this.listener = listener; - } - - public void setConnectionManager(ConnectionManager ucm){ - this.cm = ucm; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/Connection.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/Connection.java deleted file mode 100644 index da33f7360c..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/Connection.java +++ /dev/null @@ -1,23 +0,0 @@ -package dataStruct.com.coderising.download.api; - -import java.io.IOException; - -public interface Connection { - /** - * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * @param startPos 开始位置, 从0开始 - * @param endPos 结束位置 - * @return - */ - public byte[] read(int startPos, int endPos) throws IOException; - /** - * 得到数据内容的长度 - * @return - */ - public int getContentLength(); - - /** - * 关闭连接 - */ - public void close(); -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionException.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionException.java deleted file mode 100644 index 2efc59eec6..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionException.java +++ /dev/null @@ -1,20 +0,0 @@ -package dataStruct.com.coderising.download.api; - -public class ConnectionException extends Exception { - - public ConnectionException() { - } - - public ConnectionException(String message) { - super(message); - } - - public ConnectionException(String message, Throwable cause) { - super(message, cause); - } - - public ConnectionException(Throwable cause) { - super(cause); - } - -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionManager.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionManager.java deleted file mode 100644 index 2ac9aa5ac9..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionManager.java +++ /dev/null @@ -1,10 +0,0 @@ -package dataStruct.com.coderising.download.api; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * @param url - * @return - */ - public Connection open(String url) throws ConnectionException; -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/DownloadListener.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/DownloadListener.java deleted file mode 100644 index 8daca6846c..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package dataStruct.com.coderising.download.api; - -public interface DownloadListener { - public void notifyFinished(); -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionImpl.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionImpl.java deleted file mode 100644 index c9b1c7c103..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package dataStruct.com.coderising.download.impl; - -import dataStruct.com.coderising.download.api.Connection; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; - -public class ConnectionImpl implements Connection{ - - private HttpURLConnection conn; - - public ConnectionImpl(HttpURLConnection urlConnection) { - this.conn = urlConnection; - } - - public byte[] read(int startPos, int endPos) throws IOException { - conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - if (conn.getResponseCode() == 206){ - InputStream inputStream = conn.getInputStream(); - byte[] temp = new byte[endPos - startPos + 1]; - while ((inputStream.read(temp)) != -1){ - - } - return temp; - } - return new byte[0]; - } - - public int getContentLength() { - try { - if (conn.getResponseCode() == 200){ - return conn.getContentLength(); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - this.close(); - } - return 0; - } - - public void close() { - if (conn != null){ - conn.disconnect(); - conn = null; - } - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionManagerImpl.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index e8e5a85aeb..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -package dataStruct.com.coderising.download.impl; - -import dataStruct.com.coderising.download.api.Connection; -import dataStruct.com.coderising.download.api.ConnectionException; -import dataStruct.com.coderising.download.api.ConnectionManager; - -import java.net.HttpURLConnection; -import java.net.URL; - -public class ConnectionManagerImpl implements ConnectionManager { - - public Connection open(String url) throws ConnectionException { - - try { - URL urlObject = new URL(url); - HttpURLConnection urlConnection = (HttpURLConnection)urlObject.openConnection(); - urlConnection.setRequestMethod("GET"); - urlConnection.setReadTimeout(5000); - return new ConnectionImpl(urlConnection); - } catch (java.io.IOException e) { - throw new ConnectionException("连接失败"); - } - } - -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Configuration.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Configuration.java deleted file mode 100644 index c85b40029f..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Configuration.java +++ /dev/null @@ -1,7 +0,0 @@ -package dataStruct.com.coderising.litestruts; - -/** - * Created by songbao.yang on 2017/3/10. - */ -public class Configuration { -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/LoginAction.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/LoginAction.java deleted file mode 100644 index b7789abf28..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/LoginAction.java +++ /dev/null @@ -1,38 +0,0 @@ -package dataStruct.com.coderising.litestruts; - -/** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * - */ -public class LoginAction{ - private String name ; - private String password; - private String message; - - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - - public String execute(){ - if("test".equals(name) && "1234".equals(password)){ - this.message = "login successful"; - return "success"; - } - this.message = "login failed,please check your user/pwd"; - return "fail"; - } - - public void setName(String name){ - this.name = name; - } - public void setPassword(String password){ - this.password = password; - } - public String getMessage(){ - return this.message; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Struts.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Struts.java deleted file mode 100644 index 00bc5a446f..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Struts.java +++ /dev/null @@ -1,131 +0,0 @@ -package dataStruct.com.coderising.litestruts; - -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class Struts { - - public static View runAction(String actionName, Map parameters) { - -// 0. 读取配置文件struts.xml - Action action = matchAction(parseXml("/struts.xml"), actionName); - try { - -// 1. 根据actionName找到相对应的class, 通过反射实例化(创建对象), -// 根据parameters中的数据,调用对象的setter方法 - Class clazz = Class.forName(action.getClassName()); - Object instance = clazz.newInstance(); - for (String key : parameters.keySet()){ - try { - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(key, clazz); - Method setMethod = propertyDescriptor.getWriteMethod(); - setMethod.invoke(instance, parameters.get(key)); - } catch (IntrospectionException e) { - e.printStackTrace(); - } - } - -// 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" - Method exectueMethod = null; - String result = null; - try { - exectueMethod = clazz.getMethod("execute"); - result = (String)exectueMethod.invoke(instance); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - -// 3. 通过反射找到对象的所有getter方法(例如 getMessage), -// 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , -// 放到View对象的parameters - Map hashMap = new HashMap(); - Field[] declaredFields = clazz.getDeclaredFields(); - for (Field field : declaredFields){ - String name = field.getName(); - try { - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, clazz); - Method getMethod = propertyDescriptor.getReadMethod(); - Object res = getMethod.invoke(instance); - hashMap.put(name, res); - } catch (IntrospectionException e) { - e.printStackTrace(); - } - } - -// 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, -// 放到View对象的jsp字段中。 - View view = new View(); - view.setJsp((String)action.getResults().get(result)); - view.setParameters(hashMap); - return view; - - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - - return null; - } - - private static Element parseXml(String resourcePath){ - - InputStream resourceAsStream = Struts.class.getResourceAsStream(resourcePath); - SAXReader saxReader = new SAXReader(); - try { - Document document = saxReader.read(resourceAsStream); - Element rootElement = document.getRootElement(); - return rootElement; - } catch (DocumentException e) { - e.printStackTrace(); - } - - throw new RuntimeException("fail to parse xml"); - } - - private static Action matchAction(Element rootElement, String actionName){ - - List actions = rootElement.elements("action"); - Iterator iterator = actions.iterator(); - Action action = new Action(); - while (iterator.hasNext()){ - Element actionElement = (Element) iterator.next(); - String nameAttributeValue = actionElement.attributeValue("name"); - if (actionName.equals(nameAttributeValue)){ - action.setName(nameAttributeValue); - action.setClassName(actionElement.attributeValue("class")); - List results = actionElement.elements("result"); - Map resultMap = new HashMap(); - Iterator it = results.iterator(); - while (it.hasNext()){ - Element resultElement = (Element)it.next(); - resultMap.put(resultElement.attributeValue("name"), (String)resultElement.getData()); - } - action.setResults(resultMap); - } - } - - return action; - } - - - - -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/View.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/View.java deleted file mode 100644 index bb6f39e9a9..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/View.java +++ /dev/null @@ -1,23 +0,0 @@ -package dataStruct.com.coderising.litestruts; - -import java.util.Map; - -public class View { - private String jsp; - private Map parameters; - - public String getJsp() { - return jsp; - } - public View setJsp(String jsp) { - this.jsp = jsp; - return this; - } - public Map getParameters() { - return parameters; - } - public View setParameters(Map parameters) { - this.parameters = parameters; - return this; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/ArrayList.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/ArrayList.java deleted file mode 100644 index cdbb1107a0..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/ArrayList.java +++ /dev/null @@ -1,103 +0,0 @@ -package dataStruct.com.coding.basic; - -import java.util.NoSuchElementException; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public class ArrayList implements List { - - private int size = 0; - private Object[] elementData; - private static final int MIN_CAPACITY = 10; - - public ArrayList(int size) { - if (size < 0){ - throw new IllegalArgumentException("illega size: " + size); - } - this.elementData = new Object[size]; - } - - public ArrayList() { - this.elementData = new Object[0]; - } - - public void add(T o){ - ensureCapacity(size + 1); - elementData[size++] = o; - } - - private void ensureCapacity(int minCapacity){ - if (minCapacity < 0 ){ - throw new OutOfMemoryError(); - } - - int newCapcity = size; - if(minCapacity < MIN_CAPACITY){ - newCapcity = MIN_CAPACITY; - } else if(minCapacity > elementData.length){ - int tmp = elementData.length << 1; - newCapcity = tmp > elementData.length ? tmp : Integer.MAX_VALUE; - } - - newCapcity = minCapacity; - Object[] newData = new Object[newCapcity]; - System.arraycopy(elementData, 0, newData, 0, size); - elementData = newData; - } - - public void add(int index, T o){ - indexCheck(index); - ensureCapacity(size+1); - System.arraycopy(elementData, index, elementData, index+1, size-index); - elementData[index] = o; - size++; - } - - public T get(int index){ - indexCheck(index); - return (T) elementData[index]; - } - - private void indexCheck(int index){ - if(index < 0){ - throw new IllegalArgumentException("illegal index: " + index); - } - if(index >= size){ - throw new IndexOutOfBoundsException(); - } - } - - public T remove(int index){ - indexCheck(index); - Object rm = elementData[index]; - System.arraycopy(elementData, index+1, elementData, index, size-index-1); - size--; - return (T) rm; - } - - public int size(){ - return size; - } - - public Iterator iterator(){ - return new Itr(); - } - - //静态内部类的访问权限不同有何区别?? - private class Itr implements Iterator { - private int cursor = 0; - - public boolean hasNext() { - return cursor != size; - } - - public Object next() { - if (hasNext()){ - return elementData[cursor++]; - } - throw new NoSuchElementException(); - } - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/BinaryTreeNode.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/BinaryTreeNode.java deleted file mode 100644 index ee0351da07..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/BinaryTreeNode.java +++ /dev/null @@ -1,60 +0,0 @@ -package dataStruct.com.coding.basic; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public class BinaryTreeNode { - - private Integer data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public Object getData() { - return data; - } - public void setData(Integer data) { - this.data = data; - } - public BinaryTreeNode getLeft() { - return left; - } - public void setLeft(BinaryTreeNode left) { - this.left = left; - } - public BinaryTreeNode getRight() { - return right; - } - public void setRight(BinaryTreeNode right) { - this.right = right; - } - - public BinaryTreeNode insert(Integer o){ - if (o == null){ - throw new IllegalArgumentException("can not insert null"); - } - - BinaryTreeNode newNode = new BinaryTreeNode(); - newNode.data = o; - newNode.left = null; - newNode.right = null; - - BinaryTreeNode cursor = this; - BinaryTreeNode pre = cursor; - while (cursor != null){ - pre = cursor; - if (o.compareTo(cursor.data) < 0){ - cursor = cursor.left; - } else { - cursor = cursor.right; - } - } - - if (o.compareTo(pre.data) < 0){ - pre.left = newNode; - } else { - pre.right = newNode; - } - return this; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Iterator.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Iterator.java deleted file mode 100644 index 1755e82202..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Iterator.java +++ /dev/null @@ -1,11 +0,0 @@ -package dataStruct.com.coding.basic; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/LinkedList.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/LinkedList.java deleted file mode 100644 index 9238a5c7a0..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/LinkedList.java +++ /dev/null @@ -1,390 +0,0 @@ -package dataStruct.com.coding.basic; - -import java.util.NoSuchElementException; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public class LinkedList implements List { - - private Node head; - private int elementCount; - - //head作为一个节点,其next的值指向List中真正的第一个节点 - public LinkedList() { - head = new Node(); - head.next = null; - head.data = null; - elementCount = 0; - } - - public void add(T o){ - Node newNode = new Node(); - newNode.data = o; - newNode.next = null; - - Node cursor = head; - while (cursor.next != null){ - cursor = cursor.next; - } - cursor.next = newNode; - elementCount++; - } - - - public void add(int index , T o){ - indexRangeCheck(index); - Node newNode = new Node(); - newNode.data = o; - - Node cursor = head; - for (int i = 0; i < index; i++) { - cursor = cursor.next; //将cursor移动到index-1节点处; - } - - newNode.next = cursor.next; //将新节点指向原index处的节点 - cursor.next = newNode;//将原index-1处的节点指向新节点 - elementCount++; - } - - private void indexRangeCheck(int index){ - if (index < 0 || index >= size()){ - throw new IndexOutOfBoundsException(); - } - } - - public T get(int index){ - indexRangeCheck(index); - Node cursor = head; - for (int i = 0; i < index; i++) { - cursor = cursor.next; - } - return (T) cursor.next.data; - } - - public T remove(int index){ - indexRangeCheck(index); - Node cursor = head; - for (int i = 0; i < index; i++) { - cursor = cursor.next; - } - Node indexNode = cursor.next; - cursor.next = indexNode.next; - elementCount--; - return (T) indexNode; - } - - public int size(){ - return elementCount; - } - - public void addFirst(T o){ - Node node = new Node(); - node.data = o; - node.next = head.next; - head.next = node; - elementCount++; - } - - public void addLast(T o){ - - Node cursor = head; - while (cursor.next != null){ - cursor = cursor.next; - } - Node newNode = new Node(); - newNode.data = o; - newNode.next = null; - cursor.next = newNode; - elementCount++; - } - - public T removeFirst(){ - - if (size() == 0){ - throw new RuntimeException("no element in list"); - } - Node firstNode = head.next; - head.next = head.next.next; - elementCount--; - return (T) firstNode; - } - - public T removeLast(){ - if (size() == 0){ - throw new RuntimeException("no element in list"); - } - - Node cursor = head; - for (int i = 0; i < size() - 1; i++) { - cursor = cursor.next; - } - - Node lastNode = cursor.next; - cursor.next = null; - elementCount--; - - return (T) lastNode; - } - - public Iterator iterator(){ - return new Itr(); - } - - private class Itr implements Iterator { - - private Node itrCursor = head; - - public boolean hasNext() { - - return itrCursor.next != null; - } - - public Object next() { - if (hasNext()){ - return itrCursor.next; - } - throw new NoSuchElementException(); - } - } - - private static class Node{ - T data; - Node next; - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - if (elementCount <= 1){ - return; - } - - Node first = head.next; - Node second = head.next.next; - - first.next = null; - while (second != null){ - Node temp = second.next; - second.next = first; - first = second; - second = temp; - } - head.next = first; - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - - Node cousor = head.next; - for (int i = 0; i < elementCount / 2; i++) { - Node temp = cousor; - cousor = cousor.next; - temp.data = null; - temp.next = null; - } - head.next = cousor; - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * @param i - * @param length - */ - public void remove(int i, int length){ - if (i < 0 || length < 0){ - return; - } - if (i > elementCount - 1){ - throw new IndexOutOfBoundsException("index i is too big"); - } - - Node beforei = head; - for (int j = 0; j < i; j++) { - beforei = beforei.next; - } - Node cursor = beforei.next; - for (int j = 0; j < length; j++) { - if (cursor != null){ - Node temp = cursor; - cursor = cursor.next; - temp.data = null; - temp.next = null; - }else { - break; - } - } - beforei.next = cursor; - } - /** - * 假定当前链表和listB均包含已升序排列的整数 - * 从当前链表中取出那些listB所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public int[] getElements(LinkedList list){ - - int[] result = new int[list.size()]; - int i = 0; - int pre = 0; - Node cousor = head.next; - Iterator YIterator = list.iterator(); - while (YIterator.hasNext()){ - int index = (Integer) YIterator.next(); - if (index > elementCount - 1){ - break; - } - moveForwardNIndex(cousor, index - pre); - result[i++] = (Integer) cousor.data; - pre = index; - } - - int[] ints = new int[result.length]; - System.arraycopy(result, 0, ints, 0, result.length); - return ints; - } - - private void moveForwardNIndex(Node index, int n){ - for (int i = 0; i < n; i++) { - if (index == null){ - break; - } - index = index.next; - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在listB中出现的元素 - - * @param list - */ - - public void subtract(LinkedList list){ - - Node pre = head; - Node node = head.next; - while (node != null){ - if (list.contains(node.data)){ - pre.next = node.next; - node = node.next; - } else { - pre = node; - node = node.next; - } - } - } - - public boolean contains(T data){ - - Node cursor = this.head.next; - while (cursor != null){ - if (cursor.data.equals(data)){ - return true; - } - } - return false; - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - - if (elementCount <= 1){ - return; - } - Node pre = head.next; - Node node = pre.next; - while (node != null){ - if (node.data.equals(pre.data)){ - pre.next = node.next; - node = node.next; - } else { - pre = node; - node = node.next; - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - //TODO 这个泛型的比较没搞明白, 为什么会出现cast的问题,不应该都是T类型吗 - public void removeRange(T min, T max){ - if (min.compareTo(max) > 0){ - return; - } - if (size() == 0){ - return; - } - Node beforeMin = head; - //泛型化 - while (beforeMin.next != null && beforeMin.next.data.compareTo(min) <= 0){ - beforeMin = beforeMin.next; - } - Node afterMax = beforeMin.next; - while (afterMax != null && afterMax.data.compareTo(max) < 0){ - afterMax = afterMax.next; - } - beforeMin.next = afterMax; - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList intersection(LinkedList list){ - - if (list == null || list.size() == 0 || this.size() == 0){ - return new LinkedList(); - } - - Node cursorA = this.head.next; - Node cursorB = list.head.next; - LinkedList listC = new LinkedList(); - - while (cursorA != null && cursorB != null){ - if (cursorA.data.compareTo(cursorB.data) == 0){ - listC.add((T)cursorA.data); - } else if (cursorA.data.compareTo(cursorB.data) < 0){ - cursorA = cursorA.next; - } else { - cursorB = cursorB.next; - } - } - return listC; - } - - public void addAfter(Node node, T o){ - if (node == null){ - return; - } - Node newNode = new Node(); - newNode.data = o; - addAfter(node, newNode); - } - - public void addAfter(Node node, Node newNode){ - if (node == null || newNode == null){ - return; - } - newNode.next = node.next; - node.next = newNode; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/List.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/List.java deleted file mode 100644 index 20d7a6daf9..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/List.java +++ /dev/null @@ -1,14 +0,0 @@ -package dataStruct.com.coding.basic; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public interface List { - public void add(T o); - public void add(int index, T o); - public T get(int index); - public T remove(int index); - public int size(); - public Iterator iterator(); -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Queue.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Queue.java deleted file mode 100644 index 2b3a62a5d3..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Queue.java +++ /dev/null @@ -1,90 +0,0 @@ -package dataStruct.com.coding.basic; - -import java.util.NoSuchElementException; - -/** - * Created by songbao.yang on 2017/2/22. - * - */ -public class Queue { - - private Object[] elementData; - private int head; //对头的位置 - private int tail; //队尾的位置 - private int size; //队列中元素的个数 - private static final int MIN_INITIAL_CAPACITY = 10; - - public Queue() { - this.elementData = new Object[MIN_INITIAL_CAPACITY]; - this.head = 0; - this.tail = 0; - this.size = 0; - } - - public Queue(int initCapcacity) { - if (initCapcacity < MIN_INITIAL_CAPACITY){ - initCapcacity = MIN_INITIAL_CAPACITY; - } - this.elementData = new Object[initCapcacity]; - this.head = 0; - this.tail = 0; - this.size = 0; - } - - public void enQueue(Object o){ - ensureCapacity(size+1); - if(size != 0){ - tail++; - } - if(tail == elementData.length){ - tail = 0; - } - elementData[tail] = o; - size++; - } - - private void ensureCapacity(int minCapcacity){ - if(minCapcacity <= elementData.length){ - return; - } - - int newCapcacity = elementData.length << 1; - if (newCapcacity < elementData.length){ - newCapcacity = Integer.MAX_VALUE; - } - - Object[] newData = new Object[newCapcacity]; - if(size != 0){ - if(tail >= head){ - System.arraycopy(elementData, head, newData, 0, size); - } else { - System.arraycopy(elementData, head, newData, 0, elementData.length - head); - System.arraycopy(elementData, 0, newData, elementData.length - head, tail + 1); - } - elementData = newData; - head = 0; - tail = this.size - 1; - } - } - - public Object deQueue(){ - if (isEmpty()){ - throw new NoSuchElementException("empty queue"); - } - Object ele = elementData[head]; - size--; - head++; - if(head == elementData.length){ - head = 0; - } - return ele; - } - - public boolean isEmpty(){ - return size == 0; - } - - public int size(){ - return size; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Stack.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Stack.java deleted file mode 100644 index 4f41c69a9e..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/Stack.java +++ /dev/null @@ -1,63 +0,0 @@ -package dataStruct.com.coding.basic; - - -import java.util.EmptyStackException; - -/** - * Created by songbao.yang on 2017/2/22. - * - */ -public class Stack { - - private Object[] elementData; - private static final int MIN_INITIAL_CAPACITY = 10; - private int cursor; - - public Stack() { - elementData = new Object[MIN_INITIAL_CAPACITY]; - cursor = -1; - } - - public void push(Object o){ - ensureCapacity(size() + 1); - cursor++; - elementData[cursor] = o; - } - - private void ensureCapacity(int minCapacity){ - if(minCapacity <= elementData.length){ - return; - } - - int newSize = elementData.length << 1; - if (newSize < elementData.length){ - newSize = Integer.MAX_VALUE; - } - - Object[] newDataArray = new Object[newSize]; - System.arraycopy(elementData, 0, newDataArray, 0, size()); - elementData = newDataArray; - } - - - public Object pop(){ - Object ele = peek(); - cursor--; - return ele; - } - - public Object peek(){ - if (isEmpty()){ - throw new EmptyStackException(); - } - return elementData[cursor]; - } - - public boolean isEmpty(){ - return size() == 0; - } - - public int size(){ - return cursor + 1; - } -} diff --git a/group05/578505552/src/main/java/dataStruct/com/coding/basic/linklist/LRUPageFrame.java b/group05/578505552/src/main/java/dataStruct/com/coding/basic/linklist/LRUPageFrame.java deleted file mode 100644 index cebc4bc739..0000000000 --- a/group05/578505552/src/main/java/dataStruct/com/coding/basic/linklist/LRUPageFrame.java +++ /dev/null @@ -1,105 +0,0 @@ -package dataStruct.com.coding.basic.linklist; - -/** - * 用双向链表实现LRU算法 - * @author songbao.yang - * - */ -public class LRUPageFrame { - - private static class Node { - - Node prev; - Node next; - int pageNum; - - Node() { - } - } - - private int capacity; - private int size; - - private Node first;// 链表头 - private Node last;// 链表尾 - - - public LRUPageFrame(int capacity) { - - this.capacity = capacity; - this.size = 0; - first = null; - last = null; - } - - /** - * 获取缓存中对象 - * - * @param pageNum - * @return - */ - public void access(int pageNum) { - - Node newNode = new Node(); - newNode.pageNum = pageNum; - - //往链表头部加入元素 - if (size == 0){ - first = newNode; - last = newNode; - } else { - newNode.next = first; - if (first == null){ - System.out.println("fuck"); - } - first.prev = newNode; - first = newNode; - } - size++; - - //去重 - Node node = first.next; - while (node != null){ - if (node.pageNum == pageNum){ - node.prev.next = node.next; - - if (node == last){ - last = node.prev; - } else { - node.next.prev = node.prev; - } - - Node tmp = node; - node = node.next; - tmp.next = null; - tmp.prev = null; - size--; - } else { - node = node.next; - } - } - - //调整容量 - if (size > capacity){ - last = last.prev; - last.next.prev = null; - last.next = null; - size--; - } - } - - 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/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/ClassFileLoader.java b/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/ClassFileLoader.java deleted file mode 100644 index 97dc361c12..0000000000 --- a/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/ClassFileLoader.java +++ /dev/null @@ -1,68 +0,0 @@ -package miniJvm.com.coderising.jvm.loader; - -import java.io.*; -import java.util.ArrayList; -import java.util.List; - -public class ClassFileLoader { - - private List clzPaths = new ArrayList(); - - public byte[] readBinaryCode(String className) { - - String fullClassName = className.replace(".", "\\") + ".class"; - for (String clzpath : clzPaths){ - byte[] binaryCode = readBinaryCode(clzpath, fullClassName); - if (binaryCode != null){ - return binaryCode; - } - } - return null; - } - - private byte[] readBinaryCode(String clzPath, String fullClassName){ - - String filePath = clzPath + "\\" + fullClassName; - File classFile = new File(filePath); - if (!classFile.exists()){ - return null; - } - try { - FileInputStream fileInputStream = new FileInputStream(classFile); - DataInputStream dataInputStream = new DataInputStream(fileInputStream); - List bytes = new ArrayList(); - int b; - while ((b = dataInputStream.read()) != -1){ - bytes.add((byte)b); - } - byte[] res = new byte[bytes.size()]; - for (int i = 0; i < bytes.size(); i++){ - res[i] = bytes.get(i); - } - return res; - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - public void addClassPath(String path) { - - if (path == null){ - return; - } - clzPaths.add(path); - } - - public String getClassPath(){ - - StringBuffer stringBuffer = new StringBuffer(); - for (String path : clzPaths){ - stringBuffer.append(path).append(";"); - } - return stringBuffer.substring(0, stringBuffer.length() - 1); - } - -} diff --git a/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/EmployeeV1.java b/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/EmployeeV1.java deleted file mode 100644 index edae33a2aa..0000000000 --- a/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/EmployeeV1.java +++ /dev/null @@ -1,31 +0,0 @@ -package miniJvm.com.coderising.jvm.loader; - -public class EmployeeV1 { - - - private String name; - private int age; - - public EmployeeV1() { - } - - 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/group05/578505552/src/main/resources/struts.xml b/group05/578505552/src/main/resources/struts.xml deleted file mode 100644 index 0dc7b6de98..0000000000 --- a/group05/578505552/src/main/resources/struts.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group05/578505552/src/test/java/JavaTest.java b/group05/578505552/src/test/java/JavaTest.java deleted file mode 100644 index 26d2197ffe..0000000000 --- a/group05/578505552/src/test/java/JavaTest.java +++ /dev/null @@ -1,25 +0,0 @@ -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Queue; -import java.util.Stack; - -/** - * Created by songbao.yang on 2017/2/21. - */ -public class JavaTest { - - public static void main(String[] args) { - - ArrayList ss = new ArrayList(); - ss.add("a"); - ss.add("b"); - ss.add("c"); - ss.add("d"); - - System.out.println(ss.size()); - ss.remove(0); - System.out.println(ss.size()); - - - } -} diff --git a/group05/578505552/src/test/java/dataStruct/com/coderising/array/ArrayUtilTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/array/ArrayUtilTest.java deleted file mode 100644 index b09f2efcd0..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coderising/array/ArrayUtilTest.java +++ /dev/null @@ -1,205 +0,0 @@ -package dataStruct.com.coderising.array; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; - -/** - * Created by songbao.yang on 2017/3/2. - * - */ -public class ArrayUtilTest { - - private ArrayUtil arrayUtil; - - @Before - public void setUp() throws Exception { - arrayUtil = new ArrayUtil(); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void reverseArray() throws Exception { - - int[][] actualAndExpected = { - {}, {}, {0}, {0}, - {1,2,3,4,5,6}, {6,5,4,3,2,1}, - {7,9,30,3,4}, {4,3,30,9,7} - }; - - for (int i = 0; i < actualAndExpected.length; i += 2) { - int[] acutal = actualAndExpected[i]; - int[] expected = actualAndExpected[i+1]; - arrayUtil.reverseArray(acutal); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, acutal)); - } - } - - @Test - public void removeZero() throws Exception { - int[][] actualAndExpected = { - {}, {}, {0}, {}, - {1,0,3,0,5,0}, {1,3,5}, - {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}, {1,3,4,5,6,6,5,4,7,6,7,5} - }; - - for (int i = 0; i < actualAndExpected.length; i += 2) { - int[] acutal = actualAndExpected[i]; - int[] expected = actualAndExpected[i+1]; - int[] ints = arrayUtil.removeZero(acutal); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, ints)); - } - } - - @Test - public void merge() throws Exception { - int[][] actualAndExpected = { - {}, {}, {}, - {}, {0}, {0}, - {3,5,7,8}, {4,5,6,7},{3,4,5,6,7,8}, - {1,2,3,4,5,}, {6,7,8,9,10}, {1,2,3,4,5,6,7,8,9,10} - }; - - for (int i = 0; i < actualAndExpected.length; i += 3) { - int[] array1 = actualAndExpected[i]; - int[] array2 = actualAndExpected[i+1]; - int[] expected = actualAndExpected[i+2]; - int[] result = arrayUtil.merge(array1, array2); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, result)); - } - - } - - @Test - public void grow() throws Exception { - int[][] actualAndExpected = { - {}, {}, - {1}, {}, - {5}, {0,0,0,0,0}, - {0},{2,3,6}, - {3}, {2,3,6,0,0,0} - }; - - for (int i = 0; i < actualAndExpected.length; i += 3) { - int[] oldArray = actualAndExpected[i]; - int size = actualAndExpected[i+1][0]; - int[] expected = actualAndExpected[i+2]; - int[] newArray = arrayUtil.grow(oldArray, size); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, newArray)); - } - } - - @Test - public void fibonacci() throws Exception { - int[][] actualAndExpected = { - {0}, {}, - {1}, {}, - {2}, {1,1}, - {3}, {1,1,2}, - {4}, {1,1,2,3}, - {15}, {1,1,2,3,5,8,13}, - }; - - for (int i = 0; i < actualAndExpected.length; i += 2) { - int max = actualAndExpected[i][0]; - int[] expected = actualAndExpected[i+1]; - int[] actual = arrayUtil.fibonacci(max); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); - } - } - - @Test - public void getPrimes() throws Exception { - int[][] actualAndExpected = { - {-1}, {}, - {0}, {}, - {1}, {}, - {2}, {}, - {3}, {2}, - {4}, {2,3}, - {23}, {2,3,5,7,11,13,17,19}, - }; - - for (int i = 0; i < actualAndExpected.length; i += 2) { - int max = actualAndExpected[i][0]; - int[] expected = actualAndExpected[i+1]; - int[] actual = arrayUtil.getPrimes(max); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); - } - } - - @Test - public void getPerfectNumbers() throws Exception { - int[][] actualAndExpected = { - {-1}, {}, - {0}, {}, - {1}, {}, - {2}, {}, - {7}, {6}, - {30}, {6,28}, - {500}, {6,28,496}, - {10000}, {6,28,496,8128} - }; - - for (int i = 0; i < actualAndExpected.length; i += 2) { - int max = actualAndExpected[i][0]; - int[] expected = actualAndExpected[i+1]; - int[] actual = arrayUtil.getPerfectNumbers(max); - Assert.assertTrue("wrong index: " + String.valueOf(i), isArrayEqual(expected, actual)); - } - } - - @Test - public void join() throws Exception { - int[][] arrays = { - {}, - {3,8,9}, - {1}, - {0,0,0,0,0}, - {1,2,3,4,5} - }; - String[] separators = {"", "-", "+", "*", "00"}; - String[] expecteds = { - "", - "3-8-9", - "1", - "0*0*0*0*0", - "1002003004005" - }; - for (int i = 0; i < arrays.length; i++) { - int[] array = arrays[i]; - String separator = separators[i]; - String expected = expecteds[i]; - String actual = arrayUtil.join(array, separator); - Assert.assertTrue("wrong index: " + String.valueOf(i), expected.equals(actual)); - } - } - - private boolean isArrayEqual(int[] expected, int[] actual){ - if (expected.length != actual.length){ - System.out.println("expected.length != actual.length"); - System.out.println("expected: " + Arrays.toString(expected)); - System.out.println("actual: " + Arrays.toString(actual)); - return false; - } - - for (int i = 0; i < expected.length; i++) { - if (expected[i] != actual[i]){ - System.out.println("expected[i] != actual[i]"); - System.out.println("expected: " + Arrays.toString(expected)); - System.out.println("actual: " + Arrays.toString(actual)); - return false; - } - } - - return true; - } - -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java deleted file mode 100644 index dbbb80a91a..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package dataStruct.com.coderising.download; - -import dataStruct.com.coderising.download.DownloadThread; -import dataStruct.com.coderising.download.api.Connection; -import dataStruct.com.coderising.download.api.DownloadListener; -import dataStruct.com.coderising.download.impl.ConnectionManagerImpl; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; - -/** - * Created by songbao.yang on 2017/3/11. - */ -public class DownloadThreadTest { - - private DownloadThread downloadThread; - private final String url = "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=9bb90992550fd9f9bf17536f152cd42b/9a504fc2d5628535959cf4cf94ef76c6a6ef63db.jpg"; - private final String path = "D:"; - DownloadListener listener; - - @Before - public void setUp() throws Exception { - String threadName = "DownloadThreadTest"; - ConnectionManagerImpl connectionManager = new ConnectionManagerImpl(); - Connection connection = connectionManager.open(url); - File file = new File(path + File.separator + "meinv.jpg"); - int contentLength = connection.getContentLength(); - System.out.println(contentLength); - - Connection conn = connectionManager.open(url); - downloadThread = new DownloadThread(conn, 0, contentLength, file, listener); - downloadThread.setName(threadName); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void run() throws Exception { - downloadThread.run(); - } - -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coderising/download/FileDownloaderTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/download/FileDownloaderTest.java deleted file mode 100644 index cb5748f4e6..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coderising/download/FileDownloaderTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package dataStruct.com.coderising.download; - -import dataStruct.com.coderising.download.api.ConnectionManager; -import dataStruct.com.coderising.download.api.DownloadListener; -import dataStruct.com.coderising.download.impl.ConnectionManagerImpl; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class FileDownloaderTest { - boolean downloadFinished = false; - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testDownload() { - - String url = "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=9bb90992550fd9f9bf17536f152cd42b/9a504fc2d5628535959cf4cf94ef76c6a6ef63db.jpg"; - - FileDownloader downloader = new FileDownloader(url); - ConnectionManager cm = new ConnectionManagerImpl(); - downloader.setConnectionManager(cm); - downloader.setListener(new DownloadListener() { - public void notifyFinished() { - downloadFinished = true; - } - }); - downloader.execute(); - - // 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - //休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); - } - -} diff --git a/group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java deleted file mode 100644 index 967b4520a2..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package dataStruct.com.coderising.download.impl; - -import dataStruct.com.coderising.download.api.Connection; -import dataStruct.com.coderising.download.impl.ConnectionManagerImpl; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by songbao.yang on 2017/3/11. - */ -public class ConnectionImplTest { - - private Connection connection; - private final String URL = "https://ss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/image/h%3D200/sign=8e07ecabb7fb4316051f7d7a10a54642/5882b2b7d0a20cf482c772bf73094b36acaf997f.jpg"; - - @Before - public void setUp() throws Exception { - ConnectionManagerImpl connectionManager = new ConnectionManagerImpl(); - this.connection = connectionManager.open(URL); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void read() throws Exception { - byte[] read = connection.read(0, 100); - System.out.println(read); - } - - @Test - public void getContentLength() throws Exception { - int contentLength = connection.getContentLength(); - System.out.println(contentLength); - } - - @Test - public void close() throws Exception { - - } - -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coderising/litestruts/StrutsTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/litestruts/StrutsTest.java deleted file mode 100644 index bdb0334ae5..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coderising/litestruts/StrutsTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package dataStruct.com.coderising.litestruts; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - - -public class StrutsTest { - - @Test - public void testLoginActionSuccess() { - - String actionName = "login"; - - Map params = new HashMap(); - params.put("name","test"); - params.put("password","1234"); - - - View view = Struts.runAction(actionName,params); - - Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); - Assert.assertEquals("login successful", view.getParameters().get("message")); - } - - @Test - public void testLoginActionFailed() { - String actionName = "login"; - Map params = new HashMap(); - params.put("name","test"); - params.put("password","123456"); //密码和预设的不一致 - - View view = Struts.runAction(actionName,params); - - Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); - Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); - } -} diff --git a/group05/578505552/src/test/java/dataStruct/com/coding/basic/BinaryTreeNodeTest.java b/group05/578505552/src/test/java/dataStruct/com/coding/basic/BinaryTreeNodeTest.java deleted file mode 100644 index ee7ecd6e36..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coding/basic/BinaryTreeNodeTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package dataStruct.com.coding.basic; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by songbao.yang on 2017/2/28. - * - */ -public class BinaryTreeNodeTest { - - private BinaryTreeNode node; - - @Before - public void setUp() throws Exception { - node = new BinaryTreeNode(); - node.setData(100); - node.setLeft(null); - node.setRight(null); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void insert() throws Exception { - - for (int i = 0; i < 100; i++) { - int ele = (int)Math.floor(Math.random() * 200); - node.insert(ele); - } - } -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coding/basic/QueueTest.java b/group05/578505552/src/test/java/dataStruct/com/coding/basic/QueueTest.java deleted file mode 100644 index 856258a713..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coding/basic/QueueTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package dataStruct.com.coding.basic; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by songbao.yang on 2017/2/24. - */ -public class QueueTest { - - private static final int SIZE = 2000; - private Queue queue; - - @Before - public void setUp() throws Exception { - queue = new Queue(); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void enQueue() throws Exception { - for (int i = 0; i < SIZE; i++) { - queue.enQueue(i); - assertEquals(i+1, queue.size()); - } - } - - @Test - public void deQueue1() throws Exception { - enQueue(); - - int i = 0; - int startSize = queue.size(); - while (!queue.isEmpty()) { - assertEquals(startSize - i, queue.size()); - Object o = queue.deQueue(); - assertEquals(SIZE - i - 1, queue.size()); - Assert.assertEquals(i, o); - i++; - } - } - - @Test - public void deQueue2() throws Exception { - enQueue(); - int startSize = queue.size(); - - for (int i = 0; i < startSize; i++) { - queue.deQueue(); - assertEquals(startSize - 1, queue.size()); - queue.enQueue(i+1000); - assertEquals(startSize, queue.size()); - } - - } - - @Test - public void isEmpty() throws Exception { - - } - - @Test - public void size() throws Exception { - - } - -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coding/basic/StackTest.java b/group05/578505552/src/test/java/dataStruct/com/coding/basic/StackTest.java deleted file mode 100644 index c58643c31a..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coding/basic/StackTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package dataStruct.com.coding.basic; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by songbao.yang on 2017/2/24. - * - */ -public class StackTest { - - private Stack stack; - - public static final int SIZE = 100; - - @Before - public void setUp() throws Exception { - stack = new Stack(); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void push() throws Exception { - for (int i = 0; i < SIZE; i++) { - stack.push(i); - assertEquals(i+1, stack.size()); - } - System.out.println(); - } - - @Test - public void pop() throws Exception { - push(); - int beginSize = stack.size(); - for (int i = 0; i < beginSize; i++) { - Object ele = stack.pop(); - assertEquals(beginSize-i-1, stack.size()); - Assert.assertEquals(beginSize-i-1, ele); - } - } - - @Test - public void peek() throws Exception { - - } - - @Test - public void isEmpty() throws Exception { - - } - - @Test - public void size() throws Exception { - - } - -} \ No newline at end of file diff --git a/group05/578505552/src/test/java/dataStruct/com/coding/basic/linklist/LRUPageFrameTest.java b/group05/578505552/src/test/java/dataStruct/com/coding/basic/linklist/LRUPageFrameTest.java deleted file mode 100644 index ffeaa4a747..0000000000 --- a/group05/578505552/src/test/java/dataStruct/com/coding/basic/linklist/LRUPageFrameTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package dataStruct.com.coding.basic.linklist; - -import org.junit.Assert; - -import org.junit.Test; - - -public class LRUPageFrameTest { - - @Test - public void testAccess() { - LRUPageFrame frame = new LRUPageFrame(3); - frame.access(7); - frame.access(0); - frame.access(1); - Assert.assertEquals("1,0,7", frame.toString()); - frame.access(2); - Assert.assertEquals("2,1,0", frame.toString()); - frame.access(0); - Assert.assertEquals("0,2,1", frame.toString()); - frame.access(0); - Assert.assertEquals("0,2,1", frame.toString()); - frame.access(3); - Assert.assertEquals("3,0,2", frame.toString()); - frame.access(0); - Assert.assertEquals("0,3,2", frame.toString()); - frame.access(4); - Assert.assertEquals("4,0,3", frame.toString()); - } - -} diff --git a/group05/578505552/src/test/java/miniJvm/com/coderising/jvm/loader/ClassFileloaderTest.java b/group05/578505552/src/test/java/miniJvm/com/coderising/jvm/loader/ClassFileloaderTest.java deleted file mode 100644 index 97410772aa..0000000000 --- a/group05/578505552/src/test/java/miniJvm/com/coderising/jvm/loader/ClassFileloaderTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package miniJvm.com.coderising.jvm.loader; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class ClassFileloaderTest { - - static String path1 = "D:\\project\\Learn\\coding2017\\group05\\578505552\\target\\classes"; - static String path2 = "C:\\temp"; - - @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.com.coderising.jvm.loader.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1141, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "miniJvm.com.coderising.jvm.loader.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - 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 + + + diff --git a/group06/1378560653/article.txt b/group06/1378560653/article.txt index 42b64998ea..2957d8601c 100644 --- a/group06/1378560653/article.txt +++ b/group06/1378560653/article.txt @@ -1,5 +1,8 @@ +ÿ +-------------------------------------------------------------------- һƪ£http://blog.csdn.net/raymond120/article/details/57415472 ڶƪ£http://blog.csdn.net/raymond120/article/details/58043040 ƪ£http://blog.csdn.net/raymond120/article/details/60759278 ƪ£http://blog.csdn.net/raymond120/article/details/61937892 -ƪ£http://blog.csdn.net/raymond120/article/details/68665071 \ No newline at end of file +ƪ£http://blog.csdn.net/raymond120/article/details/68665071 +ƪ£http://blog.csdn.net/raymond120/article/details/68958532 \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group06/1378560653/mini-jvm/com/coderising/jvm/attr/CodeAttr.java b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..4580b092ea --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,116 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.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 attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex,attrLen, maxStack,maxLocals,codeLen,code,cmds); + + int exceptionTableLen = iter.nextU2ToInt(); + //TODO 处理exception + if(exceptionTableLen>0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.nextU2ToInt(); + + for(int x=1; x<=subAttrCount; x++){ + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(2); + //line item table + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } + else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } + else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } + else{ + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + 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 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 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 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/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.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/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..88f677b2c8 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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 index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.nextU2ToInt(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + 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/group06/1378560653/mini-jvm/com/coderising/jvm/attr/StackMapTable.java b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.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/group06/1378560653/mini-jvm/com/coderising/jvm/clz/AccessFlag.java b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassFile.java b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..d1cc66cd0c --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,111 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +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 m :methods){ + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + public Method getMainMethod(){ + return getMethod("main","([Ljava/lang/String;)V"); + } +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassIndex.java b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..e7c3dcaec8 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..6b8f2e6348 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,152 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private 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 getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/CommandParser.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..0cf09d34fa --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,164 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + +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) { + if((codes == null) || (codes.length() == 0) || (codes.length() % 2 )!=0 ) { + throw new RuntimeException("the original code is not correct."); + } //为什么必须是偶数呢? + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); //iter是codes的一个迭代器 + List cmds = new ArrayList(); + + while(iter.hasNext()){ + String opCode = iter.next2CharAsString(); + + if(opCode.equals(new_object)){ + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(invokespecial)){ + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(invokevirtual)){ + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(getfield)){ + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(getstatic)){ + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(putfield)){ + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(ldc)){ + LdcCmd cmd = new LdcCmd(clzFile, opCode); + + cmd.setOperand(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (opCode.equals(bipush)){ + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + + cmd.setOperand(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) + || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) + || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("sorry, the java instruction "+opCode+"has not been implemented."); + } + } + + calcuateOffset(cmds); + + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); //list.toArray(array); + 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/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..317f44e5bb --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + } + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..8c6b929ea5 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..bd2a47040f --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + } + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..d38cc283c8 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,86 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; + + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..5c3978777d --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + ConstantInfo info = 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; + + } + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..5b4de098e0 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,38 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo) this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + //压入操作数栈顶 + frame.getOprandStack().push(jo); + + } + +} + + diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..e2691a0276 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,146 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } + + + public int getLength(){ + return 1; + } + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..d7ae70e32f --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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; + } + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..43a628302b --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..0f5329a77b --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,66 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(){ + 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(){ + 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; + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ClassInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..ff85582159 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.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); + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..4066e59fc4 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantPool.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..b9cc66616b --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.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; + } + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..5765ee14aa --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.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); + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..971f7a5e21 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,63 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +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); + } + + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..25dbc21e7c --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.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); + + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..7782d6e61b --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/StringInfo.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f28a5502c5 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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); + + } + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/constant/UTF8Info.java b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..0bae70ca3c --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.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.visistUTF8(this); + + } + + + +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..4a6da2b702 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..a565b461ad --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,80 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.empty()){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + /* + * 把当前函数栈帧中的变量传递下一个函数栈帧局部变量表,相当于设置下一个函数栈帧的局部变量表,这个局部变量表的顺序相当于将栈右倒。 + * 加上1 是因为要把this也传递过去 + * init(name,age)->init(object(this),name,age) + */ + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/Heap.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/JavaObject.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MethodArea.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..42c90f5cfe --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,90 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + * 方法区: + * 1.存储类的数据,如字符串常量,数字常量,字段引用,方法引用,类引用及名称和类型 + * 2.存储方法字节码 + * + * 加载类到方法区: + * 将classloader加载到MethodArea + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); //HashMap + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + //非常简化的实现,类装载器可以是多个,这里简化实现 + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + ClassFile clz = this.findClassFile(className); + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MiniJVM.java b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..e4571306cd --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,48 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + /* + * 一.模拟Java命令的输入: + * 1.加载:classpath + * 2.找到:classname,系统需要找到这个类的main方法,执行其字节码 + * + * 二.执行过程: + * 1.加载类,将类加载到方法区 + * -工具:ClassFileLoader + * -目的地:方法区(MethodArea) + * --1.存储类的数据,如字符串常量,数字常量,字段引用,方法引用,类引用及名称和类型 + * --2.存储方法字节码 + * 2.获取类的main方法 + * -从方法区找 + * 3.执行main方法的字节码 + * -字节码命令(Command命令) + * -栈帧(StackFrame):Command对象要访问栈帧中的操作数栈,局部变量表 + * -堆(Heap):存放对象 + * + */ + ClassFileLoader loader = new ClassFileLoader(); + for(int i = 0; i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/field/Field.java b/group06/1378560653/mini-jvm/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..645016368e --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/field/Field.java @@ -0,0 +1,49 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 = pool.getUTF8String(nameIndex); + String desc = pool.getUTF8String(descriptorIndex); + + return name +":"+ desc; + } + + + public static Field parse(ClassFile clzFile,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attributeCount = iter.nextU2ToInt(); + + Field f = new Field(accessFlag, nameIndex, descIndex, clzFile.getConstantPool()); + + if(attributeCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java b/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..23860c17e8 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public String nextU4ToHexString() { + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + + 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 byte[] getBytes(int length) { + if(pos + length >= codes.length){ + throw new ArrayIndexOutOfBoundsException(); + } + byte[] data = Arrays.copyOfRange(codes, pos, pos+length); + pos = pos + length; + return data; + } + + public String nextUxToHexString(int len) { + byte[] temp = new byte[len]; + for(int i = 0; i < len; i++){ + temp[i] = codes[pos++]; + } + return Util.byteToHexString(temp).toLowerCase(); + } + + public void back(int i) { + pos -= i; + + } +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java b/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..c75ee71a19 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,136 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + +public class ClassFileLoader { + /* + * 1.加载文件路径 + * 2.加载.class文件 + * - clzFileName = classPath + "/" + className(.class文件) + * 3.将.class文件转换为字节数组 + * - clzFileName->byte[] codes + * 4.解析.class字节数组 + * - paser(codes) + */ + 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 getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } +} \ No newline at end of file diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java b/group06/1378560653/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..ec15d5a2e7 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,46 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.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 = "H:\\github\\coding2017\\group06\\1378560653\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} + diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java b/group06/1378560653/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..028161adc7 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + + + + } +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java b/group06/1378560653/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..01052e6d21 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,358 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.cmd.BiPushCmd; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.OneOperandCmd; +import com.coderising.jvm.cmd.TwoOperandCmd; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "H:\\github\\coding2017\\group06\\1378560653\\bin"; + static String path2 = "C:\\Temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + clzFile.print(); + } + + + + @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 = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + /* + * byte:有符号数(-128~127) + * byte[]:该数组是一个有符号的字节数组 + * byte[i] & 0xff:相当于取低8位 + */ + 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); + } + + /** + * 第四次JVM课应实现的测试用例 + */ + @Test + public void testByteCodeCommand(){ + { + Method initMethod = this.clzFile.getMethod("", "(Ljava/lang/String;I)V"); + ByteCodeCommand [] cmds = initMethod.getCmds(); + + assertOpCodeEquals("0: aload_0", cmds[0]); + assertOpCodeEquals("1: invokespecial #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/group06/1378560653/src/com/coderising/jvm/test/EmployeeV1.java b/group06/1378560653/mini-jvm/com/coderising/jvm/test/EmployeeV1.java similarity index 100% rename from group06/1378560653/src/com/coderising/jvm/test/EmployeeV1.java rename to group06/1378560653/mini-jvm/com/coderising/jvm/test/EmployeeV1.java diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java b/group06/1378560653/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..69f5f7b80d --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "H:\\github\\coding2017\\group06\\1378560653\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} diff --git a/group06/1378560653/mini-jvm/com/coderising/jvm/util/Util.java b/group06/1378560653/mini-jvm/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..d1e7ec9e64 --- /dev/null +++ b/group06/1378560653/mini-jvm/com/coderising/jvm/util/Util.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.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 clzPaths = new ArrayList(); - - public byte[] readBinaryCode(String className) { - String classDirName = className.replace('.', '\\')+".class"; - String clzpath = getClassPath()+"\\"+ classDirName; - try { - FileInputStream clz = new FileInputStream(clzpath); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - int flag = 0; - while((flag = clz.read())!=-1){ - baos.write(flag); - } - clz.close(); - return baos.toByteArray(); - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - - public void addClassPath(String path) { - File file = new File(path); - if(file.exists()){ - clzPaths.add(path); - } else { - throw new IllegalArgumentException("路径:"+path+"不存在"); - } - } - - - public String getClassPath(){ - if(clzPaths.isEmpty()){ - return " "; - } - - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < clzPaths.size(); i++) { - buf.append(clzPaths.get(i)); - if(i != (clzPaths.size() - 1)){ - buf.append(";"); - } - } - return buf.toString(); - } - -} \ No newline at end of file diff --git a/group06/1378560653/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group06/1378560653/src/com/coderising/jvm/test/ClassFileloaderTest.java deleted file mode 100644 index 3ace0974f5..0000000000 --- a/group06/1378560653/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.coderising.jvm.test; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coderising.jvm.loader.ClassFileLoader; - - -public class ClassFileloaderTest { - - - static String path1 = "H:\\github\\coding2017\\group06\\1378560653\\bin"; - static String path2 = "C:\\Temp"; - - - - @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 = "com.coderising.jvm.test.EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1056, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.coderising.jvm.test.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - 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 0){ - return false; - }else{ - return true; - } - } - - public int size(){ - return linkedlist.size(); - } -} diff --git a/group06/1378560653/src/com/coding/basic/Stack.java b/group06/1378560653/src/com/coding/basic/Stack.java deleted file mode 100644 index 37fb5f26b5..0000000000 --- a/group06/1378560653/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.array.ArrayList; - -public class Stack { - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - elementData.add(o); - } - - public Object pop(){ - if(!isEmpty()){ - return elementData.remove(size()-1); - }else{ - return null; - } - } - - public Object peek(){ - if(!isEmpty()){ - return elementData.get(size()-1); - }else{ - return null; - } - } - public boolean isEmpty(){ - if(size() > 0){ - return false; - }else{ - return true; - } - } - public int size(){ - return elementData.size(); - } -} diff --git a/group06/1378560653/src/com/coding/basic/array/ArrayList.java b/group06/1378560653/src/com/coding/basic/array/ArrayList.java index 9fd1e776cc..ab2c9d3f21 100644 --- a/group06/1378560653/src/com/coding/basic/array/ArrayList.java +++ b/group06/1378560653/src/com/coding/basic/array/ArrayList.java @@ -76,7 +76,7 @@ private ArrayListIterator(ArrayList arraylist) { } @Override public boolean hasNext() { - pos ++; + pos++; if(pos >= size){ return false; }else{ diff --git a/group06/1378560653/src/com/coding/basic/queue/CircleQueue.java b/group06/1378560653/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..f653816872 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,49 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +/** + * 用数组实现循环队列 + * @author kai + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return front == rear; + + } + + public int size() { + return (rear - front + DEFAULT_SIZE) % DEFAULT_SIZE; + } + + public void enQueue(E data) { + if((rear+1) % DEFAULT_SIZE == front){ + throw new IndexOutOfBoundsException("Queue overflow"); + } + rear = (rear+1) % DEFAULT_SIZE; + elementData[rear] = data; + } + + public E deQueue() { + if(isEmpty()){ + throw new NoSuchElementException("Queue underflow"); + } + + Object item = elementData[front]; + front = (front + 1) % DEFAULT_SIZE; + return (E) item; + } +} diff --git a/group06/1378560653/src/com/coding/basic/queue/Josephus.java b/group06/1378560653/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..bbb5e7aecd --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,38 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题:约瑟夫环 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * 实现方法: + * 1.将所有的人(0~N-1)入队 + * 2.0~M-1出队,再入队,将M剔出 + * 3.重复2,直到剩下最后一个人 + * @author kai + * + */ +public class Josephus { + + public static List execute(int n, int m){ + List result = new ArrayList<>(); + Queue queue = new Queue(); + + for(int i = 0; i < n; i++){ + queue.enQueue(i); + } + + while(queue.size() > 1){ + 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; + } + + public static void main(String[] args){ + Queue queue = new Queue<>(); + queue.enQueue(1); + queue.enQueue(2); + queue.enQueue(3); + queue.enQueue(4); + while(!queue.isEmpty()){ + System.out.println(queue.deQueue()); + } + } +} diff --git a/group06/1378560653/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group06/1378560653/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..d134fc6c80 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,54 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * @author kai + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + public int size() { + return stack1.size(); + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(isEmpty()){ + throw new NoSuchElementException("Queue underflow"); + } + + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + + E item = stack2.pop(); + + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + + return item; + } + + + + } + diff --git a/group06/1378560653/src/com/coding/basic/stack/QuickMinStack.java b/group06/1378560653/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..1fb5476be5 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack; + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author kai + * + */ +public class QuickMinStack { + class Node { + private int min; + private int data; + + public Node(int data){ + this.min = 0; + this.data = data; + } + } + + Stack stack = new Stack<>(); + + public void push(int data){ + Node node = new Node(data); + if(stack.isEmpty()){ + node.min = data; + } else { + if(data < stack.peek().min){ + node.min = data; + } else { + node.min = stack.peek().min; + } + } + stack.push(node); + } + public int pop(){ + return stack.pop().data; + } + public int findMin(){ + return stack.peek().min; + } + + public static void main(String[] args){ + QuickMinStack stack = new QuickMinStack(); + stack.push(5); + stack.push(7); + System.out.println(stack.findMin()); + stack.push(4); + System.out.println(stack.findMin()); + stack.pop(); + System.out.println(stack.findMin()); + stack.push(3); + System.out.println(stack.findMin()); + + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/Stack.java b/group06/1378560653/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..d30244dd35 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,37 @@ +package com.coding.basic.stack; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + if(!isEmpty()){ + return elementData.remove(size()-1); + }else{ + return null; + } + } + + public Object peek(){ + if(!isEmpty()){ + return elementData.get(size()-1); + }else{ + return null; + } + } + public boolean isEmpty(){ + if(size() > 0){ + return false; + }else{ + return true; + } + } + public int size(){ + return elementData.size(); + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/StackUtil.java b/group06/1378560653/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..bbbbf67411 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,145 @@ +package com.coding.basic.stack; + +import java.util.Stack; + +public class StackUtil { + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s.isEmpty()){ + return; + } + + Stack temp1 = new Stack<>(); + Stack temp2 = new Stack<>(); + + while(!s.isEmpty()){ + temp1.push(s.pop()); + } + + while(!temp1.isEmpty()){ + temp2.push(temp1.pop()); + } + + while(!temp2.isEmpty()){ + s.push(temp2.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s.isEmpty()){ + return; + } + + Stack temp = new Stack<>(); + + while(!s.isEmpty()){ + Object data = s.pop(); + if(o.equals(data)){ + continue; + } + temp.push(data); + } + + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if(s.isEmpty()){ + return new Object[0]; + } + + if(len >= s.size()){ + len = s.size(); + } + + Object[] result = new Object[len]; + + Stack temp = new Stack<>(); + int count = 0; + while(!s.isEmpty()){ + Object data = s.pop(); + temp.push(data); + result[count++] = data; + if(count == len){ + break; + } + } + + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + + return result; + } + /** + * 字符串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){ + if(s.length() == 0){ + return false; + } + + Stack temp1 = new Stack<>(); + Stack temp2 = new Stack<>(); + + for(int i = 0, j = s.length()-1; i <= j; i++,j--){ + temp1.push(s.charAt(i)); + temp2.push(s.charAt(j)); + } + + while(!temp1.isEmpty()&&!temp2.isEmpty()){ + char a = temp1.pop(); + char b = temp2.pop(); + if(a == '('){ + if(b != ')'){ + return false; + } + } + if(a == '[') { + if(b != ']'){ + return false; + } + } + if(a == '{'){ + if(b != '}'){ + return false; + } + } + } + return true; + } + + public static String toString(Stack s) { + StringBuffer buffer = new StringBuffer(); + buffer.append("["); + while(!s.isEmpty()){ + buffer.append(s.pop()); + if(s.size()!=0){ + buffer.append(","); + } + } + buffer.append("]"); + return buffer.toString(); + } +} \ No newline at end of file diff --git a/group06/1378560653/src/com/coding/basic/stack/StackUtilTest.java b/group06/1378560653/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..dd7a461ac4 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,82 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; +import java.util.Stack; +import org.junit.Assert; +import org.junit.Test; + +public class StackUtilTest { + + @Test + public void testReverse() { + Stack s = new Stack<>(); + StackUtil.reverse(s); + Assert.assertEquals("[]", s.toString()); + + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + StackUtil.reverse(s); + Assert.assertEquals("[1,2,3,4,5]", StackUtil.toString(s)); + } + @Test + public void testRemove() { + Stack s = new Stack<>(); + StackUtil.remove(s,3); + Assert.assertEquals("[]", s.toString()); + { + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + StackUtil.remove(s,3); + Assert.assertEquals("[5,4,2,1]", StackUtil.toString(s)); + } + { + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + StackUtil.remove(s,7); + Assert.assertEquals("[5,4,3,2,1]", StackUtil.toString(s)); + } + } + @Test + public void testGetTop() { + Stack s = new Stack<>(); + assertArrayEquals(new Object[0], StackUtil.getTop(s,3)); + + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + int[] expected = {5,4,3}; + Object[] result = StackUtil.getTop(s,3); + int[] actual = new int[result.length]; + for(int i = 0; i < result.length; i++){ + actual[i] = (int)result[i]; + } + + assertArrayEquals(expected, actual); + } + + @Test + public void testIsValidPairs(){ + String s1 = "([e{d}f])"; + assertTrue(StackUtil.isValidPairs(s1)); + + String s2 = "([b{x]y})"; + assertFalse(StackUtil.isValidPairs(s2)); + } +} + + diff --git a/group06/1378560653/src/com/coding/basic/stack/StackWithTwoQueues.java b/group06/1378560653/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..205381c2e1 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,66 @@ +package com.coding.basic.stack; + +import com.coding.basic.queue.Queue; + +/** + * 用两个队列来实现一个栈 + * @author kai + * + * @param + */ + +public class StackWithTwoQueues { + private Queue queue1; + private Queue queue2; + + public StackWithTwoQueues() { + queue1 = new Queue<>(); + queue2 = new Queue<>(); + + } + + public boolean isEmpty(){ + return queue1.size() == 0; + } + + public int size(){ + return queue1.size(); + } + + public void push(E data) { + queue1.enQueue(data); + } + + public E pop() { + if(isEmpty()){ + throw new RuntimeException("Stack is empty"); + } + + E item = null; + while(!queue1.isEmpty()){ + item = queue1.deQueue(); + if(!queue1.isEmpty()){ + queue2.enQueue(item); //最后一个入队的释放,不再放入第二个队列 + } + } + + while(!queue2.isEmpty()){ + queue1.enQueue(queue2.deQueue()); + } + return item; + } + + public static void main(String[] args){ + StackWithTwoQueues stack = new StackWithTwoQueues<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + while(!stack.isEmpty()){ + System.out.println(stack.pop()); + } + + } + + +} diff --git a/group06/1378560653/src/com/coding/basic/stack/TwoStackInOneArray.java b/group06/1378560653/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..b7c25c9a2f --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,134 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈,与循环队列类似,但相遇条件不同 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author kai + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private int p1 = 0; + private int p2 = data.length-1; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if(p1 == p2){ + data = grow(data, 10 , p2); + p2 += 10; + } + data[p1++] = o; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if(p1 <= 0){ + throw new RuntimeException("Stack1 is empty!"); + } + p1--; + Object result1 = data[p1]; + data[p1] = null; + return result1; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if(p1 <= 0){ + throw new RuntimeException("Stack1 is empty!"); + } + p1--; + Object result1 = data[p1]; + p1++; + return result1; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if(p1 == p2){ + data = grow(data, 10 , p2); + p2+=10; + } + data[p2--] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if(p2 >= data.length-1){ + throw new RuntimeException("Stack1 is empty!"); + } + p2++; + Object result2 = data[p2]; + data[p2] = null; + return result2; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if(p2 >= data.length-1){ + throw new RuntimeException("Stack1 is empty!"); + } + p2++; + Object result2 = data[p2]; + p2--; + return result2; + } + /* + * 扩容: + * 1.从p1与p2之间扩容,而不是直接在数组结束处扩容 + * 2.扩容之后,p2相应扩大size + * + */ + public static Object[] grow(Object[] src, int size, int p2){ + Object[] target = new Object[src.length + size]; + System.arraycopy(src, 0, target, 0, p2); + System.arraycopy(src, p2,target, p2+size, src.length-p2); + return target; + } + + public static void main(String[] args){ + TwoStackInOneArray stack = new TwoStackInOneArray(); + stack.push1(1); + stack.push1(2); + stack.push1(3); + stack.push1(4); + stack.push1(5); + stack.push1(6); + stack.push1(7); + stack.push1(8); + stack.push1(9); + stack.push2(9); + stack.push2(8); + stack.push2(7); + stack.push2(6); + stack.push2(5); + stack.push2(4); + stack.push2(3); + stack.push2(2); + stack.push2(1); + System.out.println(stack.peek1()); + System.out.println(stack.pop1()); + System.out.println(stack.pop1()); + System.out.println(stack.pop1()); + System.out.println("============"); + System.out.println(stack.peek2()); + System.out.println(stack.pop2()); + System.out.println(stack.pop2()); + System.out.println(stack.pop2()); + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expr/InfixExpr.java b/group06/1378560653/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..b081b056a6 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,98 @@ +package com.coding.basic.stack.expr; + +import java.util.Stack; + +/* + * 中序表达式求值 + * 1.只支持加减乘除,不支持括号 + * 2.表达式中只支持int,结果可能是float + * 3.用2个栈实现:一个运算符栈,一个操作数栈 + */ + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + int i = 0; + while(i < expr.length()){ + char c = expr.charAt(i); + if(isOperator(c)){ + if(opStack.isEmpty()){ + opStack.push(c); + } else { + char preOperator = opStack.peek(); + if(ComparePriority(c,preOperator) > 0){ + opStack.push(c); + } else { + float num2 = numStack.pop(); + float num1 = numStack.pop(); + numStack.push(calculate(opStack.pop(),num1,num2)); + opStack.push(c); + } + } + i++; + } + if(isNumber(c)){ + String str = String.valueOf(c); + i++; + while(i < expr.length() && isNumber(expr.charAt(i))){ + str += expr.charAt(i); + i++; + } + numStack.push(Float.parseFloat(str)); + } + } + + while(!opStack.isEmpty()){ + float num2 = numStack.pop(); + float num1 = numStack.pop(); + numStack.push(calculate(opStack.pop(),num1,num2)); + } + float result = numStack.pop(); + return result; + } + + private Float calculate(char c, float num1, float num2) { + if(c == '+'){ + return num1+num2; + } + if(c == '-'){ + return num1-num2; + } + if(c == '*'){ + return num1*num2; + } + if(c == '/'){ + return num1/num2; + } + return null; + } + + private int ComparePriority(char c, char preOperator) { + if((c == '/' || c == '*')&&(preOperator == '+' || preOperator == '-')){ + return 1; + } + return -1; + } + + private boolean isNumber(char c) { + if(c >= '0' && c <= '9'){ + return true; + } + return false; + } + + private boolean isOperator(char c) { + if(c == '+' || c == '-' || c == '*' ||c == '/'){ + return true; + } + return false; + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expr/InfixExprTest.java b/group06/1378560653/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20f52b4c63 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/InfixExpr.java b/group06/1378560653/src/com/coding/basic/stack/expression/InfixExpr.java new file mode 100644 index 0000000000..66aa2453fb --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/InfixExpr.java @@ -0,0 +1,80 @@ +package com.coding.basic.stack.expression; + +import java.util.List; +import java.util.Stack; + +/* + * 中序表达式求值 + * 1.开辟2个栈:操作数栈和运算符栈 + * 2.当token为操作数时,直接压入操作数栈 + * 3.当token为运算符时,若运算符栈为空,则直接压入,否则进行运算符优先级比较,优先级高,则直接压入栈,反之计算 + */ + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + } else { + Token pre = opStack.peek(); + if(token.hasHigherPriority(pre)){ + opStack.push(token); + } else { + float f2 = numStack.pop(); + float f1 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + opStack.push(token); + } + } + } + + if(token.isNumber()){ + numStack.push((float) token.getIntValue()); + } + } + + while(!opStack.isEmpty()){ + Token operator = opStack.pop(); + float f2 = numStack.pop(); + float f1 = numStack.pop(); + numStack.push(calculate(operator.value,f1,f2)); + } + + return numStack.pop(); + } + + private float calculate(String value, float f1, float f2) { + if(value.equals("+")){ + return f1 + f2; + } + + if(value.equals("-")){ + return f1 - f2; + } + + if(value.equals("*")){ + return f1 * f2; + } + + if(value.equals("/")){ + return f1 / f2; + } + + return -1; + } + + +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/InfixExprTest.java b/group06/1378560653/src/com/coding/basic/stack/expression/InfixExprTest.java new file mode 100644 index 0000000000..31f2be8856 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expression; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/InfixToPostfix.java b/group06/1378560653/src/com/coding/basic/stack/expression/InfixToPostfix.java new file mode 100644 index 0000000000..d667f24a1d --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/InfixToPostfix.java @@ -0,0 +1,49 @@ +package com.coding.basic.stack.expression; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + if(token.isNumber()){ + numStack.push(token); + } + + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + } else { + Token pre = opStack.peek(); + if(token.hasHigherPriority(pre)){ + opStack.push(token); + } else { + while(!opStack.isEmpty()){ + numStack.push(opStack.pop()); + } + opStack.push(token); + } + } + } + } + + List temp = new ArrayList<>(); + while(!numStack.isEmpty()){ + temp.add(numStack.pop()); + } + + List result = new ArrayList<>(); + for(int i = temp.size()-1; i >= 0; i--){ + result.add(temp.get(i)); + } + return result; + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExpr.java b/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExpr.java new file mode 100644 index 0000000000..61215eb027 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExpr.java @@ -0,0 +1,87 @@ +package com.coding.basic.stack.expression; + +import java.util.List; +import java.util.Stack; + +/* + * 后序表达式, 本身就是表达式计算的顺序 + * 后序表达式求值: + * 1.开辟2个栈:操作数栈和运算符栈 + * 2.当token为操作数时,检查操作数栈,若操作数栈为空,则压入栈中;否则,判断运算符栈是否为空,若不为空则压入栈中,否则计算 + * 3.当token为运算符时,检查运算符栈,若运算符栈为空,则压入栈中;否则,计算。 + */ +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 opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + } else { + float f2 = numStack.pop(); + float f1 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + opStack.push(token); + } + } + + if(token.isNumber()){ + if(numStack.isEmpty()){ + numStack.push((float) token.getIntValue()); + } else { + if (opStack.isEmpty()){ + numStack.push((float) token.getIntValue()); + } else { + float f2 = numStack.pop(); + float f1 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + numStack.push((float) token.getIntValue()); + } + } + } + } + while(!opStack.isEmpty()){ + float f2 = numStack.pop(); + float f1 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + } + + return numStack.pop(); + } + + private float calculate(String value, float f1, float f2) { + if(value.equals("+")){ + return f1 + f2; + } + + if(value.equals("-")){ + return f1 - f2; + } + + if(value.equals("*")){ + return f1 * f2; + } + + if(value.equals("/")){ + return f1 / f2; + } + + return -1; + } + + public static void main(String[] args){ + PostfixExpr expr = new PostfixExpr("6 5 2 3 + 8 * + 3 + *"); + System.out.println(expr.evaluate()); + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExprTest.java b/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExprTest.java new file mode 100644 index 0000000000..6f93405801 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/PostfixExprTest.java @@ -0,0 +1,42 @@ +package com.coding.basic.stack.expression; + + + +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() { + { + //6*(5+(2+3)*8+3) + 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/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExpr.java b/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExpr.java new file mode 100644 index 0000000000..832aa4feb3 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExpr.java @@ -0,0 +1,87 @@ +package com.coding.basic.stack.expression; + +import java.util.List; +import java.util.Stack; + +/* + * 前序表达式求值 + * 与后序表达式求值相反,相当于将后序表达式逆置,然后按照后续表达式的规则求值 + * + */ +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); + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(int i = tokens.size()-1; i>=0; i--){ + Token token = tokens.get(i); + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + } else { + float f1 = numStack.pop(); + float f2 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + opStack.push(token); + } + } + + if(token.isNumber()){ + if(numStack.isEmpty()){ + numStack.push((float) token.getIntValue()); + } else { + if (opStack.isEmpty()){ + numStack.push((float) token.getIntValue()); + } else { + float f1 = numStack.pop(); + float f2 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + numStack.push((float) token.getIntValue()); + } + } + } + } + + while(!opStack.isEmpty()){ + float f1 = numStack.pop(); + float f2 = numStack.pop(); + numStack.push(calculate(opStack.pop().value,f1,f2)); + } + + return numStack.pop(); + } + + private float calculate(String value, float f1, float f2) { + if(value.equals("+")){ + return f1 + f2; + } + + if(value.equals("-")){ + return f1 - f2; + } + + if(value.equals("*")){ + return f1 * f2; + } + + if(value.equals("/")){ + return f1 / f2; + } + + return -1; + } + + public static void main(String[] args){ + PrefixExpr expr = new PrefixExpr("-++6/*2 9 3 * 4 2 8"); + System.out.println(expr.evaluate()); + } +} diff --git a/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExprTest.java b/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExprTest.java new file mode 100644 index 0000000000..1fd728ea44 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack.expression; + +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/group06/1378560653/src/com/coding/basic/stack/expression/Token.java b/group06/1378560653/src/com/coding/basic/stack/expression/Token.java new file mode 100644 index 0000000000..0205e627ed --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/Token.java @@ -0,0 +1,56 @@ +package com.coding.basic.stack.expression; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.management.RuntimeErrorException; + +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 int getIntValue(){ + return Integer.valueOf(value).intValue(); + } + + 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/group06/1378560653/src/com/coding/basic/stack/expression/TokenParser.java b/group06/1378560653/src/com/coding/basic/stack/expression/TokenParser.java new file mode 100644 index 0000000000..f39ce4d0a0 --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack.expression; + +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/group06/1378560653/src/com/coding/basic/stack/expression/TokenParserTest.java b/group06/1378560653/src/com/coding/basic/stack/expression/TokenParserTest.java new file mode 100644 index 0000000000..671349412c --- /dev/null +++ b/group06/1378560653/src/com/coding/basic/stack/expression/TokenParserTest.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack.expression; +import static org.junit.Assert.*; + +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"); + + 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/group06/1454385822/.classpath b/group06/1454385822/.classpath index f68e6279c1..0449aa0e39 100644 --- a/group06/1454385822/.classpath +++ b/group06/1454385822/.classpath @@ -1,8 +1,12 @@ - - - - - - - - + + + + + + + + + + + + diff --git a/group06/1454385822/.project b/group06/1454385822/.project index 35750341bb..0788dbcaef 100644 --- a/group06/1454385822/.project +++ b/group06/1454385822/.project @@ -5,6 +5,11 @@ + + org.eclipse.wst.common.project.facet.core.builder + + + org.eclipse.jdt.core.javabuilder @@ -13,5 +18,6 @@ org.eclipse.jdt.core.javanature + org.eclipse.wst.common.project.facet.core.nature diff --git a/group06/1454385822/src/com/coding/basic/homework_02/litestruts/struts.xml b/group06/1454385822/src/com/coding/basic/homework_02/litestruts/struts.xml index 53f1245121..1fc9e357bf 100644 --- a/group06/1454385822/src/com/coding/basic/homework_02/litestruts/struts.xml +++ b/group06/1454385822/src/com/coding/basic/homework_02/litestruts/struts.xml @@ -1,11 +1,13 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - + + + + /jsp/homepage.jsp + /jsp/showLogin.jsp + + + /jsp/welcome.jsp + /jsp/error.jsp + \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AccessFlag.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AccessFlag.java new file mode 100644 index 0000000000..9854d93ba3 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AccessFlag.java @@ -0,0 +1,26 @@ +package com.coding.basic.homework_04.jvm.attr; + +public class AccessFlag { + + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flagValue) { + this.flagValue = flagValue; + } + + public boolean isPublicClass(){ + return (this.flagValue & 0x0001) != 0; + } + public boolean isFinalClass(){ + return (this.flagValue & 0x0010) != 0; + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AttributeInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..26cfa65b04 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.coding.basic.homework_04.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/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/CodeAttr.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..c82682e272 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/attr/CodeAttr.java @@ -0,0 +1,153 @@ +package com.coding.basic.homework_04.jvm.attr; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.cmd.ByteCodeCommand; +import com.coding.basic.homework_04.jvm.cmd.CommandParser; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.util.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo{ + + private int attrNameIndex; + private int attrLength; + private int maxStack; + private int maxLocals; + private int codeLen; + private String code; + private ByteCodeCommand[] cmds ; + + + + private ClassFile clzFile; + private LineNumberTable lineNumberTable; + private LocalVariableTable localVariableTable; + + public ByteCodeCommand[] getCmds() { + return cmds; + } + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code ,ByteCodeCommand[] cmds) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + this.cmds = cmds; + } + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); +// buffer.append("Code:").append(code).append("\n"); + for(int i=0;i 0){ + throw new RuntimeException("ExceptionTable has not been implemented"); + } + parseSubAttr(codeAttr, iterator, clzFile); + return codeAttr; + } + + private static void parseSubAttr(CodeAttr codeAttr, ByteCodeIterator iterator, ClassFile clzFile){ + int attributeCount = iterator.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(ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2ToInt(); + int attrLength = iter.nextU4ToInt(); + LineNumberTable table = new LineNumberTable(attrNameIndex, attrLength); + int lineNumberTableLength = iter.nextU2ToInt(); + 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 attrNameIndex = iter.nextU2ToInt(); + int attrLength = iter.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(attrNameIndex, attrLength); + int localVariableTableLength = iter.nextU2ToInt(); + for(int i=0; i fields = new ArrayList(); + private List methods = new ArrayList(); + + + public Method getMethod(String methodName, String paramAndReturnType){ + for(Method method : methods){ + String name = constantPool.getUTF8String(method.getNameIndex()); + String descriptor = constantPool.getUTF8String(method.getDescriptorIndex()); + if(name.equals(methodName) && descriptor.equals(paramAndReturnType)){ + return method; + } + } + + return null; + } + public Method getMainMethod(){ + for(Method method : methods){ + String name = constantPool.getUTF8String(method.getNameIndex()); + String descriptor = constantPool.getUTF8String(method.getDescriptorIndex()); + if(name.equals("main") && descriptor.equals("([Ljava/lang/String;)V")){ + return method; + } + } + return null; + } + + public void addMethod(Method method){ + methods.add(method); + } + + public List getMethods() { + return methods; + } + + public void addField(Field field){ + fields.add(field); + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + + + public ClassIndex getClzIndex() { + return clzIndex; + } + + + + public void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + + + public int getConstantNum() { + return ConstantNum; + } + + + + public void setConstantNum(int constantNum) { + ConstantNum = constantNum; + } + + + + public void print() { + System.out.println("MagicNumber: "+ MagicNumber); + System.out.println( "minorVersion" +minorVersion); + System.out.println("majorVersion" + majorVersion); + + } + + + + public String getMagicNumber() { + return MagicNumber; + } + + + + public void setMagicNumber(String magicNumber) { + MagicNumber = magicNumber; + } + + + + 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 ConstantPool getConstantPool() { + return constantPool; + } + + + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + + + + public List getFields() { + return fields; + } + + public String getClassName() { + ClassInfo clzInfo = (ClassInfo)constantPool.getConstantInfo(1); + String clzName = clzInfo.getClassName(); + return clzName; + } + public String getSuperClassName() { + ClassInfo clzInfo = (ClassInfo)constantPool.getConstantInfo(3); + String clzName = clzInfo.getClassName(); + return clzName; + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/clz/ClassFileParser.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/clz/ClassFileParser.java new file mode 100644 index 0000000000..ba3575a309 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/clz/ClassFileParser.java @@ -0,0 +1,134 @@ +package com.coding.basic.homework_04.jvm.clz; + +import java.io.UnsupportedEncodingException; + +import com.coding.basic.homework_04.jvm.attr.AccessFlag; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.field.Field; +import com.coding.basic.homework_04.jvm.info.ClassInfo; +import com.coding.basic.homework_04.jvm.info.FieldRefInfo; +import com.coding.basic.homework_04.jvm.info.MethodRefInfo; +import com.coding.basic.homework_04.jvm.info.NameAndTypeInfo; +import com.coding.basic.homework_04.jvm.info.NullConstantInfo; +import com.coding.basic.homework_04.jvm.info.StringInfo; +import com.coding.basic.homework_04.jvm.info.UTF8Info; +import com.coding.basic.homework_04.jvm.method.Method; +import com.coding.basic.homework_04.jvm.util.ByteCodeIterator; + +public class ClassFileParser { + + private ClassFile clzFile; + + private ConstantPool pool; + + public ClassFile parser(byte[] codes) { + ByteCodeIterator iterator = new ByteCodeIterator(codes); + clzFile = new ClassFile(); + clzFile.setMagicNumber(iterator.nextU4ToHexString()); + clzFile.setMinorVersion(iterator.nextU2ToInt()); + clzFile.setMajorVersion(iterator.nextU2ToInt()); + clzFile.setConstantNum(iterator.nextU2ToInt()); + + + + clzFile.setConstantPool(parserConstantPool(iterator)); + + + clzFile.setAccessFlag(new AccessFlag(iterator.nextU2ToInt())); + + parseClzIndex(clzFile, iterator); + + parseInterface(iterator); + + parseField(clzFile, iterator); + + parseMethod(clzFile, iterator); + + return clzFile; + } + + private void parseClzIndex(ClassFile clzFile, ByteCodeIterator iterator) { + ClassIndex clzIndex = new ClassIndex(); + clzIndex.setThisClassIndex(iterator.nextU2ToInt()); + clzIndex.setSuperClassIndex(iterator.nextU2ToInt()); + + clzFile.setClzIndex(clzIndex); + + } + + private void parseMethod(ClassFile clzFile, ByteCodeIterator iterator) { + int methodCount = iterator.nextU2ToInt(); + for(int i=0; i codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + +// public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/CommandParser.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..7ee414f8a8 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/CommandParser.java @@ -0,0 +1,146 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; + +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) { + //?为啥是大写的 + codes = codes.toUpperCase(); + + CommandIterator iterator = new CommandIterator(codes); + List commands = new ArrayList(); + while(iterator.hasNext()){ + String opCode = iterator.next2CharAsString(); + if(new_object.equals(opCode)){ + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(ldc.equals(opCode)){ + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(bipush.equals(opCode)){ + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(invokespecial.equals(opCode)){ + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(invokevirtual.equals(opCode)){ + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(getfield.equals(opCode)){ + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(putfield.equals(opCode)){ + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(getstatic.equals(opCode)){ + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iterator.next2CharAsInt()); + cmd.setOprand2(iterator.next2CharAsInt()); + commands.add(cmd); + }else if(dup.equals(opCode) || astore_1.equals(opCode) || aload_0.equals(opCode) || + aload_1.equals(opCode) || aload_2.equals(opCode) || iload.equals(opCode) || iload_1.equals(opCode)|| iload_2.equals(opCode) || iload_3.equals(opCode) || fload_3.equals(opCode) || + voidreturn.equals(opCode)){ + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + commands.add(cmd); + }else{ + throw new RuntimeException("sorry , the java instruction " + opCode + "has not implemented"); + } + } + //计算偏移量 + calcuateOffset(commands); + + ByteCodeCommand[] result = new ByteCodeCommand[commands.size()]; + commands.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(); + } + + } +} \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetFieldCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2ffe6d14a1 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,27 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + + + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetStaticFieldCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..a5876317fc --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,25 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + +} \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeSpecialCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..38f77637e0 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,27 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeVirtualCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..4eb977e204 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,26 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// } + + + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/LdcCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..227b3d6477 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/LdcCmd.java @@ -0,0 +1,35 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.info.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; + + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NewObjectCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..86b76c0a05 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,25 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NoOperandCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..8565eba0c6 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,29 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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; + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/OneOperandCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..65de0df3ae --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.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/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/PutFieldCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..ac3e4929cb --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,25 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.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); + } + +// @Override +// public void execute(StackFrame frame, ExecutionResult result) { +// +// +// } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/TwoOperandCmd.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..8057b9ec45 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coding.basic.homework_04.jvm.cmd; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.info.ClassInfo; +import com.coding.basic.homework_04.jvm.info.FieldRefInfo; +import com.coding.basic.homework_04.jvm.info.MethodRefInfo; + +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/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..df41a0dc70 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantInfo.java @@ -0,0 +1,41 @@ +package com.coding.basic.homework_04.jvm.constant; + +import com.coding.basic.homework_04.jvm.info.ClassInfo; +import com.coding.basic.homework_04.jvm.info.FieldRefInfo; +import com.coding.basic.homework_04.jvm.info.MethodRefInfo; +import com.coding.basic.homework_04.jvm.info.NameAndTypeInfo; +import com.coding.basic.homework_04.jvm.info.StringInfo; +import com.coding.basic.homework_04.jvm.info.UTF8Info; + +public abstract class ConstantInfo { + + public static final int CLASS_INFO = 7; + public static final int UTF8_INFO = 1; + public static final int STRING_INFO = 8; + public static final int FIELDREF_INFO = 9; + public static final int METHODREF_INFO = 10; + public static final int NAMEANDTYPE_INFO = 12; + + protected ConstantPool pool; + public ConstantInfo(){ + + } + public ConstantInfo(ConstantPool pool) { + this.pool = pool; + } + + public abstract int getType(); + + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantPool.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..261e5f5a15 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/constant/ConstantPool.java @@ -0,0 +1,33 @@ +package com.coding.basic.homework_04.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +import com.coding.basic.homework_04.jvm.info.UTF8Info; + +public class ConstantPool { + private List constantInfos = new ArrayList(); + + public ConstantPool() { + + } + + public void addConstantInfo(ConstantInfo info){ + constantInfos.add(info); + } + + public int getSize() { + return this.constantInfos.size() - 1; + } + + + public ConstantInfo getConstantInfo(int type) { + + return this.constantInfos.get(type); + } + + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/field/Field.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/field/Field.java new file mode 100644 index 0000000000..6c5463a748 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/field/Field.java @@ -0,0 +1,41 @@ +package com.coding.basic.homework_04.jvm.field; + +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.info.UTF8Info; +import com.coding.basic.homework_04.jvm.util.ByteCodeIterator; + +public class Field { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private ConstantPool constantPool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool constantPool) { + this.accessFlag = accessFlag; + this.descriptorIndex = descriptorIndex; + this.nameIndex = nameIndex; + this.constantPool = constantPool; + } + + public static Field parse(ConstantPool constantPool, ByteCodeIterator iterator) { + int accessFlag = iterator.nextU2ToInt(); + int nameIndex = iterator.nextU2ToInt(); + int descriptorIndex = iterator.nextU2ToInt(); + //TODO这里字段没有属性,没做解析工作 + int attributeCount = iterator.nextU2ToInt(); + Field field = new Field(accessFlag, nameIndex, descriptorIndex, constantPool); + + if(attributeCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + return field; + } + public String toString() { + String name = ((UTF8Info)constantPool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)constantPool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/ClassInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/ClassInfo.java new file mode 100644 index 0000000000..bd202dfb3d --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/ClassInfo.java @@ -0,0 +1,51 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class ClassInfo extends ConstantInfo { + + public ClassInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + public ClassInfo() { + // TODO Auto-generated constructor stub + } + + private int tag = ConstantInfo.CLASS_INFO; + + private int utf8Index; + + public int getTag() { + return tag; + } + + + public int getUtf8Index() { + return utf8Index; + } + + public void setUtf8Index(int name_index) { + this.utf8Index = name_index; + } + public String getClassName() { + int utf8Index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)pool.getConstantInfo(utf8Index); + return utf8Info.getValue(); + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } + + + + + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/FieldRefInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/FieldRefInfo.java new file mode 100644 index 0000000000..aa9ad43af1 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/FieldRefInfo.java @@ -0,0 +1,42 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class FieldRefInfo extends ConstantInfo{ + + public FieldRefInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + public FieldRefInfo() { + // TODO Auto-generated constructor stub + } + private int tag = ConstantInfo.FIELDREF_INFO; + private int clz_index; + private int nameAndType_index; + public int getClz_index() { + return clz_index; + } + public void setClz_index(int clz_index) { + this.clz_index = clz_index; + } + public int getNameAndType_index() { + return nameAndType_index; + } + public void setNameAndType_index(int nameAndType_index) { + this.nameAndType_index = nameAndType_index; + } + public int getTag() { + return tag; + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/MethodRefInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/MethodRefInfo.java new file mode 100644 index 0000000000..bbd3330f69 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/MethodRefInfo.java @@ -0,0 +1,45 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class MethodRefInfo extends ConstantInfo { + + public MethodRefInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + public MethodRefInfo() { + // TODO Auto-generated constructor stub + } + private int tag = ConstantInfo.METHODREF_INFO; + private int class_index; + private int nameAndType_index; + + public int getClass_index() { + return class_index; + } + public void setClass_index(int class_index) { + this.class_index = class_index; + } + public int getNameAndType_index() { + return nameAndType_index; + } + public void setNameAndType_index(int nameAndType_index) { + this.nameAndType_index = nameAndType_index; + } + public int getTag() { + return tag; + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NameAndTypeInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NameAndTypeInfo.java new file mode 100644 index 0000000000..51d2d98ea4 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NameAndTypeInfo.java @@ -0,0 +1,47 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class NameAndTypeInfo extends ConstantInfo { + + private int tag = ConstantInfo.NAMEANDTYPE_INFO; + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + public NameAndTypeInfo() { + // TODO Auto-generated constructor stub + } + + + 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 getTag() { + return tag; + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NullConstantInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NullConstantInfo.java new file mode 100644 index 0000000000..18c2b1d078 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/NullConstantInfo.java @@ -0,0 +1,27 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class NullConstantInfo extends ConstantInfo{ + + public NullConstantInfo(ConstantPool pool) { + super(pool); + // TODO Auto-generated constructor stub + } + + public NullConstantInfo() { + // TODO Auto-generated constructor stub + } + + @Override + public int getType() { + return -1; + } + + @Override + public void accept(Visitor visitor) { + + + } +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/StringInfo.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/StringInfo.java new file mode 100644 index 0000000000..f4228e649f --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/StringInfo.java @@ -0,0 +1,35 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class StringInfo extends ConstantInfo { + + public StringInfo(ConstantPool pool) { + super(pool); + } + public StringInfo() { + // TODO Auto-generated constructor stub + } + private int tag = ConstantInfo.STRING_INFO; + private int string_index; + public int getString_index() { + return string_index; + } + public void setString_index(int string_index) { + this.string_index = string_index; + } + public int getTag() { + return tag; + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/UTF8Info.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/UTF8Info.java new file mode 100644 index 0000000000..45a5ec4f45 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/info/UTF8Info.java @@ -0,0 +1,45 @@ +package com.coding.basic.homework_04.jvm.info; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; + +public class UTF8Info extends ConstantInfo{ + + private int tag = ConstantInfo.UTF8_INFO; + private int length; + private String value; + + public UTF8Info(ConstantPool pool) { + super(pool); + } + public UTF8Info() { + } + + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + + @Override + public String toString() { + return "UTF8Info [tag=" + tag + ", length=" + length + ", value=" + value +")]"; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + @Override + public int getType() { + return tag; + } + @Override + public void accept(Visitor visitor) { + visitor.visistUTF8(this); + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/loader/ClassFileLoader.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/loader/ClassFileLoader.java index e4d36e04c6..631fbf0db5 100644 --- a/group06/1454385822/src/com/coding/basic/homework_04/jvm/loader/ClassFileLoader.java +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/loader/ClassFileLoader.java @@ -7,6 +7,8 @@ import java.util.Arrays; import java.util.List; +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.clz.ClassFileParser; public class ClassFileLoader { @@ -62,11 +64,7 @@ private byte[] readFile(File file){ * @return */ private String getPath(String path ,String className){ - System.out.println(className); String [] ways = className.split("\\."); - for (String string : ways) { - System.out.println(string); - } StringBuilder builder = new StringBuilder(); builder.append(path); for (String string : ways) { @@ -75,7 +73,6 @@ private String getPath(String path ,String className){ builder.append(string); } builder.append(".class"); - System.out.println(builder.toString()); return builder.toString(); } @@ -107,8 +104,19 @@ public String getClassPath(){ return builder.toString(); } + public ClassFile loadClass(String className) { + byte[] codes = readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + ClassFile clzFile = parser.parser(codes); + return clzFile; + } + -} \ No newline at end of file +} + + + + \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/method/Method.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/method/Method.java new file mode 100644 index 0000000000..899427c304 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/method/Method.java @@ -0,0 +1,89 @@ +package com.coding.basic.homework_04.jvm.method; + +import com.coding.basic.homework_04.jvm.attr.AttributeInfo; +import com.coding.basic.homework_04.jvm.attr.CodeAttr; +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.cmd.ByteCodeCommand; +import com.coding.basic.homework_04.jvm.util.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private CodeAttr codeAttr; + private ClassFile clzFile; + + + public int getAccessFlag() { + return accessFlag; + } + + + public void setAccessFlag(int accessFlag) { + this.accessFlag = accessFlag; + } + + + public int getNameIndex() { + return nameIndex; + } + + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + + public int getDescriptorIndex() { + return descriptorIndex; + } + + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + + public void setCodeAttr(CodeAttr codeAttr) { + this.codeAttr = codeAttr; + } + + + private Method(int accessFlag, int nameIndex, int descriptorIndex, ClassFile clzFile){ + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.clzFile = clzFile; + } + + + public static Method parse(ClassFile clzFile, ByteCodeIterator iterator) { + int accessFlag = iterator.nextU2ToInt(); + int nameIndex = iterator.nextU2ToInt(); + int descriptorIndex = iterator.nextU2ToInt(); + Method method = new Method(accessFlag, nameIndex, descriptorIndex, clzFile); + int attributeCount = iterator.nextU2ToInt(); + if(attributeCount > 0){ + int attrNameIndex = iterator.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + if(AttributeInfo.CODE.equals(attrName)){ + iterator.back(2); + CodeAttr codeAttr = CodeAttr.parse(clzFile, iterator); + method.setCodeAttr(codeAttr); + } + } + + return method; + } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ClassFilePrinter.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..14fcf61930 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ClassFilePrinter.java @@ -0,0 +1,45 @@ +package com.coding.basic.homework_04.jvm.print; + +import com.coding.basic.homework_04.jvm.clz.ClassFile; +import com.coding.basic.homework_04.jvm.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 = "C:\\Users\\yanght\\Documents\\mygit\\coding2017-1\\group06\\1454385822\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coding.basic.homework_04.jvm.test.EmployeeV2"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ConstantPoolPrinter.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..08aaedcfe9 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,105 @@ +package com.coding.basic.homework_04.jvm.print; + +import com.coding.basic.homework_04.jvm.constant.ConstantInfo; +import com.coding.basic.homework_04.jvm.constant.ConstantInfo.Visitor; +import com.coding.basic.homework_04.jvm.constant.ConstantPool; +import com.coding.basic.homework_04.jvm.info.ClassInfo; +import com.coding.basic.homework_04.jvm.info.FieldRefInfo; +import com.coding.basic.homework_04.jvm.info.MethodRefInfo; +import com.coding.basic.homework_04.jvm.info.NameAndTypeInfo; +import com.coding.basic.homework_04.jvm.info.StringInfo; +import com.coding.basic.homework_04.jvm.info.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor consoleVisitor = new Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder builder = new StringBuilder(); + int stringIndex = info.getString_index(); + + builder.append("String #").append(stringIndex) + .append(" //" + pool.getUTF8String(stringIndex)); + + System.out.println(builder.toString()); + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder builder = new StringBuilder(); + int index1 = info.getIndex1(); + int index2 = info.getIndex2(); + + builder.append("NameAndType #").append(index1 +":#") + .append(index2) + .append(" //" + pool.getUTF8String(index1)) + .append(":" + pool.getUTF8String(index2)); + + System.out.println(builder.toString()); + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder builder = new StringBuilder(); + int clzIndex = info.getClass_index(); + int nameAndTypeIndex = info.getNameAndType_index(); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(clzIndex); + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)pool.getConstantInfo(nameAndTypeIndex); + + builder.append("MethodRef #").append(clzIndex+".#") + .append(nameAndTypeIndex) + .append(" //"+ clzInfo.getClassName()) + .append("." + pool.getUTF8String(nameAndTypeInfo.getIndex1()) + ":") + .append(pool.getUTF8String(nameAndTypeInfo.getIndex2())); + + System.out.println(builder.toString()); + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder builder = new StringBuilder(); + int clzIndex = info.getClz_index(); + int nameAndTypeIndex = info.getNameAndType_index(); + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(clzIndex); + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)pool.getConstantInfo(nameAndTypeIndex); + + builder.append("FieldRef #").append(clzIndex + ".#") + .append(nameAndTypeIndex) + .append(" //" + clzInfo.getClassName()) + .append("." + pool.getUTF8String(nameAndTypeInfo.getIndex1()) + ":") + .append(pool.getUTF8String(nameAndTypeInfo.getIndex2())); + + System.out.println(builder.toString()); + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder builder = new StringBuilder(); + builder.append("Class #").append(info.getUtf8Index()+" //") + .append(info.getClassName()); + System.out.println(builder.toString()); + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder builder = new StringBuilder(); + builder.append("Utf8 ").append(info.getValue()); + System.out.println(builder.toString()); + } + }; + + for(int i = 1; i <= pool.getSize(); i++){ + System.out.print("#" + i + " = "); + pool.getConstantInfo(i).accept(consoleVisitor); + } + + } +} diff --git a/group06/1454385822/src/com/coding/basic/homework_04/jvm/test/ClassFileloaderTest.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/test/ClassFileloaderTest.java index a0ba195077..89c199d990 100644 --- a/group06/1454385822/src/com/coding/basic/homework_04/jvm/test/ClassFileloaderTest.java +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/test/ClassFileloaderTest.java @@ -1,89 +1,355 @@ -package com.coding.basic.homework_04.jvm.test; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coding.basic.homework_04.jvm.loader.ClassFileLoader; - -public class ClassFileloaderTest { - - - static String path1 = "C:\\Users\\yanght\\Documents\\mygit\\coding2017-1\\group06\\1454385822\\bin"; - static String path2 = "D:\temp"; - - - - @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 = "com.coding.basic.homework_04.jvm.test.EmployeeV1"; -// String className = "EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1084, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.coding.basic.homework_04.jvm.test.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - 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.getClass_index()); + Assert.assertEquals(13, methodRef.getNameAndType_index()); + } + + { + 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.getClass_index()); + Assert.assertEquals(46, methodRef.getNameAndType_index()); + } + + { + 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/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/ByteCodeIterator.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/ByteCodeIterator.java new file mode 100644 index 0000000000..1e99d88145 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/ByteCodeIterator.java @@ -0,0 +1,55 @@ +package com.coding.basic.homework_04.jvm.util; + +import java.util.Arrays; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + public 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/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/Util.java b/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/Util.java new file mode 100644 index 0000000000..ce35c5a40d --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_04/jvm/util/Util.java @@ -0,0 +1,26 @@ +package com.coding.basic.homework_04.jvm.util; + +public class Util { + + public static int byteToInt(byte[] codes){ + String hexString = byteToHexString(codes); + return Integer.valueOf(hexString, 16).intValue(); + } + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExpr.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExpr.java new file mode 100644 index 0000000000..685e4050ea --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExpr.java @@ -0,0 +1,67 @@ +package com.coding.basic.homework_06.expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack numStack = new Stack(); + Stack opStack = new Stack(); + + for (Token token : tokens) { + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + }else{ + while(!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float float1 = numStack.pop(); + Float float2 = numStack.pop(); + Float result = getResult(float1, float2, prevOperator.toString()); + numStack.push(result); + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while(!opStack.isEmpty()){ + Token prevOperator = opStack.pop(); + Float float1 = numStack.pop(); + Float float2 = numStack.pop(); + Float result = getResult(float1, float2, prevOperator.toString()); + numStack.push(result); + } + + return numStack.pop(); + } + + private Float getResult(Float float1, Float float2, String operator){ + if(operator.equals("+")){ + return float1 + float2; + }else if(operator.equals("-")){ + return float2 - float1; + }else if(operator.equals("*")){ + return float1 * float2; + }else if(operator.equals("/")){ + return float2 / float1; + }else{ + throw new RuntimeException(operator + " is not supported"); + } + + + } + + +} \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExprTest.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExprTest.java new file mode 100644 index 0000000000..49014889ac --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.coding.basic.homework_06.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfix.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfix.java new file mode 100644 index 0000000000..387f0001f7 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfix.java @@ -0,0 +1,33 @@ +package com.coding.basic.homework_06.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + List infixToken = new TokenParser().parse(expr); + List posToken = new ArrayList(); + Stack stack = new Stack(); + + for (Token token : infixToken) { + if(token.isOperator()){ + while(!stack.empty() && !token.hasHigherPriority(stack.peek())){ + posToken.add(stack.pop()); + } + stack.push(token); + } + if(token.isNumber()){ + posToken.add(token); + } + } + while(!stack.isEmpty()){ + posToken.add(stack.pop()); + } + + return posToken; + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfixTest.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..b3a7661a20 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/InfixToPostfixTest.java @@ -0,0 +1,39 @@ +package com.coding.basic.homework_06.expr; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExpr.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExpr.java new file mode 100644 index 0000000000..9e20e78e99 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExpr.java @@ -0,0 +1,46 @@ +package com.coding.basic.homework_06.expr; + +import java.util.List; +import java.util.Stack; + +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 numStack = new Stack(); + + for(int i=0; i < tokens.size(); i++){ + if(tokens.get(i).isOperator()){ + float f1 = numStack.pop(); + float f2 = numStack.pop(); + numStack.push(getResult(f1, f2, tokens.get(i).value)); + }else + if(tokens.get(i).isNumber()){ + numStack.push(Float.valueOf(tokens.get(i).getIntValue())); + } + } + return numStack.pop(); + } + + private float getResult(float float1, float float2, String operator){ + if(operator.equals("+")){ + return float1 + float2; + }else if(operator.equals("-")){ + return float2 - float1; + }else if(operator.equals("*")){ + return float1 * float2; + }else if(operator.equals("/")){ + return float2 / float1; + }else{ + throw new RuntimeException(operator + " is not supported"); + } + } + + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExprTest.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExprTest.java new file mode 100644 index 0000000000..453349b6d8 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/PostfixExprTest.java @@ -0,0 +1,37 @@ +package com.coding.basic.homework_06.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/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExpr.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExpr.java new file mode 100644 index 0000000000..bafc6db694 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExpr.java @@ -0,0 +1,45 @@ +package com.coding.basic.homework_06.expr; + +import java.util.List; +import java.util.Stack; + + +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); + Stack numStack = new Stack(); + + for(int i=tokens.size()-1; i>=0; i--){ + if(tokens.get(i).isOperator()){ + float f1 = numStack.pop(); + float f2 = numStack.pop(); + numStack.push(getResult(f2, f1, tokens.get(i).value)); + }else + if(tokens.get(i).isNumber()){ + numStack.push(Float.valueOf(tokens.get(i).getIntValue())); + } + } + return numStack.pop(); + } + + private float getResult(float float1, float float2, String operator){ + if(operator.equals("+")){ + return float1 + float2; + }else if(operator.equals("-")){ + return float2 - float1; + }else if(operator.equals("*")){ + return float1 * float2; + }else if(operator.equals("/")){ + return float2 / float1; + }else{ + throw new RuntimeException(operator + " is not supported"); + } + } +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExprTest.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExprTest.java new file mode 100644 index 0000000000..54afaf1e6e --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/PrefixExprTest.java @@ -0,0 +1,44 @@ +package com.coding.basic.homework_06.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/group06/1454385822/src/com/coding/basic/homework_06/expr/Token.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/Token.java new file mode 100644 index 0000000000..59dca19bd7 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/Token.java @@ -0,0 +1,51 @@ +package com.coding.basic.homework_06.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("+", "-", "*", "/"); + public 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 int getIntValue(){ + return Integer.valueOf(value).intValue(); + } + + 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; + } + +} diff --git a/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParser.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParser.java new file mode 100644 index 0000000000..5447f608bc --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParser.java @@ -0,0 +1,54 @@ +package com.coding.basic.homework_06.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 = indexOfNextOperatorSpace(i, expr); + if(nextOperatorIndex == i){ + nextOperatorIndex = i + 1; + } + String value = expr.substring(i, nextOperatorIndex); + System.out.println(value); + Token token = new Token(Token.NUMBER, value); + tokens.add(token); + i = nextOperatorIndex; + }else if(Character.isSpaceChar(c)){ + i++; + continue; + }else{ + System.out.println("char :["+c+"] is not number or operator,ignore"); + i++; + } + } + return tokens; + } + + + private int indexOfNextOperatorSpace (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/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParserTest.java b/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParserTest.java new file mode 100644 index 0000000000..2be1d52989 --- /dev/null +++ b/group06/1454385822/src/com/coding/basic/homework_06/expr/TokenParserTest.java @@ -0,0 +1,39 @@ +package com.coding.basic.homework_06.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"); + + 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()); + } + +} \ No newline at end of file diff --git a/group06/263050006/article.txt b/group06/263050006/article.txt index 2eaa5b792f..f6a5e2ef49 100644 --- a/group06/263050006/article.txt +++ b/group06/263050006/article.txt @@ -1,2 +1,12 @@ -CPU、内存、硬盘、指令以及他们之间的关系 -https://zhuanlan.zhihu.com/p/25442061 \ No newline at end of file +第一次作业博客: +CPU、内存、硬盘、指令以及他们之间的关系 +https://zhuanlan.zhihu.com/p/25442061 +第二次作业博客: +为什么32位处理器只能配4G内存 +https://zhuanlan.zhihu.com/p/26174778 +第三次作业博客: +报文和帧 +https://zhuanlan.zhihu.com/p/26175504 +第四次作业博客: +依赖注入通俗解释 +https://zhuanlan.zhihu.com/p/26176550 diff --git a/group06/263050006/pom.xml b/group06/263050006/pom.xml new file mode 100644 index 0000000000..91c21f2b50 --- /dev/null +++ b/group06/263050006/pom.xml @@ -0,0 +1,63 @@ + + 4.0.0 + com.github.chaoswang + coding2017 + 0.0.1-SNAPSHOT + coding2017 + coding2017 + + coding2017/group06/263050006/src/main/java + coding2017/group06/263050006/src/test/java + + + coding2017/group06/263050006/src/main/java + + **/*.java + + + + + + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + + + + + junit + junit + 4.12 + test + + + + + org.apache.commons + commons-lang3 + 3.5 + + + + + commons-io + commons-io + 2.5 + + + + + jdom + jdom + 1.1 + + + + + \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/downloader/impl/ConnectionImpl.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/downloader/impl/ConnectionImpl.java index d3cd269ee1..ee9cd68c56 100644 --- a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/downloader/impl/ConnectionImpl.java +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/downloader/impl/ConnectionImpl.java @@ -40,7 +40,8 @@ public byte[] read(int startPos, int endPos) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int len = 0; int hasRead = 0; - while((len < currentSectionLength) && ((hasRead = is.read(buffer)) != -1)) { + while((len < currentSectionLength) && ((hasRead = is.read(buffer)) != -1)) { + System.out.println(buffer.length); bos.write(buffer, 0, hasRead); len += hasRead; } diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/ClassFileLoader.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/ClassFileLoader.java deleted file mode 100644 index 1b0b8f1514..0000000000 --- a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/ClassFileLoader.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.github.chaoswang.learning.java.jvm; - -import java.util.ArrayList; -import java.util.List; - -public class ClassFileLoader { - - private List clzPaths = new ArrayList(); - - public byte[] readBinaryCode(String className) { - - return null; - - } - - public void addClassPath(String path) { - - } - - public String getClassPath() { - return null; - } - -} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/AttributeInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..737a9d83db --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.github.chaoswang.learning.java.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/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/CodeAttr.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..f7157b9d3c --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/CodeAttr.java @@ -0,0 +1,50 @@ +package com.github.chaoswang.learning.java.jvm.attr; + +import com.github.chaoswang.learning.java.jvm.clz.ClassFile; +import com.github.chaoswang.learning.java.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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LineNumberTable.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..8f52a6feac --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LineNumberTable.java @@ -0,0 +1,45 @@ +package com.github.chaoswang.learning.java.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.github.chaoswang.learning.java.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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(ByteCodeIterator iter) { + + return null; + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableItem.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..4c4443a4d1 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableItem.java @@ -0,0 +1,49 @@ +package com.github.chaoswang.learning.java.jvm.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; + } +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableTable.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..c56aee7f26 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/LocalVariableTable.java @@ -0,0 +1,23 @@ +package com.github.chaoswang.learning.java.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.github.chaoswang.learning.java.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + + List items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + + return null; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/StackMapTable.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..3cb32df88b --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +package com.github.chaoswang.learning.java.jvm.attr; + +import com.github.chaoswang.learning.java.jvm.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/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/AccessFlag.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..02c11cc5d7 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/AccessFlag.java @@ -0,0 +1,26 @@ +package com.github.chaoswang.learning.java.jvm.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; + } + +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassFile.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..b6c9a423b7 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassFile.java @@ -0,0 +1,114 @@ +package com.github.chaoswang.learning.java.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.github.chaoswang.learning.java.jvm.constant.ClassInfo; +import com.github.chaoswang.learning.java.jvm.constant.ConstantPool; +import com.github.chaoswang.learning.java.jvm.field.Field; +import com.github.chaoswang.learning.java.jvm.method.Method; + +public class ClassFile { + + //ClassļĴΰ汾 + private int minorVersion; + //Classļ汾,Java SE 6.0Ӧ֧Java SE 5.0ıClassļṹ֮ + private int majorVersion; + + /** + * ClassļгҪ洢 ԼãҪַ + * finalֵijԵijʼֵȵȣҪ洢ͽӿڵȫ޶ƣ + * ֶεԼ Լ + * CONSTANT_Utf8_info,CONSTANT_Float_info,CONSTANT_Double_info + */ + private ConstantPool pool; + + //ʾ߽ӿڵķϢ + private AccessFlag accessFlag; + //ij + private ClassIndex clzIndex; + + //ֶαϢ + 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()); + + } + + private String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassIndex.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..572db1f6d8 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package com.github.chaoswang.learning.java.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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; + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ClassInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..f30e75f5df --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ClassInfo.java @@ -0,0 +1,34 @@ +package com.github.chaoswang.learning.java.jvm.constant; +/** + * CONSTANT_Class_info { + * u1 tag; + * u2 name_index; + * } + */ +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(); + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..1884cae795 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantInfo.java @@ -0,0 +1,32 @@ +package com.github.chaoswang.learning.java.jvm.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); + } + +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantPool.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..033b2de3da --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.github.chaoswang.learning.java.jvm.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 Object getSize() { + return this.constantInfos.size() - 1; + } +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/FieldRefInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..762f678545 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/FieldRefInfo.java @@ -0,0 +1,61 @@ +package com.github.chaoswang.learning.java.jvm.constant; +/** + * CONSTANT_Fieldref_info { + * u1 tag; + * u2 class_index; + * u2 name_and_type_index; + * } + */ +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(); + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/MethodRefInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f8f30a92cd --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/MethodRefInfo.java @@ -0,0 +1,62 @@ +package com.github.chaoswang.learning.java.jvm.constant; +/** + * CONSTANT_Methodref_info { + * u1 tag; + * u2 class_index; + * u2 name_and_type_index; + */ +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(); + } + +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NameAndTypeInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..bd91ec8aac --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,54 @@ +package com.github.chaoswang.learning.java.jvm.constant; +/** + * CONSTANT_NameAndType_info { + * u1 tag; + * u2 name_index; + * u2 descriptor_index; + * } + */ +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() + ")"; + } +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NullConstantInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..c1cca00185 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.github.chaoswang.learning.java.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/StringInfo.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..82c4be3245 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.github.chaoswang.learning.java.jvm.constant; +/** + * CONSTANT_String_info { + * u1 tag; + * u2 string_index; + */ +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); + } + +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/UTF8Info.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5950d094e7 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/constant/UTF8Info.java @@ -0,0 +1,45 @@ +package com.github.chaoswang.learning.java.jvm.constant; + +/** + * CONSTANT_Utf8_info { + * u1 tag; + * u2 length; + * u1 bytes[length]; + * } + */ +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; + } + +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/field/Field.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/field/Field.java new file mode 100644 index 0000000000..c0ef09f88a --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/field/Field.java @@ -0,0 +1,31 @@ +package com.github.chaoswang.learning.java.jvm.field; + +import com.github.chaoswang.learning.java.jvm.constant.ConstantPool; +import com.github.chaoswang.learning.java.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ByteCodeIterator.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..8cf2374114 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,55 @@ +package com.github.chaoswang.learning.java.jvm.loader; + +import java.util.Arrays; + +import com.github.chaoswang.learning.java.jvm.util.Util; + +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; + } +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileLoader.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..8ac7e8573d --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileLoader.java @@ -0,0 +1,116 @@ +package com.github.chaoswang.learning.java.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.github.chaoswang.learning.java.jvm.clz.ClassFile; + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + // String path = className.replaceAll("\\.", "/"); + // õķ + 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 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); + + } + + public void addClassPath(String path) { + // ѾӹIJҪټ + if (clzPaths.contains(path)) { + return; + } + clzPaths.add(path); + } + + // ------------------------------backup------------------------ + public String getClassPath_V1() { + StringBuffer sb = new StringBuffer(); + for (String clzPath : clzPaths) { + sb.append(clzPath).append(";"); + } + String classPath = sb.toString(); + return classPath.substring(0, classPath.length() - 1); + } + + // ȡһ.classļǰ4ֽڣ תʮַDzǣCAFEBABE + private byte[] readClassFile_V1(String filePath) { + BufferedInputStream bis = null; + ByteArrayOutputStream bos = null; + try { + bis = new BufferedInputStream(new FileInputStream(filePath)); + bos = new ByteArrayOutputStream(); + byte[] bbuf = new byte[1024];// ˼ǣܶ1024Ҳܲ1024 + int index = 0; + + while ((index = bis.read(bbuf)) != -1) { + // readڶĩβǰ˷һֱѭʵֻӡһ + System.out.println(bbuf.length); + bos.write(bbuf, 0, index); + } + return bos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (bos != null) { + try { + bos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileParser.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..3b133dba93 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/loader/ClassFileParser.java @@ -0,0 +1,74 @@ +package com.github.chaoswang.learning.java.jvm.loader; + +import com.github.chaoswang.learning.java.jvm.clz.AccessFlag; +import com.github.chaoswang.learning.java.jvm.clz.ClassFile; +import com.github.chaoswang.learning.java.jvm.clz.ClassIndex; +import com.github.chaoswang.learning.java.jvm.constant.ClassInfo; +import com.github.chaoswang.learning.java.jvm.constant.ConstantPool; +import com.github.chaoswang.learning.java.jvm.constant.UTF8Info; + +public class ClassFileParser { + + + public ClassFile parse(byte[] codes) { + ByteCodeIterator codeIterator = new ByteCodeIterator(codes); + ClassFile classFile = new ClassFile(); + //ħ + codeIterator.getBytes(4); + classFile.setMinorVersion(codeIterator.nextU2ToInt()); + classFile.setMajorVersion(codeIterator.nextU2ToInt()); + + return classFile; + } + + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + //أصijǶ٣ + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + + return null; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + ConstantPool pool = new ConstantPool(); + ClassInfo classInfo = new ClassInfo(pool); + //classInfo tagֵ + iter.nextU1toInt(); + classInfo.setUtf8Index(iter.nextU2ToInt()); + pool.addConstantInfo(classInfo); + + UTF8Info utf8Info = new UTF8Info(pool); + //UTF8Info tagֵ + iter.nextU1toInt(); + //UTF8Info lengthֵ + int length = iter.nextU2ToInt(); + utf8Info.setLength(length); + utf8Info.setValue(iter.nextUxToHexString(length)); + pool.addConstantInfo(utf8Info); + + classInfo = new ClassInfo(pool); + //classInfo tagֵ + iter.nextU1toInt(); + classInfo.setUtf8Index(iter.nextU2ToInt()); + pool.addConstantInfo(classInfo); + + for(int i=0;i<8;i++){ + utf8Info = new UTF8Info(pool); + //UTF8Info tagֵ + iter.nextU1toInt(); + //UTF8Info lengthֵ + length = iter.nextU2ToInt(); + utf8Info.setLength(length); + utf8Info.setValue(iter.nextUxToHexString(length)); + pool.addConstantInfo(utf8Info); + } + + return pool; + } + +} \ No newline at end of file diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/method/Method.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/method/Method.java new file mode 100644 index 0000000000..c55cb5ac25 --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/method/Method.java @@ -0,0 +1,51 @@ +package com.github.chaoswang.learning.java.jvm.method; + +import com.github.chaoswang.learning.java.jvm.attr.CodeAttr; +import com.github.chaoswang.learning.java.jvm.clz.ClassFile; +import com.github.chaoswang.learning.java.jvm.loader.ByteCodeIterator; + +public class Method { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + + + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + return null; + + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/util/Util.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/util/Util.java new file mode 100644 index 0000000000..f74531ca2d --- /dev/null +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/jvm/util/Util.java @@ -0,0 +1,22 @@ +package com.github.chaoswang.learning.java.jvm.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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} diff --git a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/stack/StackUtil.java b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/stack/StackUtil.java index d5d7ecc223..7f2c30d1f1 100644 --- a/group06/263050006/src/main/java/com/github/chaoswang/learning/java/stack/StackUtil.java +++ b/group06/263050006/src/main/java/com/github/chaoswang/learning/java/stack/StackUtil.java @@ -1,13 +1,37 @@ package com.github.chaoswang.learning.java.stack; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + public class StackUtil { + + public static void addToBottom(Stack s, Integer value) { + Stack tmpStack = new Stack(); + while(!s.empty()){ + tmpStack.push(s.pop()); + } + s.push(value); + while(!tmpStack.empty()){ + s.push(tmpStack.pop()); + } + } /** * ջеԪInteger, ջջ : 5,4,3,2,1 ø÷ ԪشΪ: 1,2,3,4,5 * ע⣺ֻʹStackĻpush,pop,peek,isEmpty ʹһջ */ - public static void reverse(Stack s) { - + public static void reverse(Stack s) { + Stack tmpStack = new Stack(); + while(!s.empty()){ + tmpStack.push(s.pop()); + } + while(!tmpStack.empty()){ + StackUtil.addToBottom(s, tmpStack.pop()); + } } /** @@ -15,8 +39,21 @@ public static void reverse(Stack s) { * * @param o */ - public static void remove(Stack s, Object o) { - + public static void remove(Stack s, Object o) { + if(o == null){ + return; + } + Stack tmpStack = new Stack(); + while(!s.empty()){ + Integer poped = s.pop(); + if(o.equals(poped)){ + break; + } + tmpStack.push(poped); + } + while(!tmpStack.empty()){ + s.push(tmpStack.pop()); + } } /** @@ -27,7 +64,21 @@ public static void remove(Stack s, Object o) { * @return */ public static Object[] getTop(Stack s, int len) { - return null; + int stackSize = s.size(); + if(len > stackSize || len <= 0){ + throw new IllegalArgumentException("parameter len illegal"); + } + List ret = new ArrayList(); + Stack tmpStack = new Stack(); + for(int i=0;i map = new HashMap(); + map.put(')', '('); + map.put(']', '['); + map.put('}', '{'); + List bracketList = Arrays.asList('(', ')','[', ']','{', '}'); + Stack tmpStack = new Stack(); + for(char c : s.toCharArray()){ + if(bracketList.contains(c)){ + tmpStack.push(c); + } + } + //ŵĸż϶ɶ + if(tmpStack.size()%2 != 0){ + return false; + } + Stack tmpStack2 = new Stack(); + int tmpSize = tmpStack.size(); + 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ӦʵֵIJ + */ + @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); + } + } \ No newline at end of file diff --git a/group06/263050006/src/test/java/com/github/chaoswang/learning/java/stack/StackUtilTest.java b/group06/263050006/src/test/java/com/github/chaoswang/learning/java/stack/StackUtilTest.java new file mode 100644 index 0000000000..cce5434964 --- /dev/null +++ b/group06/263050006/src/test/java/com/github/chaoswang/learning/java/stack/StackUtilTest.java @@ -0,0 +1,76 @@ +package com.github.chaoswang.learning.java.stack; + +import java.util.Stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddToBottom() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrame.java b/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..756de196c5 --- /dev/null +++ b/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrame.java @@ -0,0 +1,201 @@ +package com.ecust.common.linklist; + +public class LRUPageFrame { + + + + private static class Node { + + + + Node prev; + + Node next; + + int pageNum; + + + + Node() { + + } + + + + Node(int pageNum){ + + this.pageNum = pageNum; + + } + + } + + + + private int capacity; + + private int size; + + + + private Node first;// 链表头 + + private Node last;// 链表尾 + + + + + + public LRUPageFrame(int capacity) { + + + + this.capacity = capacity; + + + + } + + + + /** + + * 获取缓存中对象 + + * + + * @param pageNum + + * @return + + */ + + public void access(int pageNum) { + + //先遍历,看是否已存在缓存中 + + if (first != null) { + + Node node = first; + + while (node != null){ + + if (node.pageNum == pageNum) { + + if (node.prev != null) { + + node.prev.next = node.next; + + if (node.next != null) { + + node.next.prev = node.prev; + + } else { + + last = node.prev; + + } + + node.next = first; + + node.prev = null; + + first.prev = node; + + first = node; + + } + + return; + + } + + node = node.next; + + } + + } + + //遍历不到,插入缓存中,并去除最少用的缓存 + + if (last == null) { + + if (!(capacity > 0)) { + + return; + + } + + //一开始没有缓存的边界条件 + + last = new Node(pageNum); + + first = last; + + size++; + + return; + + } + + Node node = new Node(pageNum); + + node.next = first; + + first.prev = node; + + first = node; + + size++; + + if (size > capacity) { + + //缓存已满,去除最少用缓存 + + Node node2 = last.prev; + + node2.next = null; + + last = node2; + + size--; + + } + + } + + + + + + + + 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/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrameTest.java b/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..9680f6c7be --- /dev/null +++ b/group06/949319266/jvm1/src/com/ecust/common/linklist/LRUPageFrameTest.java @@ -0,0 +1,67 @@ +package com.ecust.common.linklist; + +import org.junit.Assert; + + + +import org.junit.Test; + + + + + +public class LRUPageFrameTest { + + + + @Test + + public void testAccess() { + + LRUPageFrame frame = new LRUPageFrame(3); + + frame.access(7); + + frame.access(7); + + Assert.assertEquals("7", frame.toString()); + + frame.access(0); + + frame.access(0); + + Assert.assertEquals("0,7", frame.toString()); + + frame.access(1); + + Assert.assertEquals("1,0,7", frame.toString()); + + frame.access(2); + + Assert.assertEquals("2,1,0", frame.toString()); + + frame.access(0); + + Assert.assertEquals("0,2,1", frame.toString()); + + frame.access(0); + + Assert.assertEquals("0,2,1", frame.toString()); + + frame.access(3); + + Assert.assertEquals("3,0,2", frame.toString()); + + frame.access(0); + + Assert.assertEquals("0,3,2", frame.toString()); + + frame.access(4); + + Assert.assertEquals("4,0,3", frame.toString()); + + } + + + +} \ No newline at end of file diff --git a/group06/949319266/jvm2/src/com/ecust/Util/Stack.java b/group06/949319266/jvm2/src/com/ecust/Util/Stack.java new file mode 100644 index 0000000000..f5a7edb537 --- /dev/null +++ b/group06/949319266/jvm2/src/com/ecust/Util/Stack.java @@ -0,0 +1,77 @@ +package com.ecust.Util; + +import org.xukai.common.ArrayList; + + + +import java.util.EmptyStackException; + + + +public class Stack { + + + + private ArrayList elementData = new ArrayList(); + + + + public void push(Object o){ + + elementData.add(o); + + } + + + + public Object pop(){ + + if (isEmpty()) { + + throw new EmptyStackException(); + + } + + return elementData.remove(elementData.size()-1); + + } + + + + public Object peek(){ + + if (isEmpty()) { + + throw new EmptyStackException(); + + } + + return elementData.get(elementData.size()-1); + + } + + + + public boolean isEmpty(){ + + return elementData.size() == 0; + + } + + + + public int size(){ + + return elementData.size(); + + } + + + + public void display() { + + elementData.display(); + + } + +} diff --git a/group06/949319266/jvm2/src/com/ecust/Util/StackUtil.java b/group06/949319266/jvm2/src/com/ecust/Util/StackUtil.java new file mode 100644 index 0000000000..cc0c247394 --- /dev/null +++ b/group06/949319266/jvm2/src/com/ecust/Util/StackUtil.java @@ -0,0 +1,291 @@ +package com.ecust.Util; + +import com.google.common.base.Preconditions; + +import com.google.common.collect.Maps; + +import org.junit.Assert; + +import org.junit.Test; + + + +import java.util.HashMap; + +import java.util.regex.Pattern; + + + +public class StackUtil { + + + + + + /** + + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + + */ + + public static void reverse(Stack s) { + + Stack stack1 = new Stack(); + + while (!s.isEmpty()){ + + stack1.push(s.pop()); + + } + + Stack stack2 = new Stack(); + + while (!stack1.isEmpty()){ + + stack2.push(stack1.pop()); + + } + + while (!stack2.isEmpty()){ + + s.push(stack2.pop()); + + } + + } + + @Test + + public void testReverse(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + reverse(stack); + + stack.display(); + + } + + + + /** + + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + + * + + * @param o + + */ + + public static void remove(Stack s,Object o) { + + Stack stack = new Stack(); + + while (!s.isEmpty()){ + + if (!s.peek().equals(o)) { + + stack.push(s.pop()); + + } else { + + s.pop(); + + } + + } + + while (!stack.isEmpty()){ + + s.push(stack.pop()); + + } + + } + + + + @Test + + public void testRemove(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + remove(stack,3); + + stack.display(); + + } + + + + + + /** + + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + + * @param len + + * @return + + */ + + public static Object[] getTop(Stack s,int len) { + + Preconditions.checkArgument(len > 0); + + Stack stack = new Stack(); + + Object[] objects = new Object[Math.min(len,s.size())]; + + for (int i = 0; i < len; i++) { + + if (s.isEmpty()) { + + break; + + } + + objects[i] = s.pop(); + + stack.push(objects[i]); + + } + + while (!stack.isEmpty()){ + + s.push(stack.pop()); + + } + + return objects; + + } + + + + @Test + + public void testGetTop(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + Object[] objects = getTop(stack, 6); + + for (int i = 0; i < objects.length; i++) { + + System.out.println(objects[i]); + + } + + } + + /** + + * 字符串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){ + + HashMap map = Maps.newHashMap(); + + map.put("}","{"); + + map.put(")","("); + + map.put("]","["); + + Stack stack = new Stack(); + + char[] chars = s.toCharArray(); + + for (int i = 0; i < chars.length; i++) { + + if (Pattern.matches("[\\[({]{1}", chars[i]+"")) { + + stack.push(chars[i]); + + } + + if (Pattern.matches("[\\])}]{1}", chars[i]+"") && !map.get(chars[i]+"").equals(""+stack.pop())) { + + return false; + + } + + } + + return true; + + } + + + + @Test + + public void testIsValidPairs(){ + + Assert.assertTrue(isValidPairs("[d(a)](da){21}")); + + Assert.assertTrue(!isValidPairs("[d(a{)}](da){21}")); + + } + + + + + +} diff --git a/group06/949319266/jvm2/src/com/ecust/Util/StackUtilTest.java b/group06/949319266/jvm2/src/com/ecust/Util/StackUtilTest.java new file mode 100644 index 0000000000..63f68e849d --- /dev/null +++ b/group06/949319266/jvm2/src/com/ecust/Util/StackUtilTest.java @@ -0,0 +1,117 @@ +package com.ecust.Util; + +import org.junit.Assert; + +import org.junit.Test; + + + +public class StackUtilTest { + + + + + + @Test + + public void testReverse(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + StackUtil.reverse(stack); + + stack.display(); + + } + + + + + + @Test + + public void testRemove(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + StackUtil.remove(stack,3); + + stack.display(); + + } + + + + + + @Test + + public void testGetTop(){ + + Stack stack = new Stack(); + + stack.push(1); + + stack.push(2); + + stack.push(3); + + stack.push(4); + + stack.push(5); + + stack.display(); + + Object[] objects = StackUtil.getTop(stack, 8); + + for (int i = 0; i < objects.length; i++) { + + System.out.println(objects[i]); + + } + + Assert.assertEquals(5,objects.length); + + } + + + + @Test + + public void testIsValidPairs(){ + + Assert.assertTrue(StackUtil.isValidPairs("[d(a)](da){21}")); + + Assert.assertTrue(!StackUtil.isValidPairs("[d(a{)}](da){21}")); + + } + + + + + +} diff --git a/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr.java b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr.java new file mode 100644 index 0000000000..d2cd280dda --- /dev/null +++ b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr.java @@ -0,0 +1,5 @@ +package com.ecust.jvm3; + +public class InfixExpr { + +} diff --git a/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr2.java b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr2.java new file mode 100644 index 0000000000..7a7ee922dd --- /dev/null +++ b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExpr2.java @@ -0,0 +1,194 @@ +package com.ecust.jvm3; + +import java.util.HashMap; +import java.util.Stack; + + + +public class InfixExpr2 { + + + + public static enum TypeToken { + + + + add('+',0),substruct('-',1),devide('/',3),plus('*',2); + + + + TypeToken(char token, Integer priority) { + + this.token = token; + + this.priority = priority; + + } + + + + private char token; + + + + private Integer priority; + + } + + + + String expr = null; + + + + public InfixExpr2(String expr) { + + this.expr = expr; + + } + +//3*20+12*5-40/2 + + public Double evaluate() { + + HashMap map = new HashMap<>(); + + map.put("+",0); + + map.put("-",1); + + map.put("/",3); + + map.put("*",2); + + + + + + Stack tokenStack = new Stack(); + + Stack numStack = new Stack(); + + char[] chars = expr.toCharArray(); + + boolean isNem = true; + + for (int i = 0; i < expr.length(); i++) { + + String token = (expr.charAt(i)) + ""; + + Integer priprity = map.get(token); + + if (priprity != null) { + + //表示是运算符 + + if (!tokenStack.isEmpty() && priprity < map.get(tokenStack.peek())) { + + Float num2 = Float.valueOf(numStack.pop().toString()); + + Float num1 = Float.valueOf(numStack.pop().toString()); + + String pop = tokenStack.pop()+""; + + if (pop.equals("-")) { + + numStack.push(num1 - num2); + + } else if (pop.equals("*")){ + + numStack.push(num1 * num2); + + } else if (pop.equals("/")){ + + numStack.push(num1 / num2); + + } else { + + throw new RuntimeException(); + + } + + + + } + + tokenStack.push(token); + + isNem = true; + + } else if(token.matches("\\d{1}")) { + + //表示是数字 + + if (isNem) { + + numStack.push(token); + + } else { + + numStack.push(numStack.pop().toString() + token); + + } + + isNem = false; + + } else { + + throw new RuntimeException(); + + } + + } + + while (!tokenStack.isEmpty()) { + + System.out.println(tokenStack.size()); + + if (tokenStack.peek().equals("+")) { + + Float num2 = Float.valueOf(numStack.pop().toString()); + + Float num1 = Float.valueOf(numStack.pop().toString()); + + numStack.push(num1+num2+""); + + } else if (tokenStack.peek().equals("-")) { + + Float num2 = Float.valueOf(numStack.pop().toString()); + + Float num1 = Float.valueOf(numStack.pop().toString()); + + numStack.push(num1-num2+""); + + } else if (tokenStack.peek().equals("/")) { + + Float num2 = Float.valueOf(numStack.pop().toString()); + + Float num1 = Float.valueOf(numStack.pop().toString()); + + numStack.push(num1/num2+""); + + } else if (tokenStack.peek().equals("*")) { + + Float num2 = Float.valueOf(numStack.pop().toString()); + + Float num1 = Float.valueOf(numStack.pop().toString()); + + numStack.push(num1*num2+""); + + } else { + + throw new RuntimeException(); + + } + + tokenStack.pop(); + + } + + return Double.valueOf(numStack.pop().toString()); + + } + +} diff --git a/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExprTest.java b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExprTest.java new file mode 100644 index 0000000000..607f5b8292 --- /dev/null +++ b/group06/949319266/jvm3/src/com/ecust/jvm3/InfixExprTest.java @@ -0,0 +1,5 @@ +package com.ecust.jvm3; + +public class InfixExprTest { + +} diff --git a/group06/949319266/jvm4/src/com/ecust/jvm4/InfixToPostfix2.java b/group06/949319266/jvm4/src/com/ecust/jvm4/InfixToPostfix2.java new file mode 100644 index 0000000000..b115f10a66 --- /dev/null +++ b/group06/949319266/jvm4/src/com/ecust/jvm4/InfixToPostfix2.java @@ -0,0 +1,95 @@ +package com.ecust.jvm4; + +import java.util.List; + +import java.util.Stack; + + + +public class InfixToPostfix2 { + + + + + + private static TokenParser tokenParser = new TokenParser(); + + + + public static String toPostFixExpr(String expr){ + + + + List tokens = tokenParser.parse(expr); + + + + Stack s1 = new Stack(); + + Stack s2 = new Stack(); + + + + for (Token token : tokens) { + + if (token.isNumber()) { + + s2.push(token); + + } else { + + while (token.isOperator() && !s1.isEmpty()) { + + if (!token.hasHigherPriority(s1.peek())) { + + s2.push(s1.pop()); + + continue; + + } + + break; + + } + + s1.push(token); + + } + + } + + while (!s1.isEmpty()) { + + s2.push(s1.pop()); + + } + + StringBuilder stringBuilder = new StringBuilder(); + + while (!s2.isEmpty()) { + + Token token = s2.pop(); + + s1.push(token); + + } + + while (!s1.isEmpty()) { + + Token token = s1.pop(); + + stringBuilder.append(token.toString()).append(" "); + + } + + + + return stringBuilder.substring(0,stringBuilder.length() - 1); + + } + + + + + +} diff --git a/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExpr.java b/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExpr.java new file mode 100644 index 0000000000..0e34a72d54 --- /dev/null +++ b/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExpr.java @@ -0,0 +1,111 @@ +package com.ecust.jvm4; + +import java.util.List; + +import java.util.Stack; + + + +/** + + * 与前缀表达式类似,只是顺序是从左至右: + + 从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。 + + 例如后缀表达式“3 4 + 5 × 6 -”: + + (1) 从左至右扫描,将3和4压入堆栈; + + (2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈; + + (3) 将5入栈; + + (4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈; + + (5) 将6入栈; + + (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。 + + */ + +public class PostfixExpr { + +String expr = null; + + + + public PostfixExpr(String expr) { + + this.expr = expr; + + } + + + + public float evaluate() { + + TokenParser parser = new TokenParser(); + + List tokens = parser.parse(this.expr); + + + + + + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if(token.isNumber()){ + + numStack.push(new Float(token.getIntValue())); + + } else{ + + Float f2 = numStack.pop(); + + Float f1 = numStack.pop(); + + numStack.push(calculate(token.toString(),f1,f2)); + + } + + } + + return numStack.pop().floatValue(); + + } + + + + private Float calculate(String op, Float f1, Float f2){ + + if(op.equals("+")){ + + return f1+f2; + + } + + if(op.equals("-")){ + + return f1-f2; + + } + + if(op.equals("*")){ + + return f1*f2; + + } + + if(op.equals("/")){ + + return f1/f2; + + } + + throw new RuntimeException(op + " is not supported"); + + } + +} diff --git a/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExprTest.java b/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExprTest.java new file mode 100644 index 0000000000..ae48effdad --- /dev/null +++ b/group06/949319266/jvm4/src/com/ecust/jvm4/PostfixExprTest.java @@ -0,0 +1,87 @@ +package com.ecust.jvm4; + +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); + + } + + } + + + + @Test + + public void testTo(){ + + String poseExpr = InfixToPostfix2.toPostFixExpr("10-2*3+50"); + + System.out.println(poseExpr); + + } + + + +} diff --git a/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExpr.java b/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExpr.java new file mode 100644 index 0000000000..3274a236bd --- /dev/null +++ b/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExpr.java @@ -0,0 +1,89 @@ +package com.ecust.jvm4; + +import java.util.List; + +import java.util.Stack; + + +public class PrefixExpr { + + + private String expr; + + + + public PrefixExpr(String expr) { + + this.expr = expr; + + } + + + + public float evaluate(){ + + + + TokenParser tokenParser = new TokenParser(); + + List tokens = tokenParser.parse(expr); + + + + Stack numStack = new Stack(); + + Stack oprStack = new Stack(); + + + + for (int i = tokens.size() - 1; i > -1; i--) { + + if (tokens.get(i).isNumber()) { + + numStack.push(new Float(tokens.get(i).getIntValue())); + + } else { + + Float num1 = numStack.pop(); + + Float num2 = numStack.pop(); + + numStack.push(caculate(tokens.get(i).toString(), num1, num2)); + + } + + } + + + + return numStack.pop(); + + } + + + + private Float caculate(String oper, Float num1, Float num2){ + + if (oper.equals("+")) { + + return num1 + num2; + + } else if (oper.equals("-")) { + + return num1 - num2; + + } else if (oper.equals("/")) { + + return num1 / num2; + + } else if (oper.equals("*")) { + + return num1 * num2; + + } + + throw new RuntimeException("illeagal operation token"); + + } + +} diff --git a/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExprTest.java b/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExprTest.java new file mode 100644 index 0000000000..44c16c1f83 --- /dev/null +++ b/group06/949319266/jvm4/src/com/ecust/jvm4/PrefixExprTest.java @@ -0,0 +1,5 @@ +package com.ecust.jvm4; + +public class PrefixExprTest { + +} diff --git a/group06/949319266/jvm5/src/com/ecust/jvm5/CircleQueue.java b/group06/949319266/jvm5/src/com/ecust/jvm5/CircleQueue.java new file mode 100644 index 0000000000..58e87c295e --- /dev/null +++ b/group06/949319266/jvm5/src/com/ecust/jvm5/CircleQueue.java @@ -0,0 +1,149 @@ +package com.ecust.jvm5; + + + +public class CircleQueue { + + + + private final static int DEFAULT_SIZE = 10; + + + + private int count = 0; + + + + //用数组来保存循环队列的元素 + + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + + + //队头 + + private int front = 0; + + //队尾 + + private int rear = 0; + + + + public boolean isEmpty() { + + return count == 0; + + + + } + + + + public int size() { + + return count; + + } + + + + + + + + public void enQueue(E data) { + + if (count == DEFAULT_SIZE ) { + + throw new RuntimeException(); + + } + + elementData[front] = data; + + front = (front + 1) % DEFAULT_SIZE; + + count++; + + } + + + + public E deQueue() { + + if (count == 0) { + + return null; + + } + + count--; + + E e = (E)elementData[rear]; + + rear = (rear + 1) % DEFAULT_SIZE; + + return e; + + } + + + + public static void main(String[] args) { + + CircleQueue queue = new CircleQueue<>(); + + queue.enQueue(1); + + queue.enQueue(2); + + queue.enQueue(3); + + queue.enQueue(4); + + queue.enQueue(5); + + queue.enQueue(6); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue());System.out.println(queue.deQueue());System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + queue.enQueue(7); + + queue.enQueue(8); + + queue.enQueue(9); + + queue.enQueue(0); + + queue.enQueue(1); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + + + } + + + + + +} \ No newline at end of file diff --git a/group06/949319266/jvm5/src/com/ecust/jvm5/Josephus.java b/group06/949319266/jvm5/src/com/ecust/jvm5/Josephus.java new file mode 100644 index 0000000000..da0e89dc2f --- /dev/null +++ b/group06/949319266/jvm5/src/com/ecust/jvm5/Josephus.java @@ -0,0 +1,77 @@ +package com.ecust.jvm5; + +import java.util.ArrayDeque; + +import java.util.ArrayList; + +import java.util.List; + + + +public class Josephus { + + + + + + public static List execute(int n, int m){ + + Preconditions.checkArgument(n > 0); + + ArrayList deadList = new ArrayList<>(); + + ArrayDeque deque1 = new ArrayDeque<>(); + + ArrayDeque deque2 = new ArrayDeque<>(); + + for (int i = 0; i < n; i++) { + + deque1.offer(i); + + } + + int count = 0; + + while(n >= m){ + + if (deque1.isEmpty()) { + + while (!deque2.isEmpty()){ + + deque1.offer(deque2.poll()); + + } + + } + + count++; + + if (count == m) { + + deadList.add(deque1.poll()); + + count = 0; + + n--; + + continue; + + } + + deque2.offer(deque1.poll()); + + + + } + + + + return deadList; + + } + + + + + +} \ No newline at end of file diff --git a/group06/949319266/jvm5/src/com/ecust/jvm5/JosephusTest.java b/group06/949319266/jvm5/src/com/ecust/jvm5/JosephusTest.java new file mode 100644 index 0000000000..76bb7d3ba4 --- /dev/null +++ b/group06/949319266/jvm5/src/com/ecust/jvm5/JosephusTest.java @@ -0,0 +1,5 @@ +package com.ecust.jvm5; + +public class JosephusTest { + +} diff --git a/group06/949319266/jvm5/src/com/ecust/jvm5/QueueWithTwoStacks.java b/group06/949319266/jvm5/src/com/ecust/jvm5/QueueWithTwoStacks.java new file mode 100644 index 0000000000..052cf6d444 --- /dev/null +++ b/group06/949319266/jvm5/src/com/ecust/jvm5/QueueWithTwoStacks.java @@ -0,0 +1,162 @@ +package com.ecust.jvm5; + +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(); + + } + + + + + + + + public int size() { + + return stack1.size(); + + } + + + + + + + + public void enQueue(E item) { + + stack1.push(item); + + } + + + + public E deQueue() { + + if (stack1.isEmpty()) { + + return null; + + } + + while (!stack1.isEmpty()) { + + stack2.push(stack1.pop()); + + } + + E e = stack2.pop(); + + while (!stack2.isEmpty()) { + + stack1.push(stack2.pop()); + + } + + return e; + + } + + + + public static void main(String[] args) { + + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + + queue.enQueue(1); + + queue.enQueue(2); + + queue.enQueue(3); + + queue.enQueue(4); + + queue.enQueue(5); + + queue.enQueue(6); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue());System.out.println(queue.deQueue());System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + queue.enQueue(7); + + queue.enQueue(8); + + queue.enQueue(9); + + queue.enQueue(0); + + queue.enQueue(1); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + System.out.println(queue.deQueue()); + + + + + + } + + + + } + diff --git a/group11/1178243325/week06/readme.md b/group11/1178243325/week06/readme.md index d89a5c904e..df09ad3398 100644 --- a/group11/1178243325/week06/readme.md +++ b/group11/1178243325/week06/readme.md @@ -2,7 +2,7 @@ - 17-03-27:JVM第一周 - 17-03-29:JVM之classLoader -## 第六周作业(3-27 至 04-02) +## 第六周作业---JVM(1)(3-27 至 04-02) - 完成对一个.class文件的读取和对.class文件开头四个字节的魔数的判断需要实现ClassLoader.java - 实现LRU算法 - 一篇文章 diff --git a/group11/1178243325/week07/.readme.md.swp b/group11/1178243325/week07/.readme.md.swp deleted file mode 100644 index 3d7e4464a8..0000000000 Binary files a/group11/1178243325/week07/.readme.md.swp and /dev/null differ diff --git a/group11/1178243325/week07/readme.md b/group11/1178243325/week07/readme.md index cc9d7c6f3c..af37f44357 100644 --- a/group11/1178243325/week07/readme.md +++ b/group11/1178243325/week07/readme.md @@ -1,12 +1,12 @@ ## 讲课内容: - 17-03-29 :JVM之classLoader -## 第七周作业(04-03 至 04-09) +## 第七周作业---JVM(2)(04-03 至 04-09) - 实现对一个.class文件的常量池读取 - 实现StackUtil - [文章](http://www.jianshu.com/p/502c1e5caa97) ## 完成情况: - +ok ## 我的收获: - +其实最难是坚持 diff --git a/group11/1178243325/week07/src/main/java/com/sprint/datastructure/StackUtil.java b/group11/1178243325/week07/src/main/java/com/sprint/datastructure/StackUtil.java new file mode 100644 index 0000000000..cf6afb5b3c --- /dev/null +++ b/group11/1178243325/week07/src/main/java/com/sprint/datastructure/StackUtil.java @@ -0,0 +1,127 @@ +package com.sprint.datastructure; + +import java.util.Stack; +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + /* Stack stack = new Stack<>(); + while (!s.isEmpty()) { + stack.push(s.pop()); + } + + Stack stack1 = new Stack<>(); + while (!stack.isEmpty()) { + stack1.push(stack.pop()); + } + + while (!stack1.isEmpty()) { + s.push(stack1.pop()); + } + **/ + + if (s == null || s.isEmpty()) + return; + Stack tmp = new Stack<>(); + while (!s.isEmpty()) { + tmp.push(s.pop()); + } + while (!tmp.isEmpty()) { + Integer top = tmp.pop(); + addToBottom(s, top); + } + } + + private static void addToBottom(Stack s, Integer value) { + if (s.isEmpty()) { + s.push(value); + } else { + Integer top = s.pop(); + addToBottom(s, value); + s.push(top); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if (s == null || s.isEmpty()) + return; + + Stack tmp = new Stack(); + while (!s.isEmpty()) { + Object value = s.pop(); + if (!value.equals(o)) { + tmp.push(value); + } + } + + while (!tmp.isEmpty()) { + s.push(tmp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (s == null || s.isEmpty() || len <= 0) { + return null; + } + Object[] objs = new Object[len]; + Stack tmp = new Stack(); + int count = 0; + while (!s.isEmpty() && count < len) { + Object top = s.pop(); + tmp.push(top); + objs[count++] = top; + } + + while (!tmp.isEmpty()) { + s.push(tmp.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 stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } else if (c == ')') { + char topChar = stack.pop(); + if (topChar != '(') { + return false; + } + } else if (c == ']') { + char topChar = stack.pop(); + if (topChar != '[') { + return false; + } + } else if (c == '}') { + char topChar = stack.pop(); + if (topChar != '{') { + return false; + } + } + } + return stack.size() == 0; + } +} diff --git a/group11/1178243325/week07/src/test/java/com/sprint/datastructure/StackUtilTest.java b/group11/1178243325/week07/src/test/java/com/sprint/datastructure/StackUtilTest.java new file mode 100644 index 0000000000..86f9db1607 --- /dev/null +++ b/group11/1178243325/week07/src/test/java/com/sprint/datastructure/StackUtilTest.java @@ -0,0 +1,65 @@ +package com.sprint.datastructure; + +import java.util.Stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group11/1178243325/week08/build.gradle b/group11/1178243325/week08/build.gradle new file mode 100644 index 0000000000..f46c5add86 --- /dev/null +++ b/group11/1178243325/week08/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + compile("commons-io:commons-io:2.4") + //compile("commons-lang:commons-lang:2.6") + compile("org.apache.commons:commons-lang3:3.4") + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week08/readme.md b/group11/1178243325/week08/readme.md new file mode 100644 index 0000000000..1d096b5807 --- /dev/null +++ b/group11/1178243325/week08/readme.md @@ -0,0 +1,13 @@ +## 讲课内容: + +## 第八周作业---JVM(3)(04-10 至 04-16) +- 实现对一个.class文件的字段和方法的读取,需要实现的类是ClassFileParser.java及其相关的类,实现后需要通过测试:ClassFileloaderTest.java +- 数据结构,实现InfixExpr.java,需要通过InfixExprTest.java +- 写一篇文章 + +## 完成情况: +- jvm未完 +- 其余已完 + +## 我的收获: +其实最难是坚持 diff --git a/group11/1178243325/week08/src/main/java/com/sprint/datastructure/InfixExpr.java b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/InfixExpr.java new file mode 100644 index 0000000000..dc302720da --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/InfixExpr.java @@ -0,0 +1,61 @@ +package com.sprint.datastructure; + +import java.util.List; +import java.util.Stack; +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + if (token.isOperator()) { + while (!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())) { + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1, f2); + numStack.push(result); + } + opStack.push(token); + } + + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } + } + + while (!opStack.isEmpty()) { + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException (op + " is not supported "); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/datastructure/Token.java b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/Token.java new file mode 100644 index 0000000000..c776b1c97a --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/Token.java @@ -0,0 +1,53 @@ +package com.sprint.datastructure; + +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + @Override + public String toString() { + return value; + } + + public boolean hasHigherPriority(Token t) { + if (!this.isOperator() && !t.isOperator()) { + throw new RuntimeException("number can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/datastructure/TokenParser.java b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/TokenParser.java new file mode 100644 index 0000000000..2985d0e32f --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/datastructure/TokenParser.java @@ -0,0 +1,45 @@ +package com.sprint.datastructure; + +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 boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } + + private int indexOfNextOperator(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + } + +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/AccessFlag.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..e74740aa3e --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.sprint.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flagValue) { + this.flagValue = flagValue; + } + + public boolean isPublicClass() { + return (this.flagValue & 0x0001) != 0; + } + + public boolean isFinalClass() { + return (this.flagValue & 0x0010) != 0; + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassFile.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4e5aad16f9 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassFile.java @@ -0,0 +1,71 @@ +package com.sprint.jvm.clz; + +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.ClassInfo; +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool 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 AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ClassIndex getClassIndex() { + return clzIndex; + } + + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getConstantPool() { + return pool; + } + + public void setConstantPool(ConstantPool pool) { + this.pool = pool; + } + + 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() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassIndex.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..46e7443d90 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + + public void setThisClassIndex(int index) { + this.thisClassIndex = index; + } + + public int getSuperClassIndex() { + return superClassIndex; + } + + public void setSuperClassIndex(int index) { + this.superClassIndex = index; + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ClassInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b8da3c656d --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index; + + public ClassInfo(ConstantPool pool) { + super(pool); + } + + public void setUtf8Index(int index) { + this.utf8Index = index; + } + + public int getUtf8Index() { + return utf8Index; + } + + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a8db82689e --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.sprint.jvm.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); + } + +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantPool.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..3a35c22ce0 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/ConstantPool.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.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 Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..c0eb449085 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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(); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..85bb5c4934 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.sprint.jvm.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(); + } +} + diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..492fd6e0db --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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 getType() { + return type; + } + + 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 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() + ")"; + } + + +} + + diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..f257cea240 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java @@ -0,0 +1,12 @@ +package com.sprint.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/StringInfo.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..73c58a5e71 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.sprint.jvm.constant; + +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool constantPool) { + super(constantPool); + } + + 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); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/UTF8Info.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5516999c0e --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/constant/UTF8Info.java @@ -0,0 +1,35 @@ +package com.sprint.jvm.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; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..fc5d1b2ac2 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,50 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.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/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f190f54915 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.util.List; +import java.util.ArrayList; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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); + } +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileParser.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..4b77190a04 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/loader/ClassFileParser.java @@ -0,0 +1,107 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import com.sprint.jvm.clz.AccessFlag; +import com.sprint.jvm.clz.ClassIndex; +import com.sprint.jvm.constant.ClassInfo; +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.FieldRefInfo; +import com.sprint.jvm.constant.NameAndTypeInfo; +import com.sprint.jvm.constant.NullConstantInfo; +import com.sprint.jvm.constant.MethodRefInfo; +import com.sprint.jvm.constant.StringInfo; +import com.sprint.jvm.constant.UTF8Info; +import java.io.UnsupportedEncodingException; +public class ClassFileParser { + public ClassFile parse(byte[] codes) { + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + clzFile.setMinorVersion(iter.nextU2ToInt()); + System.out.println("minor:" + clzFile.getMinorVersion()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + System.out.println("marjor:" + clzFile.getMajorVersion()); + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstantPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + ClassIndex clzIndex = parseClassIndex(iter); + clzFile.setClassIndex(clzIndex); + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + return flag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + return clzIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constPoolCount = iter.nextU2ToInt(); + System.out.println("Constant Pool Count :" + constPoolCount); + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i <= constPoolCount - 1; i++) { + int tag = iter.nextU1ToInt(); + if (tag == 7) { + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + } else if (tag == 1) { + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + } else if (tag == 8) { + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == 9) { + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == 10) { + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == 12) { + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setIndex1(iter.nextU2ToInt()); + nameType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag:" + tag + "has no been implemented yet."); + } + } + System.out.println("Finished reading Constant Pool"); + return pool; + } + + +} diff --git a/group11/1178243325/week08/src/main/java/com/sprint/jvm/util/Util.java b/group11/1178243325/week08/src/main/java/com/sprint/jvm/util/Util.java new file mode 100644 index 0000000000..0f5dc89626 --- /dev/null +++ b/group11/1178243325/week08/src/main/java/com/sprint/jvm/util/Util.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} diff --git a/group11/1178243325/week08/src/test/java/com/sprint/datastructure/InfixExprTest.java b/group11/1178243325/week08/src/test/java/com/sprint/datastructure/InfixExprTest.java new file mode 100644 index 0000000000..bf8907c9b6 --- /dev/null +++ b/group11/1178243325/week08/src/test/java/com/sprint/datastructure/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.sprint.datastructure; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group11/1178243325/week08/src/test/java/com/sprint/datastructure/TokenParserTest.java b/group11/1178243325/week08/src/test/java/com/sprint/datastructure/TokenParserTest.java new file mode 100644 index 0000000000..67ccfb52f0 --- /dev/null +++ b/group11/1178243325/week08/src/test/java/com/sprint/datastructure/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.sprint.datastructure; + +import static org.junit.Assert.*; + +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"); + + 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/group11/1178243325/week09/build.gradle b/group11/1178243325/week09/build.gradle new file mode 100644 index 0000000000..f46c5add86 --- /dev/null +++ b/group11/1178243325/week09/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + compile("commons-io:commons-io:2.4") + //compile("commons-lang:commons-lang:2.6") + compile("org.apache.commons:commons-lang3:3.4") + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week09/readme.md b/group11/1178243325/week09/readme.md new file mode 100644 index 0000000000..57bf01280a --- /dev/null +++ b/group11/1178243325/week09/readme.md @@ -0,0 +1,15 @@ +## 讲课内容: + +## 第九周作业---JVM(4)(04-17 至 04-23) +- 把字节码指令转变为java对象, 需要实现的类: CommandParser.java +- 实现类似的javap命令, 需要实现的类:ClassFilePrinter.java +- 数据结构,实现前缀表达计算PrefixExpr.java,后缀表达计算PostfixExpr.java,中缀表达式转后缀表达式InfixToPostfix.java +- 写一篇文章 + +## 完成情况: +- 数据结构已完 +- 文章已完 +- JVM未完 + +## 我的收获: +其实最难是坚持 diff --git a/group11/1178243325/week09/src/main/java/com/sprint/datastructure/InfixToPostfix.java b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/InfixToPostfix.java new file mode 100644 index 0000000000..a30f29633c --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/InfixToPostfix.java @@ -0,0 +1,32 @@ +package com.sprint.datastructure; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +public class InfixToPostfix { + + public static List convert(String expr) { + List inFixTokens = new TokenParser().parse(expr); + List postFixTokens = new ArrayList<>(); + Stack opStack = new Stack<>(); + + for (Token token : inFixTokens) { + if (token.isOperator()) { + while (!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())) { + postFixTokens.add(opStack.pop()); + } + opStack.push(token); + } + + if (token.isNumber()) { + postFixTokens.add(token); + } + } + + while (!opStack.isEmpty()) { + postFixTokens.add(opStack.pop()); + } + return postFixTokens; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PostfixExpr.java b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PostfixExpr.java new file mode 100644 index 0000000000..b1d5d2892a --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PostfixExpr.java @@ -0,0 +1,44 @@ +package com.sprint.datastructure; + +import java.util.List; +import java.util.Stack; +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack numStack = new Stack<>(); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1+f2; + } + if (op.equals("-")) { + return f1-f2; + } + if (op.equals("*")) { + return f1*f2; + } + if (op.equals("/")) { + return f1/f2; + } + throw new RuntimeException(op + " is not supported "); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PrefixExpr.java b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PrefixExpr.java new file mode 100644 index 0000000000..36d4bac543 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/PrefixExpr.java @@ -0,0 +1,54 @@ +package com.sprint.datastructure; + +import java.util.List; +import java.util.Stack; +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + exprStack.push(token); + } + + while (!exprStack.isEmpty()) { + Token t = exprStack.pop(); + if (t.isNumber()) { + numStack.push(new Float(t.getIntValue())); + } else { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(t.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + + if (op.equals("-")) { + return f1 - f2; + } + + if (op.equals("*")) { + return f1 * f2; + } + + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported "); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/datastructure/Token.java b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/Token.java new file mode 100644 index 0000000000..c776b1c97a --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/Token.java @@ -0,0 +1,53 @@ +package com.sprint.datastructure; + +import java.util.Arrays; +import java.util.List; +import java.util.HashMap; +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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + @Override + public String toString() { + return value; + } + + public boolean hasHigherPriority(Token t) { + if (!this.isOperator() && !t.isOperator()) { + throw new RuntimeException("number can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/datastructure/TokenParser.java b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/TokenParser.java new file mode 100644 index 0000000000..2985d0e32f --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/datastructure/TokenParser.java @@ -0,0 +1,45 @@ +package com.sprint.datastructure; + +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 boolean isOperator(char c) { + String sc = String.valueOf(c); + return Token.OPERATORS.contains(sc); + } + + private int indexOfNextOperator(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + } + +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/AccessFlag.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..e74740aa3e --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.sprint.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flagValue) { + this.flagValue = flagValue; + } + + public boolean isPublicClass() { + return (this.flagValue & 0x0001) != 0; + } + + public boolean isFinalClass() { + return (this.flagValue & 0x0010) != 0; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassFile.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4e5aad16f9 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassFile.java @@ -0,0 +1,71 @@ +package com.sprint.jvm.clz; + +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.ClassInfo; +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool 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 AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ClassIndex getClassIndex() { + return clzIndex; + } + + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getConstantPool() { + return pool; + } + + public void setConstantPool(ConstantPool pool) { + this.pool = pool; + } + + 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() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassIndex.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..46e7443d90 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + + public void setThisClassIndex(int index) { + this.thisClassIndex = index; + } + + public int getSuperClassIndex() { + return superClassIndex; + } + + public void setSuperClassIndex(int index) { + this.superClassIndex = index; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ClassInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b8da3c656d --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index; + + public ClassInfo(ConstantPool pool) { + super(pool); + } + + public void setUtf8Index(int index) { + this.utf8Index = index; + } + + public int getUtf8Index() { + return utf8Index; + } + + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a8db82689e --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.sprint.jvm.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); + } + +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantPool.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..3a35c22ce0 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/ConstantPool.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.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 Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..c0eb449085 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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(); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..85bb5c4934 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.sprint.jvm.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(); + } +} + diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..492fd6e0db --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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 getType() { + return type; + } + + 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 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() + ")"; + } + + +} + + diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..f257cea240 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java @@ -0,0 +1,12 @@ +package com.sprint.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/StringInfo.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..73c58a5e71 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.sprint.jvm.constant; + +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool constantPool) { + super(constantPool); + } + + 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); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/UTF8Info.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5516999c0e --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/constant/UTF8Info.java @@ -0,0 +1,35 @@ +package com.sprint.jvm.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; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..fc5d1b2ac2 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,50 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.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/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f190f54915 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.util.List; +import java.util.ArrayList; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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); + } +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileParser.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..4b77190a04 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/loader/ClassFileParser.java @@ -0,0 +1,107 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import com.sprint.jvm.clz.AccessFlag; +import com.sprint.jvm.clz.ClassIndex; +import com.sprint.jvm.constant.ClassInfo; +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.FieldRefInfo; +import com.sprint.jvm.constant.NameAndTypeInfo; +import com.sprint.jvm.constant.NullConstantInfo; +import com.sprint.jvm.constant.MethodRefInfo; +import com.sprint.jvm.constant.StringInfo; +import com.sprint.jvm.constant.UTF8Info; +import java.io.UnsupportedEncodingException; +public class ClassFileParser { + public ClassFile parse(byte[] codes) { + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + clzFile.setMinorVersion(iter.nextU2ToInt()); + System.out.println("minor:" + clzFile.getMinorVersion()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + System.out.println("marjor:" + clzFile.getMajorVersion()); + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstantPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + ClassIndex clzIndex = parseClassIndex(iter); + clzFile.setClassIndex(clzIndex); + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + return flag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + return clzIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constPoolCount = iter.nextU2ToInt(); + System.out.println("Constant Pool Count :" + constPoolCount); + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i <= constPoolCount - 1; i++) { + int tag = iter.nextU1ToInt(); + if (tag == 7) { + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + } else if (tag == 1) { + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + } else if (tag == 8) { + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == 9) { + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == 10) { + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == 12) { + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setIndex1(iter.nextU2ToInt()); + nameType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag:" + tag + "has no been implemented yet."); + } + } + System.out.println("Finished reading Constant Pool"); + return pool; + } + + +} diff --git a/group11/1178243325/week09/src/main/java/com/sprint/jvm/util/Util.java b/group11/1178243325/week09/src/main/java/com/sprint/jvm/util/Util.java new file mode 100644 index 0000000000..0f5dc89626 --- /dev/null +++ b/group11/1178243325/week09/src/main/java/com/sprint/jvm/util/Util.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} diff --git a/group11/1178243325/week09/src/test/java/com/sprint/datastructure/InfixToPostfixTest.java b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/InfixToPostfixTest.java new file mode 100644 index 0000000000..b84e754655 --- /dev/null +++ b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/InfixToPostfixTest.java @@ -0,0 +1,41 @@ +package com.sprint.datastructure; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PostfixExprTest.java b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PostfixExprTest.java new file mode 100644 index 0000000000..d2870efffe --- /dev/null +++ b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PostfixExprTest.java @@ -0,0 +1,39 @@ +package com.sprint.datastructure; + +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/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PrefixExprTest.java b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PrefixExprTest.java new file mode 100644 index 0000000000..3c21b9dcc1 --- /dev/null +++ b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/PrefixExprTest.java @@ -0,0 +1,46 @@ +package com.sprint.datastructure; + + +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/group11/1178243325/week09/src/test/java/com/sprint/datastructure/TokenParserTest.java b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/TokenParserTest.java new file mode 100644 index 0000000000..67ccfb52f0 --- /dev/null +++ b/group11/1178243325/week09/src/test/java/com/sprint/datastructure/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.sprint.datastructure; + +import static org.junit.Assert.*; + +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"); + + 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/group11/1178243325/week10/build.gradle b/group11/1178243325/week10/build.gradle new file mode 100644 index 0000000000..f46c5add86 --- /dev/null +++ b/group11/1178243325/week10/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + compile("commons-io:commons-io:2.4") + //compile("commons-lang:commons-lang:2.6") + compile("org.apache.commons:commons-lang3:3.4") + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week10/readme.md b/group11/1178243325/week10/readme.md new file mode 100644 index 0000000000..0c1085521b --- /dev/null +++ b/group11/1178243325/week10/readme.md @@ -0,0 +1,14 @@ +## 讲课内容: + +## 第10周作业---JVM(5)(04-24 至 04-30) +- 实现一个简单的执行引擎,主要代码engine cmd +- 数据结构,实现循环队列CircleQueue.java,约瑟夫环Josephus.java,用两个栈实现队列QueueWithTwoStacks.java +- 写一篇文章 + +## 完成情况: +- 数据结构已完 +- 文章已完 +- jvm未完 + +## 我的收获: +其实最难是坚持 diff --git a/group11/1178243325/week10/src/main/java/com/sprint/datastructure/CircleQueue.java b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/CircleQueue.java new file mode 100644 index 0000000000..42f8fcd4df --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/CircleQueue.java @@ -0,0 +1,49 @@ +package com.sprint.datastructure; + +public class CircleQueue { + + private Object[] elementData; + private int size = 0; + //队头 + private int front = 0; + + //队尾 + private int rear = 0; + + + public CircleQueue(int capacity) { + elementData = new Object[capacity]; + } + + public boolean isEmpty() { + return front == rear; + } + + public boolean isFull() { + return size == elementData.length; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + if (isFull()) { + throw new RuntimeException("The queue is full"); + } + elementData[rear++] = data; + size++; + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("The queue is empty"); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front + 1) % elementData.length; + size--; + return data; + } +} + diff --git a/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Josephus.java b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Josephus.java new file mode 100644 index 0000000000..9656e15c02 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Josephus.java @@ -0,0 +1,34 @@ +package com.sprint.datastructure; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * + */ +public class Josephus { + + public static List execute(int n, int m){ + Queue queue = new Queue<>(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + + List result = new ArrayList<>(); + int i = 0; + + while (!queue.isEmpty()) { + int x = queue.deQueue(); + if (++i %m == 0) { + result.add(x); + } else { + queue.enQueue(x); + } + } + return result; + } + +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Queue.java b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Queue.java new file mode 100644 index 0000000000..e7c14ac30e --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/Queue.java @@ -0,0 +1,54 @@ +package com.sprint.datastructure; + +import java.util.NoSuchElementException; +public class Queue { + 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/group11/1178243325/week10/src/main/java/com/sprint/datastructure/QueueWithTwoStacks.java b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/QueueWithTwoStacks.java new file mode 100644 index 0000000000..3ca10f4b25 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/datastructure/QueueWithTwoStacks.java @@ -0,0 +1,58 @@ +package com.sprint.datastructure; + +import java.util.Stack; +import java.util.NoSuchElementException; +/** + * 用两个栈来实现一个队列 + * + * @param + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + if (item == null) + return; + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + if (stack2.isEmpty()) { + moveStack1ToStack2(); + } + return stack2.pop(); + } + + private void moveStack1ToStack2() { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + + } + diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/AccessFlag.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..e74740aa3e --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.sprint.jvm.clz; + +public class AccessFlag { + private int flagValue; + + public AccessFlag(int value) { + this.flagValue = value; + } + + public int getFlagValue() { + return flagValue; + } + + public void setFlagValue(int flagValue) { + this.flagValue = flagValue; + } + + public boolean isPublicClass() { + return (this.flagValue & 0x0001) != 0; + } + + public boolean isFinalClass() { + return (this.flagValue & 0x0010) != 0; + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassFile.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4e5aad16f9 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassFile.java @@ -0,0 +1,71 @@ +package com.sprint.jvm.clz; + +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.ClassInfo; +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool 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 AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ClassIndex getClassIndex() { + return clzIndex; + } + + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getConstantPool() { + return pool; + } + + public void setConstantPool(ConstantPool pool) { + this.pool = pool; + } + + 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() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassIndex.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..46e7443d90 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex() { + return thisClassIndex; + } + + public void setThisClassIndex(int index) { + this.thisClassIndex = index; + } + + public int getSuperClassIndex() { + return superClassIndex; + } + + public void setSuperClassIndex(int index) { + this.superClassIndex = index; + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ClassInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b8da3c656d --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.constant; + +public class ClassInfo extends ConstantInfo { + private int type = ConstantInfo.CLASS_INFO; + private int utf8Index; + + public ClassInfo(ConstantPool pool) { + super(pool); + } + + public void setUtf8Index(int index) { + this.utf8Index = index; + } + + public int getUtf8Index() { + return utf8Index; + } + + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a8db82689e --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.sprint.jvm.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); + } + +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantPool.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..3a35c22ce0 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/ConstantPool.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.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 Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..c0eb449085 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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(); + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..85bb5c4934 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.sprint.jvm.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(); + } +} + diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..492fd6e0db --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.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 getType() { + return type; + } + + 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 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() + ")"; + } + + +} + + diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..f257cea240 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java @@ -0,0 +1,12 @@ +package com.sprint.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/StringInfo.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..73c58a5e71 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.sprint.jvm.constant; + +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool constantPool) { + super(constantPool); + } + + 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); + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/UTF8Info.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5516999c0e --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/constant/UTF8Info.java @@ -0,0 +1,35 @@ +package com.sprint.jvm.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; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..fc5d1b2ac2 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,50 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.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/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f190f54915 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java @@ -0,0 +1,52 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; +import java.util.List; +import java.util.ArrayList; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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); + } +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileParser.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..4b77190a04 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/loader/ClassFileParser.java @@ -0,0 +1,107 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import com.sprint.jvm.clz.AccessFlag; +import com.sprint.jvm.clz.ClassIndex; +import com.sprint.jvm.constant.ClassInfo; +import com.sprint.jvm.constant.ConstantPool; +import com.sprint.jvm.constant.FieldRefInfo; +import com.sprint.jvm.constant.NameAndTypeInfo; +import com.sprint.jvm.constant.NullConstantInfo; +import com.sprint.jvm.constant.MethodRefInfo; +import com.sprint.jvm.constant.StringInfo; +import com.sprint.jvm.constant.UTF8Info; +import java.io.UnsupportedEncodingException; +public class ClassFileParser { + public ClassFile parse(byte[] codes) { + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + clzFile.setMinorVersion(iter.nextU2ToInt()); + System.out.println("minor:" + clzFile.getMinorVersion()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + System.out.println("marjor:" + clzFile.getMajorVersion()); + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstantPool(pool); + + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + ClassIndex clzIndex = parseClassIndex(iter); + clzFile.setClassIndex(clzIndex); + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + return flag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + return clzIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constPoolCount = iter.nextU2ToInt(); + System.out.println("Constant Pool Count :" + constPoolCount); + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i <= constPoolCount - 1; i++) { + int tag = iter.nextU1ToInt(); + if (tag == 7) { + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + } else if (tag == 1) { + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + } else if (tag == 8) { + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == 9) { + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == 10) { + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == 12) { + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setIndex1(iter.nextU2ToInt()); + nameType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag:" + tag + "has no been implemented yet."); + } + } + System.out.println("Finished reading Constant Pool"); + return pool; + } + + +} diff --git a/group11/1178243325/week10/src/main/java/com/sprint/jvm/util/Util.java b/group11/1178243325/week10/src/main/java/com/sprint/jvm/util/Util.java new file mode 100644 index 0000000000..0f5dc89626 --- /dev/null +++ b/group11/1178243325/week10/src/main/java/com/sprint/jvm/util/Util.java @@ -0,0 +1,22 @@ +package com.sprint.jvm.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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} diff --git a/group11/1178243325/week10/src/test/java/com/sprint/datastructure/CircleQueueTest.java b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/CircleQueueTest.java new file mode 100644 index 0000000000..d61b0ce8cc --- /dev/null +++ b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/CircleQueueTest.java @@ -0,0 +1,45 @@ +package com.sprint.datastructure; + + +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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} diff --git a/group11/1178243325/week10/src/test/java/com/sprint/datastructure/JosephusTest.java b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/JosephusTest.java new file mode 100644 index 0000000000..353d9b0d73 --- /dev/null +++ b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/JosephusTest.java @@ -0,0 +1,27 @@ +package com.sprint.datastructure; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group11/1178243325/week10/src/test/java/com/sprint/datastructure/QueueWithTwoStacksTest.java b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..a5eb27c758 --- /dev/null +++ b/group11/1178243325/week10/src/test/java/com/sprint/datastructure/QueueWithTwoStacksTest.java @@ -0,0 +1,28 @@ +package com.sprint.datastructure; + +import org.junit.Assert; +import org.junit.Test; +public class QueueWithTwoStacksTest { + + @Test + public void test() { + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + Assert.assertTrue(queue.isEmpty()); + + queue.enQueue("a"); + queue.enQueue("b"); + queue.enQueue("c"); + queue.enQueue("d"); + queue.enQueue("e"); + + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } +} diff --git a/group11/1178243325/week11/build.gradle b/group11/1178243325/week11/build.gradle new file mode 100644 index 0000000000..c4da624f95 --- /dev/null +++ b/group11/1178243325/week11/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week11/readme.md b/group11/1178243325/week11/readme.md new file mode 100644 index 0000000000..bfd7dcf47c --- /dev/null +++ b/group11/1178243325/week11/readme.md @@ -0,0 +1,11 @@ +## 讲课内容: + +## 第11周作业(05-01 至 05-07) +- 数据结构,实现QuickMinStack.java, StackWithTwoQueues.java,TwoStackInOneArray.java +- 写一篇文章 + +## 完成情况: +- end + +## 我的收获: +其实最难是坚持 diff --git a/group11/1178243325/week11/src/main/java/com/sprint/datastructure/Queue.java b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/Queue.java new file mode 100644 index 0000000000..e7c14ac30e --- /dev/null +++ b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/Queue.java @@ -0,0 +1,54 @@ +package com.sprint.datastructure; + +import java.util.NoSuchElementException; +public class Queue { + 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/group11/1178243325/week11/src/main/java/com/sprint/datastructure/QuickMinStack.java b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/QuickMinStack.java new file mode 100644 index 0000000000..03dd5a02fb --- /dev/null +++ b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/QuickMinStack.java @@ -0,0 +1,56 @@ +package com.sprint.datastructure; + +import java.util.Stack; +import java.util.EmptyStackException; +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * + */ +public class QuickMinStack { + + Stack stack = new Stack<>(); + int minValue; + + public void push(int data){ + if (isEmpty()) { + minValue = data; + } + if (minValue > data) { + minValue = data; + } + stack.push(data); + } + + public int pop(){ + if (isEmpty()) { + throw new EmptyStackException(); + } + int top = stack.pop(); + if (top == minValue && !isEmpty()) { + minValue = getMinValue(stack); + } + return top; + } + + public int findMin(){ + return minValue; + } + + private boolean isEmpty() { + return stack.size() == 0; + } + + private int getMinValue(Stack stack) { + Stack stack1 = stack; + int min = stack1.pop(); + while (!isEmpty()) { + int value = stack1.pop(); + if (min > value) { + min = value; + } + } + return min; + } +} + diff --git a/group11/1178243325/week11/src/main/java/com/sprint/datastructure/StackWithTwoQueues.java b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/StackWithTwoQueues.java new file mode 100644 index 0000000000..e95bdee501 --- /dev/null +++ b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/StackWithTwoQueues.java @@ -0,0 +1,43 @@ +package com.sprint.datastructure; + +import java.util.EmptyStackException; +public class StackWithTwoQueues { + + Queue queue1; + Queue queue2; + + public StackWithTwoQueues() { + queue1 = new Queue(); + queue2 = new Queue(); + + } + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + if (queue1.isEmpty()) { + throw new EmptyStackException(); + } + int top = getTop(); + return top; + } + + private int getTop() { + int length = queue1.size() - 1; //小bug:queue.size() + for (int i = 0; i < length; i++) { + queue2.enQueue(queue1.deQueue()); + + } + int top = (int)queue1.deQueue(); + queue2ToQueue1(); + return top; + } + + private void queue2ToQueue1() { + while (!queue2.isEmpty()) { + queue1.enQueue(queue2.deQueue()); + } + } +} diff --git a/group11/1178243325/week11/src/main/java/com/sprint/datastructure/TwoStackInOneArray.java b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/TwoStackInOneArray.java new file mode 100644 index 0000000000..0dcc41d1bf --- /dev/null +++ b/group11/1178243325/week11/src/main/java/com/sprint/datastructure/TwoStackInOneArray.java @@ -0,0 +1,120 @@ +package com.sprint.datastructure; + +import java.util.EmptyStackException; +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + */ +public class TwoStackInOneArray { + Object[] data; + int capacity; + int front; + int rear; + + public TwoStackInOneArray() { + data = new Object[10]; + front = 0; + rear = 9; + capacity = 10; + } + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if (front == rear) { + expandCapacity(capacity * 2 + 1); + } + data[front] = o; + front++; + } + + private void expandCapacity(int newCapacity) { + Object[] old = data; + //将old中数据转移到data中 + data = new Object[newCapacity]; + //将前栈数据复制进去 + for (int i = 0; i < front; i++) { + data[i] = old[i]; + } + //将后栈数据复制进去 + int size = this.capacity - rear - 1; + for (int i = 0; i < size; i++) { + data[newCapacity - 1] = old[capacity - 1]; + } + capacity = newCapacity; + rear = newCapacity - size - 1; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + Object old = null; + if (front <= 0) { + throw new EmptyStackException(); + } + old = data[--front]; + data[front] = null; + return old; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if (front == 0) + return null; + //返回data[0] + int header = (int)data[0]; + //将前栈元素前移 +/* for (int i = 1; i < front; i++) { + data[i - 1] = data[i]; + } + front--; +*/ + return header; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if (front == rear) { + expandCapacity(capacity * 2 + 1); + } + data[rear] = o; + rear--; + } + + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + Object old = null; + if (rear >= capacity - 1) { + throw new EmptyStackException(); + } + old = data[++rear]; + data[rear] = null; + return old; + } + + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if (rear >= capacity - 1) + return null; + int header = (int)data[capacity - 1]; + return header; + } + +} diff --git a/group11/1178243325/week11/src/test/java/com/sprint/datastructure/QuickMinStackTest.java b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/QuickMinStackTest.java new file mode 100644 index 0000000000..7860868c1a --- /dev/null +++ b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/QuickMinStackTest.java @@ -0,0 +1,18 @@ +package com.sprint.datastructure; + +import org.junit.Test; +public class QuickMinStackTest { + + + @Test + public void test() { + QuickMinStack stack = new QuickMinStack(); + stack.push(8); + stack.push(9); + stack.push(7); + stack.push(2); + stack.pop(); + + System.out.println(stack.findMin()); + } +} diff --git a/group11/1178243325/week11/src/test/java/com/sprint/datastructure/StackWithTwoQueuesTest.java b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..647034d970 --- /dev/null +++ b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/StackWithTwoQueuesTest.java @@ -0,0 +1,18 @@ +package com.sprint.datastructure; + +import org.junit.Assert; +import org.junit.Test; +public class StackWithTwoQueuesTest { + + @Test + public void test() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + stack.push(1); + stack.push(2); + stack.push(3); + + Assert.assertEquals(3, stack.pop()); + Assert.assertEquals(2, stack.pop()); + Assert.assertEquals(1, stack.pop()); + } +} diff --git a/group11/1178243325/week11/src/test/java/com/sprint/datastructure/TwoStackInOneArrayTest.java b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..aff1d82a95 --- /dev/null +++ b/group11/1178243325/week11/src/test/java/com/sprint/datastructure/TwoStackInOneArrayTest.java @@ -0,0 +1,34 @@ +package com.sprint.datastructure; + +import org.junit.Assert; +import org.junit.Test; +public class TwoStackInOneArrayTest { + + TwoStackInOneArray stack = new TwoStackInOneArray(); + @Test + public void testStack() { + //测试前栈push , pop 并扩荣 + for (int i = 0; i < 20; i++) { + System.out.println(i); + stack.push1(i); + } + Assert.assertEquals(0, stack.peek1()); + Assert.assertEquals(21, stack.capacity); + stack.push2(0); + stack.push2(1); + stack.push2(2); + stack.push2(3); + System.out.println("Stack的容量:" + stack.capacity); + + Assert.assertEquals(19, stack.pop1()); + Assert.assertEquals(3, stack.pop2()); + + Assert.assertEquals(0, stack.peek2()); + } + + @Test + public void testRearStack() { + //原来不同的@Test里面会会重新初始化stack. + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/api/Connection.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/Connection.java new file mode 100644 index 0000000000..930cea370d --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/Connection.java @@ -0,0 +1,22 @@ +package com.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * ʼͽλãȡݣֵֽ + * @param startPos ʼλã 0ʼ + * @param endPos λ + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + /** + * õݵij + * @return + */ + public int getContentLength(); + /** + * ر + */ + public void close(); +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionException.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..35c8dc5758 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,7 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception{ + public ConnectionException(Exception e){ + super(e); + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionManager.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..bda19f285f --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * һ URLһ + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/api/DownloadListener.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..bf9807b307 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionImpl.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..efa9e562cd --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,73 @@ +package com.coderising.download.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; + +public class ConnectionImpl implements Connection{ + URL url; + static final int BUFFER_SIZE = 1024; + + ConnectionImpl(String _url) throws ConnectionException{ + try { + url = new URL(_url); + } catch (Exception e) { + throw new ConnectionException(e); + } + } + @Override + public byte[] read(int startPos, int endPos) throws IOException { + //ʼ + System.out.println("ʼ"); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + // öȡλ + httpConn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + // URLӻ + InputStream is = httpConn.getInputStream(); + + //is.skip(startPos); + byte[] buff = new byte[BUFFER_SIZE]; + int totalLen = endPos - startPos + 1; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while(baos.size() < totalLen){ + int len = is.read(buff); + if(len<0){ + break; + } + baos.write(buff,0,len); + } + + if(baos.size() > totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + return baos.toByteArray(); + } + + @Override + public int getContentLength() { + URLConnection con; + try { + con = url.openConnection(); + return con.getContentLength(); + } catch (Exception e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionManagerImpl.java b/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..ff92aa77fe --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,16 @@ +package com.coderising.download.impl; + +import java.net.URL; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager{ + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm.zip b/group11/1310368322/src/Mini_JVM/com/coderising/jvm.zip new file mode 100644 index 0000000000..6177632c3f Binary files /dev/null and b/group11/1310368322/src/Mini_JVM/com/coderising/jvm.zip differ diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java index e07662a68b..b09c94f55a 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java @@ -1,6 +1,8 @@ package com.coderising.jvm.attr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; import com.coderising.jvm.loader.ByteCodeIterator; public class CodeAttr extends AttributeInfo{ @@ -10,6 +12,12 @@ public class CodeAttr extends AttributeInfo{ private int codeLen; private String code; + private ByteCodeCommand[] cmds; + + public ByteCodeCommand[] getCmds(){ + return cmds; + } + public String getCode(){ return code; } @@ -21,12 +29,13 @@ public String getCode(){ - public CodeAttr(int attrNameIndex, int attrLen , int maxStack, int maxLocals, int codeLen,String code) { + 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) { @@ -50,7 +59,12 @@ public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ int codeLen = iter.nextU4toInt(); // code String code = iter.nextUxToHexString(codeLen); - CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, max_Locals, max_Locals, code); + System.out.println("code: " + code); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + System.out.println("cmds: ==== " + cmds.length); + System.out.println("CodeAttrеcmdijȣ " + cmds.length); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, max_Locals, max_Locals, code, cmds); int exceptionTableLen = iter.nextU2toInt(); diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassFile.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassFile.java index 4492d2df9e..adf0162155 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassFile.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassFile.java @@ -5,6 +5,7 @@ import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; @@ -92,4 +93,31 @@ private String getSuperClassName(){ return superClass.getClassName(); } + public Method getMethod(String methodName, String paramAndReturnType){ + for(Method m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + + public Method getMainMethod(){ + + for(Method m : methods){ + int nameIndex = m.getNameIndex(); + int descIndex = m.getDescriptorIndex(); + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descIndex); + if( name.equals("main") && desc.equals("([Ljava/lang/String;)V")){ + return m; + } + } + return null; + } + } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/BiPushCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..62359138ea --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +// bipush: ֽڵijֵ(-128 - 127) ջ +public class BiPushCmd extends OneOperandCmd{ + + protected BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/ByteCodeCommand.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..f9ccb52a97 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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.toUpperCase(); + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + System.out.println("opCode: " + opCode); + String txt = codeMap.get(opCode); + if(txt == null){ + System.out.println("txt: " + txt); + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/CommandParser.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..7f85fb5664 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,149 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + +public class CommandParser { + + public static final String aconst_null = "01";// nullջ + public static final String new_object = "BB";// һ󣬲ֵѹջ,ֽڹִӿڵķ + public static final String lstore = "37";// ջ long ֵ ָر + public static final String invokespecial = "B7";// ó๹췽ʵʼ˽з,byteڹǰʱijصָʱصһķ + 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";// int float String ͳֵӳջһֽһָintfloat͵ij + public static final String dup = "59";// ֵջջֵѹջ + public static final String bipush = "10";// byte չΪһ int ͵ֵ valueȻvalueѹ뵽ջһֽvalue + 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";// ڶintͱرջ + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25";// ĸfloatͱرջ + + public static final String voidreturn = "B1";// ޷ֵķ + public static final String ireturn = "AC";// ӵǰ int + public static final String freturn = "AE";// ӵǰ float + + public static final String astore_1 = "4C";//ջʹڶֲһNoOperand + 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";// iconst_0 int 0 ջ + 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 iter = new CommandIterator(codes); + List cmds = new ArrayList(); + while(iter.hasNext()){ + String opCode = iter.next2CharAsString(); + System.out.println("ֽ룺 opCode --- " + opCode); + if(new_object.equalsIgnoreCase(opCode)){// new ָ + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + System.out.println("cmd"); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + }else if(invokespecial.equalsIgnoreCase(opCode)){// invokespecial ָ + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(getfield.equalsIgnoreCase(opCode)){// getfield ָ + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + }else if(putfield.equalsIgnoreCase(opCode)){ + System.out.println("putfield"); + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(getstatic.equalsIgnoreCase(opCode)){ + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(invokevirtual.equalsIgnoreCase(opCode)){ + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(bipush.equalsIgnoreCase(opCode)){ + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(ldc.equalsIgnoreCase(opCode)){ + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + }else if(dup.equalsIgnoreCase(opCode) || aload_0.equalsIgnoreCase(opCode) || iconst_0.equalsIgnoreCase(opCode) || iconst_1.equalsIgnoreCase(opCode) || + aload_0.equalsIgnoreCase(opCode) || aload_1.equalsIgnoreCase(opCode) || aload_2.equalsIgnoreCase(opCode) || iload_1.equalsIgnoreCase(opCode) || + iload_2.equalsIgnoreCase(opCode) || iload_3.equalsIgnoreCase(opCode) || voidreturn.equalsIgnoreCase(opCode) || + astore_1.equalsIgnoreCase(opCode)){ + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + }else{ + System.out.println("the " + opCode+ "has not been implements"); + } + } + + calcuateOffset(cmds); + System.out.println("cmds.size ------ " + cmds.size()); + 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/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetFieldCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..d383c51497 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +public class GetFieldCmd extends TwoOperandCmd{ + + protected GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..fafe227dee --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +public class GetStaticFieldCmd extends TwoOperandCmd{ + + protected GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..300e0f68c6 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,18 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +public class InvokeSpecialCmd extends TwoOperandCmd{ + + protected InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..99dfbab1a9 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; + +public class InvokeVirtualCmd extends TwoOperandCmd{ + + protected InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool){ + return super.getOperandAsMethod(pool); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/LdcCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..6b110a8f47 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,48 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + }else{ + throw new RuntimeException("Only support StringInfo constant"); + } + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NewObjectCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..e2a31a2d9c --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + protected NewObjectCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool){ + return super.getOperandAsClassInfo(pool); + } + + public void execute(StackFrame frame, ExecutionResult result){ + + int index = this.getIndex();// + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + // Javaϴһʵ + JavaObject jo = Heap.getInstance().newObject(clzName); + frame.getOprandStack().push(jo);// ǰջ֡еIJջѹʵ + + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NoOperandCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..202e13419d --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class NoOperandCmd extends ByteCodeCommand{ + + protected NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public int getLength() { + return 1; + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + String opCode = this.getOpCode(); + + + + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/OneOperandCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..9d1f85005c --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.cmd; + +import com.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/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/PutFieldCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..59e5a09230 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,35 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd{ + + protected PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + public void execute(StackFrame frame, ExecutionResult result){ + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // example : name + String fieldName = nameTypeInfo.getName(); + // example : Ljava/lang/String + String fieldType = nameTypeInfo.getTypeInfo(); + + + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/TwoOperandCmd.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..44d232d2e5 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,86 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class TwoOperandCmd extends ByteCodeCommand{ + + // + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public int getOprand2() { + return oprand2; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + + protected 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(); + } + + @Override + public int getLength() { + return 3; + } + + @Override + public String toString(ConstantPool pool) { + return null; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java index 13fc4101a3..78210d1090 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class ClassInfo extends ConstantInfo{ private int type = ConstantInfo.CLASS_INFO;// ʾóΪ ӿڵķ @@ -28,6 +30,11 @@ public String getClassName(){ UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java index e20be200d6..87d6bfda12 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java @@ -30,5 +30,17 @@ public ConstantInfo getConstantInfo(int index){ // ContantInfo е getConstantInfo ͬ } + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visitUTF8(UTF8Info info); + } + + } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantPool.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantPool.java index 82565b7f59..11546afd64 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantPool.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantPool.java @@ -24,7 +24,7 @@ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize(){ + public int getSize(){ return constantInfos.size() - 1; } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/FieldRefInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/FieldRefInfo.java index 731c35b118..9e9136511e 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/FieldRefInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class FieldRefInfo extends ConstantInfo{ private int type = ConstantInfo.FIELD_INFO; @@ -50,6 +52,12 @@ public String getFieldType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(nameAndTypeIndex); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + visitor.visitFieldRef(this); + + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/MethodRefInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/MethodRefInfo.java index 49d89083fd..0931939a35 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/MethodRefInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class MethodRefInfo extends ConstantInfo{ private int type = ConstantInfo.METHOD_INFO; @@ -49,4 +51,10 @@ public String getParamAndReturnType(){ return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + + } + } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NameAndTypeInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NameAndTypeInfo.java index 8494e5e76a..93e4db9331 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class NameAndTypeInfo extends ConstantInfo{ public int type = ConstantInfo.NAME_AND_TYPE_INFO; @@ -48,5 +50,11 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo() + ")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java index f0be39e410..5237dd0ade 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class NullConstantInfo extends ConstantInfo{ public NullConstantInfo(){ @@ -9,5 +11,9 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java index 3ff8e9402b..f84782a7da 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class StringInfo extends ConstantInfo{ private int type = ConstantInfo.STRING_INFO; @@ -27,4 +29,11 @@ public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } + } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java index 6374764b5f..edfa5aeabd 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java @@ -1,5 +1,7 @@ package com.coderising.jvm.constant; +import com.coderising.jvm.constant.ConstantInfo.Visitor; + public class UTF8Info extends ConstantInfo{ private int type = ConstantInfo.UTF8_INFO; @@ -35,6 +37,12 @@ public void setValue(String value){ public String toString(){ return "UTF8Info [type=" + type + ",length" + length + ",value" + value + ")]"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitUTF8(this); + + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutionResult.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..7aefa17174 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action){ + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutorEngine.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..cd48c10186 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,70 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + + +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + List list = new ArrayList(); + public ExecutorEngine(){ + + } + + public void execute(Method mainMethod){ + + // mainջ֡ + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + + while(! stack.isEmpty() ){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod);// µջ֡ + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + + } else { + stack.pop(); + } + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + List paramList = nextMethod.getParameterList(); + // 1 ΪҪ this Ҳȥ + int paramNum = paramList.size() + 1; + + List values = new ArrayList(); + // ջȡ ջ X Ԫ + while(paramNum > 0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum--; + } + + // һб + List params = new ArrayList(); + for(int i = values.size() -1; i>=0; i--){ + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/Heap.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..e1907976be --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * ûʵգ Զ´Ķ ûм¼һݽṹ + */ + + private static Heap instance = new Heap(); + + private Heap(){ } + + public static Heap getInstance(){ + return instance; + } + + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/JavaObject.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..62fd2ce2a9 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,70 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MethodArea.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..8cc2ee2c37 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,88 @@ +package com.coderising.jvm.engine; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { +public static final MethodArea instance = new MethodArea(); + + /** + * ע⣺˼ļ򻯣 ClassLoader ֻһ ʵJVMеClassLoader,һ˫ίеģ + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) throws IOException{ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className) throws IOException{ + + if(map.get(className) != null){ + return map.get(className); + } + // class ļûload + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType) throws IOException{ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef) throws IOException{ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVM.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..43bfb6ec97 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.engine; + +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + +public class MiniJVM { + + public void run(String[] classPaths, String className) throws IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for (int i = 0; i < classPaths.length; i++) { + loader.addClassPath(classPaths[i]); + } + + MethodArea methodArea = MethodArea.getInstance(); + + methodArea.setClassFileLoader(loader); + + ExecutorEngine engine = new ExecutorEngine(); + + className = className.replace(".", "/"); + + engine.execute(methodArea.getMainMethod(className)); + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVMTest.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVMTest.java new file mode 100644 index 0000000000..1b70348d1a --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/MiniJVMTest.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.engine; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +public class MiniJVMTest { + + static final String PATH = "D:\\"; + + @Test + public void test() throws IOException { + String []classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "EmployeeV1"); + + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/StackFrame.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..877fd67d17 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/engine/StackFrame.java @@ -0,0 +1,115 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.method.Method; + +public class StackFrame { + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + private StackFrame(Method m) { + this.m = m; + + } + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //⣺ ΪʲôҪô + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileLoader.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileLoader.java index 6e479bbce9..c2328bcfba 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileLoader.java @@ -22,8 +22,9 @@ public class ClassFileLoader { * @ֽ */ public byte[] readBinaryCode(String className) throws IOException{ + System.out.println("className: " + className); DataInputStream dis = new DataInputStream( - new BufferedInputStream(new FileInputStream(className))); + new BufferedInputStream(new FileInputStream("D://EmployeeV1.class"))); for(int i = 0; dis.available() != 0; i++){ a[i] = dis.readByte(); countForReadBinaryCode++; diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/method/Method.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/method/Method.java index 572880f729..05a86d2c44 100644 --- a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/method/Method.java +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/method/Method.java @@ -1,8 +1,13 @@ package com.coderising.jvm.method; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public class Method { @@ -54,6 +59,7 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ System.out.println("attrCount: " + attrCount); // methodе for(int i = 0; i < attrCount; i++){ + System.out.println("ִеڣ " + i + ""); int attrNameIndex = iter.nextU2toInt(); String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); System.out.println(attrName); @@ -65,4 +71,52 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ } return method; } + + public ByteCodeCommand[] getCmds() { + return this.codeAttr.getCmds(); + } + + // õǩ[ ҲDzбͷֵ ] + private String getParamAndReturnType(){ + + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile().getConstantPool() + .getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList() { + + // e.g (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + + String param = paramAndType.substring(first+1, last);// ȡIJ + + java.util.List paramList = new ArrayList(); + + if( null == param || "".equals(param)){ + return paramList; + } + + while( !param.equals("")){ + + int pos = 0; + // һ + if( param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + if(end == -1){ + throw new RuntimeException("can not find the ;"); + } + paramList.add(param.substring(pos+1, end)); + pos = end + 1; + } + } + + + + return null; + } } diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ClassFilePrinter.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..82c1803b3c --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ClassFilePrinter.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.print; + +import java.io.IOException; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.loader.ClassFileLoader; + +public class ClassFilePrinter { + ClassFile clzFile = null; + public ClassFilePrinter(ClassFile clzFile){ + this.clzFile = clzFile; + } + + public void print(){ + + + /*System.out.println("Class Name:"+ clzFile.getClassName()); + + System.out.println("Super Class Name:"+ clzFile.getSuperClassName());*/ + //System.out.println("public class " + clzFile.getConstantPool().getConstantInfo(clzFile.getClzIndex().getThisClassIndex())); + + System.out.println("minor version:" + clzFile.getMinorVersion()); + System.out.println("major version:" + clzFile.getMajorVersion()); + if(clzFile.getAccessFlag().isPublicClass()){ + System.out.println("flags: public "); + } + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + } + + public static void main(String[] args) throws IOException{ + String path = "D:/ProgramWorld/Java/Practice/LangSi/2017Ⱥ/bin/com/coderising/jvm/loader/EmployeeV1.class"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(path); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ConstantPoolPrinter.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..4d71c51470 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,82 @@ +package com.coderising.jvm.print; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantInfo.Visitor; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitUTF8(UTF8Info info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Utf8 ").append(info.getValue()); + System.out.println(buffer); + + } + + @Override + public void visitString(StringInfo info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("NameAndTypeInfo #").append(info.getIndex1()).append( + info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("MethodRefInfo #").append(info.getClassInfoIndex()+"#").append( + info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append( + info.getNameAndTypeIndex()); + System.out.println(buffer); + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Class #").append(info.getUtf8Index()); + System.out.println(buffer); + } + }; + + for (int i = 1; i <= pool.getSize(); i++) { + ConstantInfo constatnInfo = pool.getConstantInfo(i); + System.out.print("#"+i+" = "); + constatnInfo.accept(visitor); + } + + + } +} diff --git a/group11/1310368322/src/data_structure/baseDataStructure_1/ArrayList.java b/group11/1310368322/src/data_structure/dataStructure_1/ArrayList.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_1/ArrayList.java rename to group11/1310368322/src/data_structure/dataStructure_1/ArrayList.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_1/LinkedList.java b/group11/1310368322/src/data_structure/dataStructure_1/LinkedList.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_1/LinkedList.java rename to group11/1310368322/src/data_structure/dataStructure_1/LinkedList.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_2/ArrayUtil.java b/group11/1310368322/src/data_structure/dataStructure_2/ArrayUtil.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_2/ArrayUtil.java rename to group11/1310368322/src/data_structure/dataStructure_2/ArrayUtil.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_3/LinkedList.java b/group11/1310368322/src/data_structure/dataStructure_3/LinkedList.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_3/LinkedList.java rename to group11/1310368322/src/data_structure/dataStructure_3/LinkedList.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_4_LRU/LRUPageFrame.java b/group11/1310368322/src/data_structure/dataStructure_4_LRU/LRUPageFrame.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_4_LRU/LRUPageFrame.java rename to group11/1310368322/src/data_structure/dataStructure_4_LRU/LRUPageFrame.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_5_Stack/StackUtil.java b/group11/1310368322/src/data_structure/dataStructure_5_Stack/StackUtil.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_5_Stack/StackUtil.java rename to group11/1310368322/src/data_structure/dataStructure_5_Stack/StackUtil.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java b/group11/1310368322/src/data_structure/dataStructure_6InfixExpr/InfixExpr.java similarity index 100% rename from group11/1310368322/src/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java rename to group11/1310368322/src/data_structure/dataStructure_6InfixExpr/InfixExpr.java diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/InfixToPostfix.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/InfixToPostfix.java new file mode 100644 index 0000000000..cfe418302b --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/InfixToPostfix.java @@ -0,0 +1,63 @@ +package dataStructure_7_PreAndPost; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr){ + + List result = new ArrayList(); + Stack operatorStack = new Stack(); + TokenParser parser = new TokenParser(); + List list = parser.parse(expr); + + for (Token token : list) { + + if(token.isNumber()){ + result.add(token); + }else if(token.isOperator()){ + + if(operatorStack.isEmpty()){ + operatorStack.push(token); + }else{ + + Token topOperator = operatorStack.pop(); + + if(!token.hasHigherPriority(topOperator)){ + list.add(topOperator); + while(true){ + if(!operatorStack.isEmpty()){ + Token top = operatorStack.pop(); + + if(!token.hasHigherPriority(top) && !operatorStack.isEmpty()){ + list.add(top); + }else{ + break; + } + } + + } + operatorStack.push(token); + }else{ + operatorStack.push(topOperator); + operatorStack.push(token); + } + + } + + } + } + + return result; + } + + public static void main(String[] args) { + + List result = convert("3+2*5+6"); + for (Token token : result) { + System.out.println(token); + } + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PostFixExpr.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PostFixExpr.java new file mode 100644 index 0000000000..603a797489 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PostFixExpr.java @@ -0,0 +1,47 @@ +package dataStructure_7_PreAndPost; + +import java.util.List; +import java.util.Stack; + +public class PostFixExpr { + + String expr = null; + + public PostFixExpr(String expr){ + this.expr = expr; + } + + public float evaluate(){ + //Stack operatorStack = new Stack(); + Stack operandStack = new Stack(); + TokenParser parser = new TokenParser(); + List list = parser.parse(expr); + for (Token token : list) { + if(token.isNumber()){ + Float operand = Float.parseFloat(token.toString()); + operandStack.push(operand); + }else if(token.isOperator()){ + Float operand = operandStack.pop(); + Float operanded = operandStack.pop(); + operandStack.push(calculate(token.toString(), operanded, operand)); + } + } + return operandStack.pop(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PreFixExpr.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PreFixExpr.java new file mode 100644 index 0000000000..ed3c4b889e --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/PreFixExpr.java @@ -0,0 +1,60 @@ +package dataStructure_7_PreAndPost; + +import java.util.List; +import java.util.Stack; + +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); + Stack operatorStack = new Stack(); + Stack operandStack = new Stack(); + + for(int i = tokens.size()-1; i >= 0; i--){ + if(tokens.get(i).isNumber()){ + operandStack.push(new Float(tokens.get(i).getIntValue())); + }else if(tokens.get(i).isOperator()){ + checkOperandStack(operandStack.size()); + Float operand = operandStack.pop(); + Float operanded = operandStack.pop(); + Float result = calculate(tokens.get(i).toString(),operand, operanded); + operandStack.push(result); + } + } + + return operandStack.pop(); + } + + private boolean checkOperandStack(int size) { + if(size < 2){ + throw new RuntimeException("ջеԪ̫"); + } + return true; + } + + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TestIntegerValueOf.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TestIntegerValueOf.java new file mode 100644 index 0000000000..fd870c9eeb --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TestIntegerValueOf.java @@ -0,0 +1,8 @@ +package dataStructure_7_PreAndPost; + +public class TestIntegerValueOf { + public static void main(String[] args) { + String s = "123"; + System.out.println(Integer.valueOf(s).intValue());// Ȱ String װ Integer Ȼתint + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/Token.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/Token.java new file mode 100644 index 0000000000..bb16a7c9e9 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/Token.java @@ -0,0 +1,66 @@ +package dataStructure_7_PreAndPost; + +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; + 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 int getIntValue(){ + return Integer.valueOf(value).intValue(); + } + + public String toString(){ + return value; + } + + public boolean hasHigherPriority(Token t){ + if( !this.isOperator() || !t.isOperator()){ + throw new RuntimeException("number can't compare priority"); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } + + + + + + + + + + + + + + +} diff --git a/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TokenParser.java b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TokenParser.java new file mode 100644 index 0000000000..dda9412e24 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_7_PreAndPost/TokenParser.java @@ -0,0 +1,55 @@ +package dataStructure_7_PreAndPost; + +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/group11/1310368322/src/data_structure/dataStructure_8_Queue/CircleQueue.java b/group11/1310368322/src/data_structure/dataStructure_8_Queue/CircleQueue.java new file mode 100644 index 0000000000..b5dd034ca2 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_8_Queue/CircleQueue.java @@ -0,0 +1,40 @@ +package dataStructure_8_Queue; + +public class CircleQueue { + + private final static int DEFAULT_SIZE = 5; + + // ѭеԪ + private Object [] elementData = new Object[DEFAULT_SIZE]; + + // ͷ + private int front = 0; + // β + private int rear = 0; + + + public Object getElementData(int index){ + return elementData[index]; + } + public boolean isEmpty(){ + return front==rear; + } + + public int size(){ + return rear-front; + } + + public void enQueue(E data){ + if((rear+1)%DEFAULT_SIZE == front){ + return; + }else{ + rear = (++rear)%DEFAULT_SIZE; + elementData[rear] = data; + } + } + + public E deQueue(){ + front = (++front)%DEFAULT_SIZE; + return (E) elementData[front]; + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_8_Queue/Josephus.java b/group11/1310368322/src/data_structure/dataStructure_8_Queue/Josephus.java new file mode 100644 index 0000000000..6877bbefa8 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_8_Queue/Josephus.java @@ -0,0 +1,36 @@ +package dataStructure_8_Queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * QueueʵJosephus + * ϵ⵱У Nݾһַͬʽ NΧһȦλüΪ0N-1 Ҵӵһ˱ M˻ᱻɱ ֱһ + * ÷һList ˱ɱ˵Ĵ + * @author liuxin + * + */ + +public class Josephus { + + + public static List execute(int n, int m){ + List list = new ArrayList(); + List listNew = new ArrayList(); + for (int i = 0; i < n; i++) { + list.add(i); + } + + int size = list.size(); + System.out.println(list.size()); + int index = 0; + while(size != 0){ + index += m-1; + index = index%size; + listNew.add(list.remove(index)); + size--; + } + + return listNew; + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_8_Queue/QueueWithTwoStack.java b/group11/1310368322/src/data_structure/dataStructure_8_Queue/QueueWithTwoStack.java new file mode 100644 index 0000000000..a0c37e9167 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_8_Queue/QueueWithTwoStack.java @@ -0,0 +1,53 @@ +package dataStructure_8_Queue; + +import java.util.Stack; + +/** + * ջʵһ + * @author liuxin + * @param + * + * @param + */ + +public class QueueWithTwoStack { + + private Stack stack1; + private Stack stack2; + private static int i = 0; + + public QueueWithTwoStack() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return false; + } + + public int size() { + return -1; + } + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(stack2.isEmpty()){ + moveStack1ToStack2(); + } + if(i!=0){ + return stack2.pop(); + } + return null; + } + + public void moveStack1ToStack2() { + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + i++; + } + } + +} diff --git a/group11/1310368322/src/data_structure/dataStructure_9_Stack/Queue.java b/group11/1310368322/src/data_structure/dataStructure_9_Stack/Queue.java new file mode 100644 index 0000000000..0cc93daa1c --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_9_Stack/Queue.java @@ -0,0 +1,61 @@ +package dataStructure_9_Stack; + +import java.util.NoSuchElementException; + + +public class Queue { + 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/group11/1310368322/src/data_structure/dataStructure_9_Stack/QuickMinStack.java b/group11/1310368322/src/data_structure/dataStructure_9_Stack/QuickMinStack.java new file mode 100644 index 0000000000..69fbc1735b --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_9_Stack/QuickMinStack.java @@ -0,0 +1,52 @@ +package dataStructure_9_Stack; + +import java.util.Stack; + +/** + * һջ֧ջpushpopԼֲfindMin, ظݽṹеСԪ + * finMinʱ临ӶӦO(1) һξͿԵõСֵ + * @author liuxin + * + */ +public class QuickMinStack { + + Stack stack = new Stack(); + Stack temp = new Stack(); + public void push(int data){ + + + if(stack.isEmpty()){ + stack.push(data); + temp.push(data); + }else{ + + if(data queue1 = new Queue(); + Queue queue2 = new Queue(); + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + if(queue1.isEmpty()){ + throw new RuntimeException("ջΪ"); + } + moveQueue1ToQueue2LeftLastOne(); + int pop = queue1.deQueue(); + moveQueue2ToQueue1(); + return pop; + } + + private void moveQueue2ToQueue1() { + while(!queue2.isEmpty()){ + queue1.enQueue(queue2.deQueue()); + } + + } + + private void moveQueue1ToQueue2LeftLastOne() { + while(queue1.size()!=1){ + queue2.enQueue(queue1.deQueue());; + } + } +} diff --git a/group11/1310368322/src/data_structure/dataStructure_9_Stack/TwoStackInOneArray.java b/group11/1310368322/src/data_structure/dataStructure_9_Stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..3b1c4ec8d2 --- /dev/null +++ b/group11/1310368322/src/data_structure/dataStructure_9_Stack/TwoStackInOneArray.java @@ -0,0 +1,89 @@ +package dataStructure_9_Stack; +import java.util.ArrayList; + +import javax.management.RuntimeErrorException; +/** + * һʵջ + * ʼλÿǵһջջףβڶջջףѹջʱջֱָмƶֱջָݡ + * @author liuxin + * + */ +public class TwoStackInOneArray { + + Object[] data = new Object[10]; + int i = 0;// һջ ջָ + int j = data.length-1;// ڶջջָ + public int getSize(){ + return data.length; + } + /** + * һջѹԪ + * @param o + */ + public void push1(Object o){ + ensureCapacity(); + System.out.println("i= " + i); + data[i++] = o; + } + + /** + * ӵһջеԪ + * @return + */ + public Object pop1(){ + if(i ==0 ){ + throw new RuntimeException("һջΪ"); + } + + return data[i--]; + } + + /** + * ȡһջջԪ + * @return + */ + + public Object peek1(){ + return data[i]; + } + /* + * ڶջѹԪ + */ + public void push2(Object o){ + ensureCapacity(); + System.out.println("j==" + j); + data[j--] = o; + } + /**b + * ӵڶջԪ + * @return + */ + public Object pop2(){ + return data[j++]; + } + /** + * ȡڶջջԪ + * @return + */ + + public Object peek2(){ + return data[j]; + } + + private void ensureCapacity() { + System.out.println("ensureCapacity: " + i + "" + j); + if(i >= j){ + data = grow(); + j = data.length - j; + } + + } + + private Object[] grow() { + Object[] dataNew = new Object[data.length*2]; + System.arraycopy(data, 0, dataNew, 0, i); + System.arraycopy(data, i, dataNew, dataNew.length-j, j); + return dataNew; + + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/basic/Stack.java b/group11/252308879/data-structure/src/main/java/com/pan/basic/Stack.java new file mode 100644 index 0000000000..fee417f7f0 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/basic/Stack.java @@ -0,0 +1,25 @@ +package com.pan.basic; + + +import java.util.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + } + + public Object pop(){ + return null; + } + + public Object peek(){ + return null; + } + public boolean isEmpty(){ + return false; + } + public int size(){ + return -1; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/download/DownloadThread.java b/group11/252308879/data-structure/src/main/java/com/pan/download/DownloadThread.java new file mode 100644 index 0000000000..8155031ad8 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/download/DownloadThread.java @@ -0,0 +1,42 @@ +package com.pan.download; + + + + +import com.pan.download.api.Connection; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class DownloadThread extends Thread { + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String localFile; + + public DownloadThread(Connection conn, int startPos, int endPos, String localFile, CyclicBarrier barrier) { + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.localFile = localFile; + this.barrier = barrier; + } + + public void run() { + try { + System.out.println("Begin to read [" + startPos + "-" + endPos + "]"); + byte[] data = conn.read(startPos, endPos); + RandomAccessFile file = new RandomAccessFile(localFile, "rw"); + file.seek(startPos); + file.write(data); + file.close(); + conn.close(); + System.out.println(this.currentThread().getName() + "once over"); + barrier.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/download/FileDownloader.java b/group11/252308879/data-structure/src/main/java/com/pan/download/FileDownloader.java new file mode 100644 index 0000000000..8da8be9f5d --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/download/FileDownloader.java @@ -0,0 +1,94 @@ +package com.pan.download; + + + +import com.pan.download.api.Connection; +import com.pan.download.api.ConnectionManager; +import com.pan.download.api.DownloadListener; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class FileDownloader { + + private String url; + private DownloadListener listener; + private ConnectionManager cm; + private static String LOCAL_FILE = "F:/xxx.jpg"; + + private static final int DOWNLOAD_THREAD_NUM = 3; + + public FileDownloader(String url) { + this.url = url; + } + // 当所有的Thread都调用 await方法时,会执行后面的 barrierAction,调用后面这个线程 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_THREAD_NUM,new Runnable() { + @Override + public void run() { + listener.notifyFinished(); + } + }); + + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + conn = cm.open(this.url); + int length = conn.getContentLength();// 拿到将要下载文件的长度 + RandomAccessFile file = new RandomAccessFile(LOCAL_FILE,"rw"); + for(int i = 0; i < length; i++){ + file.write(0); + } + file.close(); + int [][] ranges = new int[DOWNLOAD_THREAD_NUM][2]; + int eachThreadSize = length / DOWNLOAD_THREAD_NUM; + int left = length % DOWNLOAD_THREAD_NUM; + for(int i = 0; i totalSize) { + return Arrays.copyOf(data, totalSize); + } + return data; + } + + @Override + public int getContentLength() { + URLConnection con; + try { + con = url.openConnection(); + return con.getContentLength(); + } catch (Exception e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/download/impl/ConnectionManagerImpl.java b/group11/252308879/data-structure/src/main/java/com/pan/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..9e415863e3 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,25 @@ +package com.pan.download.impl; + + + + +import com.pan.download.api.Connection; +import com.pan.download.api.ConnectionManager; + +import java.io.IOException; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) { + try { + ConnectionImpl conn=null; + conn=new ConnectionImpl(url); + return conn; + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/utils/JaxpDomUtil.java b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/JaxpDomUtil.java similarity index 99% rename from group11/252308879/dataStructure/src/main/java/org/pan/coding2017/utils/JaxpDomUtil.java rename to group11/252308879/data-structure/src/main/java/com/pan/litestruts/JaxpDomUtil.java index d8fe537e35..e806d4fac6 100644 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/utils/JaxpDomUtil.java +++ b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/JaxpDomUtil.java @@ -1,4 +1,4 @@ -package org.pan.coding2017.utils; +package com.pan.litestruts; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; diff --git a/group11/252308879/data-structure/src/main/java/com/pan/litestruts/LoginAction.java b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/LoginAction.java new file mode 100644 index 0000000000..ca9c0a41a7 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package com.pan.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/litestruts/Struts.java b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/Struts.java new file mode 100644 index 0000000000..ca17b809ba --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/Struts.java @@ -0,0 +1,109 @@ +package com.pan.litestruts; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + + +public class Struts { + + public static View runAction(String actionName, Map parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + try { + Document document = JaxpDomUtil.getDocument(); + NodeList actionNodeList = document.getElementsByTagName("action"); + for (int i = 0; i < actionNodeList.getLength(); i++) { + NamedNodeMap attributes = actionNodeList.item(i).getAttributes(); + String methodName = attributes.getNamedItem("name").getTextContent(); + if (!actionName.equals(methodName)) { + continue; + } + // 获取全类名对象,反射创建对象 + String className = attributes.getNamedItem("class").getTextContent(); + Class actionClass = Class.forName(className); + + // 获取反射的方法名称, 因为是public修饰所以用的是getMethod,获取私有方法需要用 getDeclaredMethod + Method setName = actionClass.getMethod("setName", String.class); + Method setPassword = actionClass.getMethod("setPassword", String.class); + // 创建对象 + Object actionObject = actionClass.newInstance(); + + // 调用反射的setter方法,给参数赋值 + setName.invoke(actionObject, parameters.get("name")); + setPassword.invoke(actionObject, parameters.get("password")); + + // 获取execute方法 + Method execute = actionClass.getMethod("execute"); + // 返回结果 + String result = (String) execute.invoke(actionObject); + + // 获取getMessage方法 + Method getMessage = actionClass.getMethod("getMessage"); + String message = (String) getMessage.invoke(actionObject); + // 创建一个Map 用来放置在 View中 + Map params = new HashMap(); + params.put("message", message); + + // 获取返回的JSP路径,这个需要比较result节点的name属性 + //获取action的子节点 + NodeList resultNodes = actionNodeList.item(i).getChildNodes(); + String viewUrl = ""; + for (int n = 0; n < resultNodes.getLength(); n++) { + Node item = resultNodes.item(n); + NamedNodeMap resultAttributes = item.getAttributes(); + if (resultAttributes == null) { + continue; + } + String name = resultAttributes.getNamedItem("name").getTextContent(); + if (result.equals(name)) { + viewUrl = item.getTextContent(); + break; + } + } + View view = new View(); + view.setJsp(viewUrl); + view.setParameters(params); + return view; + } + + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + return null; + + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/litestruts/View.java b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/View.java new file mode 100644 index 0000000000..a57f4d50c3 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/litestruts/View.java @@ -0,0 +1,23 @@ +package com.pan.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/queue/CircleQueue.java b/group11/252308879/data-structure/src/main/java/com/pan/queue/CircleQueue.java new file mode 100644 index 0000000000..040df85d1f --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/queue/CircleQueue.java @@ -0,0 +1,46 @@ +package com.pan.queue; + +public class CircleQueue { + + //用数组来保存循环队列的元素 + private Object[] elementData ; + int size = 0; + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public CircleQueue(int capacity){ + elementData = new Object[capacity]; + } + public boolean isEmpty() { + return front == rear; + + } + + public boolean isFull(){ + return size == elementData.length; + } + public int size() { + return size; + } + + public void enQueue(E data) { + if(isFull()){ + throw new RuntimeException("The queue is full"); + } + elementData[rear++] = data; + size++; + } + + public E deQueue() { + if(isEmpty()){ + throw new RuntimeException("The queue is empty"); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front+1) % elementData.length; + size --; + return data; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/queue/Josephus.java b/group11/252308879/data-structure/src/main/java/com/pan/queue/Josephus.java new file mode 100644 index 0000000000..45e4b53526 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/queue/Josephus.java @@ -0,0 +1,39 @@ +package com.pan.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + + Queue queue = new Queue(); + for (int i = 0; i < n; i++){ + queue.enQueue(i); + } + + List result = new ArrayList(); + int i = 0; + + while (!queue.isEmpty()) { + + int x = queue.deQueue(); + + if (++i % m == 0){ + result.add(x); + } else{ + queue.enQueue(x); + } + } + + + return result; + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/queue/Queue.java b/group11/252308879/data-structure/src/main/java/com/pan/queue/Queue.java new file mode 100644 index 0000000000..fcd08e7a0c --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/queue/Queue.java @@ -0,0 +1,61 @@ +package com.pan.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group11/252308879/data-structure/src/main/java/com/pan/queue/QueueWithTwoStacks.java b/group11/252308879/data-structure/src/main/java/com/pan/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..0ef6f82625 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/queue/QueueWithTwoStacks.java @@ -0,0 +1,55 @@ +package com.pan.queue; + +import java.util.NoSuchElementException; +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + private void moveStack1ToStack2() { + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + + } + + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue is empty"); + } + if (stack2.isEmpty()) { + moveStack1ToStack2(); + } + + return stack2.pop(); + } + + + + } + diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/QuickMinStack.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/QuickMinStack.java new file mode 100644 index 0000000000..b665a680a4 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/QuickMinStack.java @@ -0,0 +1,19 @@ +package com.pan.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + public void push(int data){ + + } + public int pop(){ + return -1; + } + public int findMin(){ + return -1; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/StackWithTwoQueues.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..72a87b3b68 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/StackWithTwoQueues.java @@ -0,0 +1,16 @@ +package com.pan.stack; + + +public class StackWithTwoQueues { + + + public void push(int data) { + + } + + public int pop() { + return -1; + } + + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/TwoStackInOneArray.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..f00f36b2e6 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/TwoStackInOneArray.java @@ -0,0 +1,57 @@ +package com.pan.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return null; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + return null; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return null; + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/CalculateUtil.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/CalculateUtil.java new file mode 100644 index 0000000000..3eb1a9f6e9 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/CalculateUtil.java @@ -0,0 +1,27 @@ +package com.pan.stack.expr; + +import java.util.Stack; + +/** + * Created by Pan on 2017/5/7. + */ +public class CalculateUtil { + + + public static Float calculate(String op, Float f1, Float f2) { + if (op.equals("+")) { + return f1 + f2; + } + if (op.equals("-")) { + return f1 - f2; + } + if (op.equals("*")) { + return f1 * f2; + } + if (op.equals("/")) { + return f1 / f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixExpr.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..e7d8797eb6 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixExpr.java @@ -0,0 +1,56 @@ +package com.pan.stack.expr; + +import java.util.List; +import java.util.Stack; + + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for (Token token : tokens) { + + if (token.isOperator()) { + + while (!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())) { + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = CalculateUtil.calculate(prevOperator.toString(), f1, f2); + numStack.push(result); + + } + opStack.push(token); + } + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } + } + + while (!opStack.isEmpty()) { + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(CalculateUtil.calculate(token.toString(), f1, f2)); + } + + + return numStack.pop().floatValue(); + } + + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixToPostfix.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..df17c3af43 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/InfixToPostfix.java @@ -0,0 +1,40 @@ +package com.pan.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + List inFixTokens = new TokenParser().parse(expr); + + List postFixTokens = new ArrayList<>(); + + Stack opStack = new Stack(); + for (Token token : inFixTokens) { + + if (token.isOperator()) { + + while (!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())) { + postFixTokens.add(opStack.pop()); + + } + opStack.push(token); + + } + if (token.isNumber()) { + + postFixTokens.add(token); + + } + } + + while (!opStack.isEmpty()) { + postFixTokens.add(opStack.pop()); + } + + return postFixTokens; + } +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PostfixExpr.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..c649aa604b --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PostfixExpr.java @@ -0,0 +1,32 @@ +package com.pan.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack numStack = new Stack<>(); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push(new Float(token.getIntValue())); + } else { + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(CalculateUtil.calculate(token.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PrefixExpr.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..902ecfa0cb --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/PrefixExpr.java @@ -0,0 +1,38 @@ +package com.pan.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + Stack exprStack = new Stack<>(); + Stack numStack = new Stack<>(); + for (Token token : tokens) { + exprStack.push(token); + } + + while (!exprStack.isEmpty()) { + Token t = exprStack.pop(); + if (t.isNumber()) { + numStack.push(new Float(t.getIntValue())); + } else { + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(CalculateUtil.calculate(t.toString(), f1, f2)); + + } + } + return numStack.pop().floatValue(); + } + + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/Token.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/Token.java new file mode 100644 index 0000000000..f7db7d2a00 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/Token.java @@ -0,0 +1,53 @@ +package com.pan.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + 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/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/TokenParser.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/TokenParser.java new file mode 100644 index 0000000000..90338a98a8 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.pan.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/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeNode.java b/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..7860b6b0da --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeNode.java @@ -0,0 +1,35 @@ +package com.pan.tree; + +public class BinaryTreeNode { + + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(T data){ + this.data=data; + } + public T getData() { + return data; + } + public void setData(T data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeUtil.java b/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeUtil.java new file mode 100644 index 0000000000..c3c5301eb9 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/tree/BinaryTreeUtil.java @@ -0,0 +1,90 @@ +package com.pan.tree; + +import java.util.ArrayList; +import java.util.List; + +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + return result; + } + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + if (root != null){ + List leftResult = inOrderVisit(root.getLeft()); + result.add(root.getData()); +// result = leftResult; + List rightResult = inOrderVisit(root.getRight()); + } + return result; + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + return result; + } + /** + * 用非递归的方式实现对二叉树的前序遍历 + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + + return result; + } + /** + * 用非递归的方式实现对二叉树的中序遍历 + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + if (root == null){ + return result; + } + // 没有子节点 + if (root.getLeft() == null && root.getRight() == null){ + result.add(root.getData()); + return result; + } + + BinaryTreeNode leftDepth1 = root.getLeft(); + BinaryTreeNode leftDepthMax = leftDepth1.getLeft(); +// int leftDe + while (leftDepthMax != null){ + leftDepthMax = leftDepthMax.getLeft(); + } + + + + BinaryTreeNode rightDepth1 = root.getRight(); + + + return result; + } + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/tree/FileList.java b/group11/252308879/data-structure/src/main/java/com/pan/tree/FileList.java new file mode 100644 index 0000000000..bb25628a82 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/tree/FileList.java @@ -0,0 +1,28 @@ +package com.pan.tree; + +import java.io.File; + + +public class FileList { + + /** + * 给定一个目录,递归给出这个目录下的子目录和文件 + * @param file + */ + public void list(File file) { + String[] path = file.list(); + for (String pathItem : path) { + File fileTmp = new File(file.getAbsolutePath()+"\\"+pathItem); + if (fileTmp.isDirectory()){ + System.out.print("\t"); + System.out.println(fileTmp); + list(fileTmp); + }else { + System.out.print("\t\t"); + System.out.println(pathItem); + } + } + } + + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/download/FileDownloaderTest.java b/group11/252308879/data-structure/src/test/java/com/pan/download/FileDownloaderTest.java new file mode 100644 index 0000000000..6e8d059c3a --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/download/FileDownloaderTest.java @@ -0,0 +1,43 @@ +package com.pan.download; + +import com.pan.download.api.ConnectionManager; +import com.pan.download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + String url = "http://pic17.nipic.com/20111102/3707281_235344313129_2.jpg"; + + FileDownloader downloader = new FileDownloader(url); + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + downloader.setListener(() -> downloadFinished = true); + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/linklist/LRUPageFrameTest.java b/group11/252308879/data-structure/src/test/java/com/pan/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..e2d5325661 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.pan.linklist; + +import com.pan.linklist.LRUPageFrame; +import org.junit.Assert; +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/litestruts/StrutsTest.java b/group11/252308879/data-structure/src/test/java/com/pan/litestruts/StrutsTest.java new file mode 100644 index 0000000000..cc1a132d50 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.pan.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/queue/CircleQueueTest.java b/group11/252308879/data-structure/src/test/java/com/pan/queue/CircleQueueTest.java new file mode 100644 index 0000000000..1afe297c98 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/queue/CircleQueueTest.java @@ -0,0 +1,44 @@ +package com.pan.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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/queue/JosephusTest.java b/group11/252308879/data-structure/src/test/java/com/pan/queue/JosephusTest.java new file mode 100644 index 0000000000..a0c56cc12a --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.pan.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/stack/StackUtilTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/StackUtilTest.java new file mode 100644 index 0000000000..7969de3356 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/StackUtilTest.java @@ -0,0 +1,77 @@ +package com.pan.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Stack; + +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddToBottom() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack<>(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixExprTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..ff7f8cc0e6 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.pan.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixToPostfixTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..e46641122f --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/InfixToPostfixTest.java @@ -0,0 +1,41 @@ +package com.pan.stack.expr; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { + List tokens = InfixToPostfix.convert("2+3"); + Assert.assertEquals("[2, 3, +]", tokens.toString()); + } + { + + List tokens = InfixToPostfix.convert("2+3*4"); + Assert.assertEquals("[2, 3, 4, *, +]", tokens.toString()); + } + + { + + List tokens = InfixToPostfix.convert("2-3*4+5"); + Assert.assertEquals("[2, 3, 4, *, -, 5, +]", tokens.toString()); + } + } + +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PostfixExprTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..1ed273c5ab --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.pan.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/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PrefixExprTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..0e6c4513ed --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.pan.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/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/TokenParserTest.java b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..5e95bf95b1 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.pan.stack.expr; + +import static org.junit.Assert.*; + +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"); + + 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/group11/252308879/data-structure/src/test/java/com/pan/tree/BinaryTreeUtilTest.java b/group11/252308879/data-structure/src/test/java/com/pan/tree/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..ae2cb14f30 --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/tree/BinaryTreeUtilTest.java @@ -0,0 +1,73 @@ +package com.pan.tree; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class BinaryTreeUtilTest { + + BinaryTreeNode root = null; + @Before + public void setUp() throws Exception { + root = new BinaryTreeNode(1); + root.setLeft(new BinaryTreeNode(2)); + root.setRight(new BinaryTreeNode(5)); + root.getLeft().setLeft(new BinaryTreeNode(3)); + root.getLeft().setRight(new BinaryTreeNode(4)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + + + } + @Test + public void testInOrderVisit() { + + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[3, 2, 4, 1, 5]", result.toString()); + } + + @Test + public void testPostOrderVisit() { + + + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[3, 4, 2, 5, 1]", result.toString()); + + } + + + @Test + public void testInOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[3, 2, 6, 4, 7, 1, 5]", result.toString()); + + } + @Test + public void testPreOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 6, 7, 5]", result.toString()); + + } +} diff --git a/group11/252308879/data-structure/src/test/java/com/pan/tree/FileListTest.java b/group11/252308879/data-structure/src/test/java/com/pan/tree/FileListTest.java new file mode 100644 index 0000000000..be080a82ab --- /dev/null +++ b/group11/252308879/data-structure/src/test/java/com/pan/tree/FileListTest.java @@ -0,0 +1,19 @@ +package com.pan.tree; + +import org.junit.Test; + +import java.io.File; + +/** + * Created by Pan on. + * 2017/5/9 + */ +public class FileListTest { + + @Test + public void testFileList(){ + FileList fileList = new FileList(); + fileList.list(new File("E:\\DevWorkspace\\GitHub\\coding2017\\group11")); + } + +} diff --git a/group11/252308879/dataStructure/.gitignore b/group11/252308879/dataStructure/.gitignore deleted file mode 100644 index c7175f9b40..0000000000 --- a/group11/252308879/dataStructure/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -dataStructure/.classpath -dataStructure/.project -dataStructure/.settings/ - -.project -.settings/ -target/ -# 忽略IntelliJ IDEA配置文件 -*.iml -*.idea/ diff --git a/group11/252308879/dataStructure/pom.xml b/group11/252308879/dataStructure/pom.xml deleted file mode 100644 index 0bf21adba4..0000000000 --- a/group11/252308879/dataStructure/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ - - 4.0.0 - - org.apn.coding2017 - dataStructure - 1.0.0-SNAPSHOT - jar - - dataStructure - http://maven.apache.org - - - UTF-8 - - - - - junit - junit - 4.12 - test - - - junit - junit - RELEASE - - - dom4j - dom4j - 1.6.1 - - - diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/array/ArrayUtil.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/array/ArrayUtil.java deleted file mode 100644 index 82d7073a0f..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/array/ArrayUtil.java +++ /dev/null @@ -1,282 +0,0 @@ -package org.pan.coding2017.array; - -import java.util.Arrays; - -/** - * Created by QiPan on 2017/2/27. - */ -public class ArrayUtil { - - - /** - * 给定一个整形数组a , 对该数组的值进行置换 - * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] - * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * - * @param origin - * @return - */ - public static void reverseArray(int[] origin) { - - // 如果是null, 或者长度小于等于1, 直接返回 - if (origin == null || origin.length <= 1) { - return; - } - for (int i = 0; i < origin.length / 2; i++) { - int tmp = origin[i]; - origin[i] = origin[origin.length - 1 - i]; - origin[origin.length - 1 - i] = tmp; - } - } - - /** - * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: - * {1,3,4,5,6,6,5,4,7,6,7,5} - * - * @param oldArray - * @return - */ - - public static int[] removeZero(int[] oldArray) { - - if (oldArray == null) { - return oldArray; - } - int[] newArray = null; - int count = 0; //统计被移出的数组的个数 - for (int i = 0; i < oldArray.length; i++) { - int num = oldArray[i]; - if (num == 0) { - count++; - System.arraycopy(oldArray, i + 1, oldArray, i, oldArray.length - i - 1); - i--; - } - } - if (count == 0) { - newArray = oldArray; - } else { - newArray = new int[oldArray.length - count]; - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length - count); - } - return newArray; - } - - /** - * 不用JavaAPI来做 - * - * @param oldArray - * @return - */ - public static int[] removeZero_2(int[] oldArray) { - - if (oldArray == null) { - return oldArray; - } - int count = 0; - for (int num : oldArray) { - if (num == 0) { - count++; - } - } - int[] newArray = new int[oldArray.length - count]; - for (int i = 0, j = 0; i < oldArray.length; i++, j++) { - int num = oldArray[i]; - if (num == 0) { - j--; - } else { - newArray[j] = num; - } - } - return newArray; - } - - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 - * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - * - * @param array1 - * @param array2 - * @return - */ - public static int[] merge(int[] array1, int[] array2) { - //先初始化一个array3,但不是最后返回的数组 - int[] array3 = new int[array1.length + array2.length]; - int i = 0, j = 0; - int array3Size = 0; // 统计实际上合并数组后的大小 - while (i < array1.length && j < array2.length) { - if (array1[i] < array2[j]) {// 如果array1中元素小,则插入到array3中 - array3[array3Size++] = array1[i]; - ++i; - } else if (array1[i] > array2[j]) {//如果array2中元素小,则插入到array3中 - array3[array3Size++] = array2[j]; - ++j; - } else {//否则随便插入一个,但是计数要同时加1 - array3[array3Size++] = array1[i]; - ++i; - ++j; - } - } - - if (i == array1.length) { //如果array1中全部循环完毕了,那么需要去处理array2中剩余的元素 - for (int n = j; n < array2.length; n++) { - array3[array3Size++] = array2[n]; - } - } else if (j == array2.length) {// 如果array2中全部循环完毕,那么需要去处理array1中剩余的元素 - for (int n = i; n < array1.length; n++) { - array3[array3Size++] = array1[n]; - } - } - int[] returnResultArray = new int[array3Size]; - System.arraycopy(array3, 0, returnResultArray, 0, - array3Size); - return returnResultArray; - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * - * @param oldArray - * @param size - * @return - */ - public static int[] grow(int[] oldArray, int size) { - if (oldArray == null) { - oldArray = new int[size]; - } - oldArray = Arrays.copyOf(oldArray, oldArray.length + size); - return oldArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - * - * @param max - * @return - */ - public static int[] fibonacci(int max) { - if (max <= 1) { - return new int[0]; - } - int[] arrays = new int[max / 2]; - int firstNum = 1; //第一个数字 - int secondNum = 1; // 第二个数字 - int arraySize = 0; - arrays[arraySize++] = 1; // 初始化第一位 - while (secondNum < max) { - arrays[arraySize++] = secondNum; - int tmpNum = secondNum; // 保存第二个数,得会需要付给第一个数 - secondNum = firstNum + secondNum; // 为前两个数之和 - firstNum = tmpNum; // 第一个数,后移 - } - return Arrays.copyOf(arrays, arraySize); - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public static int[] getPrimes(int max) { - int[] returnResultArray = new int[max + 1]; - int arraySize = 0; - for (int i = 2; i < max; i++) { - if (isPrime(i)) { - returnResultArray[arraySize++] = i; - } - - } - if (arraySize == returnResultArray.length) { - return returnResultArray; - } - return Arrays.copyOf(returnResultArray, arraySize); - } - - private static boolean isPrime(final int number) { - if (number < 2) { - return false; - } - // 因为不可能将一个数除与所有小于它的数字,只要检查到N的平方根就好了。 - // 但直接开根号还有个精度的问题。这个可能会产生误差。 索性将判断条件写成 i*i<=number - for (int i = 2; i * i <= number; i++) { - if (number % i == 0) {//查看所有小于number平方根的数,能够被整除 - return false; - } - } - // 如果一个都没有,那么就是素数 - return true; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * - * @param max - * @return - */ - public static int[] getPerfectNumbers(int max) { - int[] array = new int[max]; - int arraySize = 0; - for (int n = 0; n < max; n++) { - int fac,// 被除的因子 - sum,// 用来统计因子之和 - num;// 除数的因子,中间变量 - for (sum = 1, num = n, fac = 2; fac < num; fac++) { - - if (n % fac == 0) {// 如果余数为0,那么说明有因子 - sum += fac; // 统计因子和 - num = n / fac; // num=等于除数的最大因子 - if (num == fac) // 如果最大和最小相等跳出循环 - break; - sum += num; // 再统计因子 - } - } - - if (sum == n) { //因子和与整数相等,那么就是一个完美数 - if (n != 1) { - System.out.println(n + "是一个完全数,其因子为:"); - } - for (fac = 1; fac < n; fac++) { - if (n % fac == 0) {// 列出所有的因子 - System.out.print(fac + " "); - } - } - System.out.println(); - array[arraySize++] = n; // 放到数组中 - } - } - return Arrays.copyOf(array, arraySize); - } - - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" - * - * @param array - * @param seperator - * @return - */ - public static String join(int[] array, String seperator) { - if (array == null) { - return null; - } - StringBuilder str = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - if (i == array.length - 1) { - str.append(array[i]); - continue; - } - str.append(array[i]).append(seperator); - } - return str.toString(); - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/ArrayList.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/ArrayList.java deleted file mode 100644 index 73dd4b7a5f..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/ArrayList.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.pan.coding2017.basic; - -import java.util.Arrays; -import java.util.NoSuchElementException; - -/** - * Created by QiPan on 2017/2/23. - */ -public class ArrayList implements List { - - private int size; - - // 设置默认容量 不可变 - private static final int DEFAULT_CAPACITY = 10; - - private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - - private Object[] elementData; - - // 定义一个默认的空的数组,引用不可变 - private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; - - public ArrayList(int initialCapacity) { - if (initialCapacity > 0) { - this.elementData = new Object[initialCapacity]; - } else if (initialCapacity == 0) { - this.elementData = new Object[]{}; - } else { - throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); - } - } - - public ArrayList() { // 如果调用默认构造函数,设置容器为空的默认数组 - this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; - } - - - public boolean add(Object o) { - ensureCapacityInternal(size + 1); - elementData[size++] = o; - return true; - } - - @Override - public boolean add(int index, Object o) { - if (index > size || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - ensureCapacityInternal(size + 1); - // 从插入位置开发,所有的数据需要往后移动 - System.arraycopy(elementData, index, elementData, index + 1, - size - index); - elementData[index] = o; - size++; - return true; - } - - public Object set(int index, Object element) { - checkIndexOutOf(index); - Object oldEle = elementData[index]; - elementData[index] = element; - return oldEle; - } - - public Object get(int index) { - checkIndexOutOf(index); - return elementData[index]; - } - - public Object remove(int index) { - checkIndexOutOf(index); - Object oldValue = elementData[index]; - - // 计算需要移动的位数 - int needMoveNum = size - index - 1; - - if (needMoveNum > 0) { - /* - * src:源数组; - * srcPos:源数组要复制的起始位置; - * dest:目的数组; - * destPos:目的数组放置的起始位置; - * length:复制的长度。 - */ - System.arraycopy(elementData, index + 1, elementData, index, needMoveNum); - } - // 避免对象游离,是的gcc能工作回收 - elementData[--size] = null; - return oldValue; - } - - public int size() { - return this.size; - } - - public boolean isEmpty() { - return this.size == 0; - } - - public Iterator iterator() { - return new Itr(); - } - - - private String outOfBoundsMsg(int index) { - return "Index: " + index + ", Size: " + size; - } - - /** - * 检查数组越界 - * - * @param index - */ - private void checkIndexOutOf(int index) { - if (index >= size) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - } - - private void ensureCapacityInternal(int minCapacity) { - // 如果是容器是默认的空的数组 - if (this.elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { - // 取得为与默认容量相比的较大值 - minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); - } - // 调用确保有能力放下那么多元素 - ensureExplicitCapacity(minCapacity); - } - - private void ensureExplicitCapacity(int minCapacity) { - // 防止容量溢出。所需的最小容器大于数组长度 - if (minCapacity - elementData.length > 0) { - grow(minCapacity); - } - } - - /** - * 扩充容量 - * - * @param minCapacity - */ - private void grow(int minCapacity) { - int oldCapacity = elementData.length; - // 得到一个新的容量大小,为 oldCapacity 的1.5倍 - int newCapacity = oldCapacity + (oldCapacity >> 1); - // 如果扩容后的大小比,最小容量(DEFAULT_CAPACITY: 10)小 - if (newCapacity - minCapacity < 0) { - newCapacity = minCapacity; - } else if (newCapacity - MAX_ARRAY_SIZE > 0) { // 扩容后比最大的还大,考虑溢出 - // - newCapacity = hugeCapacity(minCapacity); - } - - elementData = Arrays.copyOf(elementData, newCapacity); - } - - /** - * 这个很少用到这个判断,毕竟基本不会使用那么大容量存储 - * - * @param minCapacity - * @return - */ - private static int hugeCapacity(int minCapacity) { - if (minCapacity < 0) { - throw new OutOfMemoryError(); - } - return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; - } - - private class Itr implements Iterator { - - /** - * 当前游标 - */ - int cursor; - int lastRet = -1; // 是否是返回最后一个结果 - - @Override - public boolean hasNext() { - return cursor != size; - } - - @Override - public Object next() { - int i = cursor; - // 游标已经超过数组的大小 - if (i >= size) { - throw new NoSuchElementException(); - } - Object[] elementData = ArrayList.this.elementData; - - // 指向下一个元素 - cursor = i + 1; - Object elementDatum = elementData[i]; - lastRet = i; - return elementDatum; - } - - @Override - public void remove() { - if (lastRet < 0) { - throw new IllegalStateException(); - } - // 实际上这个时候的 lastRet,为 next方法时候的 i = cursor - ArrayList.this.remove(lastRet); - cursor = lastRet; - lastRet = -1; - } - } - - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/BinaryTreeNode.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/BinaryTreeNode.java deleted file mode 100644 index 80f7f78751..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/BinaryTreeNode.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by QiPan on 2017/2/23. - */ -public class BinaryTreeNode, Value> { - - private Node root; - - private class Node { - private Key key; - private Value value; - private Node left, right; //指向子树的链接 - private int N; // 以该节点为根的子树节点总数 - public Node(Key key, Value value, int N) { - this.key = key; - this.value = value; - this.N = N; - } - } - - public int size() { - return size(root); - } - - private int size(Node x) { - if (x == null) return 0; - else return x.N; - } - - public Value get(Key key){ - return get(root, key); - } - - private Value get(Node x, Key key) { - // 如果根节点也是Null 那么返回null - if (x == null){ - return null; - } - // 拿需要查询的key 与 根节点的 key 比较 - int cmp = key.compareTo(x.key); - if (cmp < 0){ // 如果小于0 那么去左子树上查询,并且递归调用 - return get(x.left, key); - }else if (cmp > 0){// 如果大于0 那么去右子树上查询,并且递归调用 - return get(x.right, key); - }else { - return x.value; - } - } - - public void push(Key key, Value value){ - // 查询key, 找到则更新它的值,否则就创建 - root = put(root, key, value); - } - - private Node put(Node x, Key key, Value value) { - // 如果key 存在于以 x 为根节点的子树中 则更新它的值 - // 否则将以key 和 value 为键值对的新节点插入到该子树中 - - if (x == null){ - return new Node(key, value, 1); - } - int cmp = key.compareTo(x.key); - if (cmp < 0 ){ - x.left = put(x.left, key, value); - }else if (cmp > 0){ - x.right = put(x.right, key, value); - }else { // 存在更新值 - x.value = value; - } - // 重新统计节点总数 - x.N = size(x.left) + size(x.right) + 1; - return x; - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Iterator.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Iterator.java deleted file mode 100644 index 3d1849f1a0..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Iterator.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by QiPan on 2017/2/23. - */ -public interface Iterator { - boolean hasNext(); - - Object next(); - - void remove(); -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/LinkedList.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/LinkedList.java deleted file mode 100644 index 015ac3d59d..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/LinkedList.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by QiPan on 2017/2/23. - */ -public class LinkedList { - - private Node head; - private int size; - public LinkedList() { - head = new Node(null, null); - size = 0; - } - - public void add(Object o){ - add(size, o); - } - - public void add(int index , Object o){ - if (index > size || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - Node frontNode = getNode(index-1); - Node newNode = new Node(o, frontNode.next); - frontNode.next = newNode; - size++; - - } - - private Node getNode(int index) { - Node node = head; - int i = 0; - while(node.next != null && i <= index) { - node = node.next; - i++; - } - return node; - } - - public Object get(int index){ - if (index >= size || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - - Node node = getNode(index); - return node.data; - } - - public Object remove(int index){ - if (index >= size || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - Node frontNode = getNode(index-1); - Node oldNode = getNode(index); - frontNode.next = oldNode.next; - size--; - return oldNode.data; - } - - public int size(){ - return size; - } - - public void addFirst(Object o){ - add(0, o); - } - - public void addLast(Object o){ - add(size, o); - } - - public Object removeFirst(){ - return remove(0); - } - - public Object removeLast(){ - return remove(size-1); - } - - public Iterator iterator(){ - return new LinkedListIterator(); - } - - private class LinkedListIterator implements Iterator { - int index; - final int capacity = size; - LinkedListIterator() { - index = 0; - } - @Override - public boolean hasNext() { - return index < capacity; - } - - @Override - public Object next() { - return get(index++); - } - - @Override - public void remove() { - - } - } - - private String outOfBoundsMsg(int index) { - return "index:" + index + ", size:" + size; - } - - private static class Node { - Object data; - Node next; - - Node(Object data, Node next) { - this.data = data; - this.next = next; - } - } - - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/List.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/List.java deleted file mode 100644 index 82e72e1080..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/List.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.pan.coding2017.basic; - - -/** - * Created by QiPan on 2017/2/23. - */ -public interface List { - - void add(Object o); - void add(int index, Object o); - Object get(int index); - Object remove(int index); - int size(); -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Queue.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Queue.java deleted file mode 100644 index af478b4288..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Queue.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by QiPan on 2017/2/23. - * 队列,链表实现版本 - */ -public class Queue { - - private Node first; - private Node last; - private int N; - - private class Node { - E item; - Node next; - } - - public void enQueue(E e) { - // 向表尾添加元素 - Node oldLast = last; - last = new Node(); - last.item = e; - last.next = null; - if (isEmpty()){// 如果是往空的队列里面添加东西。那么首尾链表都是指向第一个元素 - first = last; - }else { - - oldLast.next = last; - } - N++; - } - - public E deQueue() { - E item = first.item; - first = first.next; - if (isEmpty()){ - last = null; - } - N--; - return item; - } - - public boolean isEmpty() { - return first == null; - } - - public int size() { - return N; - } -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack.java deleted file mode 100644 index 918db8f70d..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by QiPan on 2017/2/23. - */ -public class Stack { - - private E[] elements; - // 记录元素当前位置 - private int N; - - public Stack(int cap) { - elements = (E[]) new Object[cap]; - } - - public boolean isEmpty() { - return N == 0; - } - - public int size() { - return N; - } - - public void push(E e) { - // 如果 N 和数组的长度已经相同,就进行扩容 - if (N == elements.length) { - resize(2 * elements.length); - } - elements[N++] = e; - } - - public E pop() { - E element = elements[--N]; - elements[N] = null;// 避免对象游离 - // 如果元素值剩下容量的1/4,那么就把数组容量变成现在的一半 - if (N > 0 && N == elements.length / 4) { - resize(elements.length / 2); - } - return element; - } - - private void resize(int max) { - E[] elementTmps = (E[]) new Object[max]; - for (int i = 0; i < N; i++) { - elementTmps[i] = elements[i]; - } - // 指向扩容的数组 - elements = elementTmps; - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack2.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack2.java deleted file mode 100644 index 2a056b8bbf..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic/Stack2.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.pan.coding2017.basic; - -/** - * Created by Pan on 2017/2/25. - * 栈(链表实现): 下压栈。操作栈顶元素 - */ -public class Stack2 { - - private Node first; - private int N; - - private class Node { - E item; - Node next; - } - - public boolean isEmpty(){ - return first == null; - } - - public int size(){ - return N; - } - - /** - * 向栈顶添加元素 - * @param element - */ - public void push (E element){ - Node oldFirst = first; - first = new Node(); - first.item = element; - first.next = oldFirst; - N++; - } - - /** - * 弹出栈顶元素 - * @return - */ - public E pop(){ - E item = first.item; - first = first.next; - N--; - return item; - } -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic2/LinkedList.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic2/LinkedList.java deleted file mode 100644 index 5286f27746..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/basic2/LinkedList.java +++ /dev/null @@ -1,429 +0,0 @@ -package org.pan.coding2017.basic2; - -import org.pan.coding2017.basic.Iterator; -import org.pan.coding2017.basic.List; - -public class LinkedList implements List { - - private Node head; - private Node tail; - private int size=0; - - private void checkIndex(int index){ - if(index<0 || index>=this.size) - { - throw new IndexOutOfBoundsException("Error!Invalid index:"+index); - } - } - - private void checkSize(){ - if(size==0) - { - throw new RuntimeException("Empty LinkedList."); - } - } - - public void add(Object o){ - Node temp = new Node(o,null); - if(this.head==null){ - this.head = temp; - this.tail = head; - }else{ - this.tail.next = temp; - this.tail = temp; - } - this.size++; - } - - /* (non-Javadoc) - * @see com.coding.basic2.List#add(int, java.lang.Object) - */ - public void add(int index , Object o){ - checkIndex(index); - if(index==0) - { - Node newNode = new Node(o,head); - head = newNode; - }else{ - Node temp = head; - for(int i=1;i0){ - Node temp = head; - sb.append(temp.data); - while(temp.hasNext()){ - temp = temp.next; - sb.append(","); - sb.append(temp.data); - } - } - return sb.toString(); - } - - public Object remove(int index){ - checkIndex(index); - Node temp = head; - Node pre = head; - Object result; - if(index == 0) - { - result = head.data; - head = head.next; - }else{ - for(int i=0;i0) - { - pre=pre.next; - } - temp=temp.next; - } - result = temp.data; - pre.next=temp.next; - temp = null; - - - if(index == size-1) - { - tail = pre; - } - } - size--; - - return result; - } - - public int size(){ - return this.size; - } - - public void addFirst(Object o){ - Node temp = new Node(o,head); - head = temp; - size++; - - } - public void addLast(Object o){ - Node temp = new Node(o,null); - tail.next = temp; - tail = temp; - size++; - } - public Object removeFirst(){ - return remove(0); - } - public Object removeLast(){ - return remove(size-1); - } - public Iterator iterator(){ - return new LinkedListIterator(); - } - - private class LinkedListIterator implements Iterator{ - private Node current = head; - - @Override - public boolean hasNext() - { - return current!=null; - } - - @Override - public Object next() { - if(current==null) - { - throw new RuntimeException("Current element has not next."); - } - - Object result = current.data; - current = current.next; - return result; - } - - @Override - public void remove() { - - } - - } - - - private static class Node{ - Object data; - Node next; - public boolean hasNext(){ - return (this.next!=null); - } - - public Node(Object data,Node next){ - this.data=data; - this.next=next; - } - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - checkSize(); - int tempSize = size; - Node temp = new Node(removeFirst(),null); - tail = temp; - while(size>0){ - temp = new Node(removeFirst(),temp); - } - head = temp; - size = tempSize; - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - checkSize(); - if(size>1) - { - int temp = size; - for(int i=0;isize-i) - { - throw new RuntimeException("No enough size to remove from index:"+i); - }else{ - for(int j=0;j101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public int[] getElements(LinkedList list){ - if(size==0||list.size==0){ - return new int[0]; - }else{ - int[] result = new int[list.size()]; - Node temp = head; - int currentPos = 0; - for(int i=0;ival){ - break; - }else if(tempVal==val){ - remove(j); - break; - }else{ - continue; - } - } - } - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - Node temp = head; - while(temp!=null){ - while(temp.hasNext()&&temp.data.equals(temp.next.data)) - { - temp.next = temp.next.next; - size--; - } - temp = temp.next; - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max){ - int headVal = (int)head.data; - int tailVal = (int)tail.data; - //if all the values in linkedList fall into the range, clean up; - if(min<=headVal && max>=tailVal) - { - System.out.println("min<=headVal && max>=tailVal"); - head = null; - tail = null; - size = 0; - }else{ - Node preRange = null; - Node sufRange = null; - Node temp = head; - int counter = 0; - while(temp!=null){ - if((int)temp.data=min) - { - preRange = temp; - System.out.println("Found preRange node, val="+temp.data+",next val="+temp.next.data); - } - if((int)temp.data>max){ - sufRange = temp; - System.out.println("Found sufRange node, val="+temp.data+",next val="+(temp.hasNext()?temp.next.data:null)); - break; - } - if((int)temp.data>=min && (int)temp.data<=max) - { - counter++; - } - System.out.println("Counter="+counter); - temp = temp.next; - } - if(min<=headVal){ - head = sufRange; - } - if(max>=tailVal){ - tail = preRange; - } - if(preRange!=null){ - preRange.next = sufRange; - } - size -= counter; - } - - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList intersection( LinkedList list){ - if(size==0 || list==null || list.size()==0) - { - return new LinkedList(); - }else{ - int pos1=0; - int pos2=0; - LinkedList result = new LinkedList(); - while(pos1val2) - { - if(pos2 downloadFinished = true); - downloader.execute(); - - // 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - //休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/Connection.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/Connection.java deleted file mode 100644 index 98046b6c8f..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/Connection.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api; - -import java.io.IOException; - -public interface Connection { - /** - * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * @param startPos 开始位置, 从0开始 - * @param endPos 结束位置 - * @return - */ - public byte[] read(int startPos, int endPos) throws IOException; - /** - * 得到数据内容的长度 - * @return - */ - public int getContentLength(); - - /** - * 关闭连接 - */ - public void close(); -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionException.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionException.java deleted file mode 100644 index cb3a1b6d0a..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionException.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api; - -public class ConnectionException extends Exception { - public ConnectionException(Exception e){ - super(e); - } -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionManager.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionManager.java deleted file mode 100644 index 4ac353f33d..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/ConnectionManager.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * @param url - * @return - */ - public Connection open(String url) throws ConnectionException; -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/DownloadListener.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/DownloadListener.java deleted file mode 100644 index 0de8c742d0..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api; - -public interface DownloadListener { - public void notifyFinished(); -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionImpl.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionImpl.java deleted file mode 100644 index d8639a5b6b..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api.impl; - -import org.pan.coding2017.multThreadDownload.api.Connection; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.util.Arrays; - - -public class ConnectionImpl implements Connection { - - private URL url; - private static final int BUFFER_SIZE = 1024; - - ConnectionImpl(){} - - ConnectionImpl(String url) throws MalformedURLException { - this.url = new URL(url); - } - - @Override - public byte[] read(int startPos, int endPos) throws IOException { - - HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); - urlConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - InputStream inputStream = urlConnection.getInputStream(); - - byte[] buff = new byte[BUFFER_SIZE]; - int totalSize = endPos - startPos + 1; - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - while (byteArrayOutputStream.size() < totalSize) { - int readSize = inputStream.read(buff); - if (readSize < 0) { - break; - } - byteArrayOutputStream.write(buff, 0, readSize); - } - byte[] data = byteArrayOutputStream.toByteArray(); - if (byteArrayOutputStream.size() > totalSize) { - return Arrays.copyOf(data, totalSize); - } - return data; - } - - @Override - public int getContentLength() { - URLConnection con; - try { - con = url.openConnection(); - return con.getContentLength(); - } catch (Exception e) { - e.printStackTrace(); - } - return -1; - } - - @Override - public void close() { - - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionManagerImpl.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionManagerImpl.java deleted file mode 100644 index 5a555652fc..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/multThreadDownload/api/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.pan.coding2017.multThreadDownload.api.impl; - - -import org.pan.coding2017.multThreadDownload.api.Connection; -import org.pan.coding2017.multThreadDownload.api.ConnectionManager; - -import java.io.IOException; - -public class ConnectionManagerImpl implements ConnectionManager { - - @Override - public Connection open(String url) { - try { - ConnectionImpl conn=null; - conn=new ConnectionImpl(url); - return conn; - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/LoginAction.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/LoginAction.java deleted file mode 100644 index f38cbcb084..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/LoginAction.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.pan.coding2017.parsingXML; - -/** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * @author liuxin - * - */ -public class LoginAction{ - private String name ; - private String password; - private String message; - - public String getName() { - return name; - } - - public String getPassword() { - return password; - } - - public String execute(){ - if("test".equals(name) && "1234".equals(password)){ - this.message = "login successful"; - return "success"; - } - this.message = "login failed,please check your user/pwd"; - return "fail"; - } - - public void setName(String name){ - this.name = name; - } - public void setPassword(String password){ - this.password = password; - } - public String getMessage(){ - return this.message; - } -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/Struts.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/Struts.java deleted file mode 100644 index 90c5443c23..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/Struts.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.pan.coding2017.parsingXML; - -import org.pan.coding2017.utils.JaxpDomUtil; -import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - - -public class Struts { - - public static View runAction(String actionName, Map parameters) { - - /* - - 0. 读取配置文件struts.xml - - 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) - 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 - ("name"="test" , "password"="1234") , - 那就应该调用 setName和setPassword方法 - - 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" - - 3. 通过反射找到对象的所有getter方法(例如 getMessage), - 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , - 放到View对象的parameters - - 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, - 放到View对象的jsp字段中。 - - */ - try { - Document document = JaxpDomUtil.getDocument(); - NodeList actionNodeList = document.getElementsByTagName("action"); - for (int i = 0; i < actionNodeList.getLength(); i++) { - NamedNodeMap attributes = actionNodeList.item(i).getAttributes(); - String methodName = attributes.getNamedItem("name").getTextContent(); - if (!actionName.equals(methodName)) { - continue; - } - // 获取全类名对象,反射创建对象 - String className = attributes.getNamedItem("class").getTextContent(); - Class actionClass = Class.forName(className); - - // 获取反射的方法名称, 因为是public修饰所以用的是getMethod,获取私有方法需要用 getDeclaredMethod - Method setName = actionClass.getMethod("setName", String.class); - Method setPassword = actionClass.getMethod("setPassword", String.class); - // 创建对象 - Object actionObject = actionClass.newInstance(); - - // 调用反射的setter方法,给参数赋值 - setName.invoke(actionObject, parameters.get("name")); - setPassword.invoke(actionObject, parameters.get("password")); - - // 获取execute方法 - Method execute = actionClass.getMethod("execute"); - // 返回结果 - String result = (String) execute.invoke(actionObject); - - // 获取getMessage方法 - Method getMessage = actionClass.getMethod("getMessage"); - String message = (String) getMessage.invoke(actionObject); - // 创建一个Map 用来放置在 View中 - Map params = new HashMap(); - params.put("message", message); - - // 获取返回的JSP路径,这个需要比较result节点的name属性 - //获取action的子节点 - NodeList resultNodes = actionNodeList.item(i).getChildNodes(); - String viewUrl = ""; - for (int n = 0; n < resultNodes.getLength(); n++) { - Node item = resultNodes.item(n); - NamedNodeMap resultAttributes = item.getAttributes(); - if (resultAttributes == null) { - continue; - } - String name = resultAttributes.getNamedItem("name").getTextContent(); - if (result.equals(name)) { - viewUrl = item.getTextContent(); - break; - } - } - View view = new View(); - view.setJsp(viewUrl); - view.setParameters(params); - return view; - } - - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - return null; - - } - -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/StrutsTest.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/StrutsTest.java deleted file mode 100644 index ccdacc514c..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/StrutsTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.pan.coding2017.parsingXML; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - - - - - -public class StrutsTest { - - @Test - public void testLoginActionSuccess() { - - String actionName = "login"; - - Map params = new HashMap(); - params.put("name","test"); - params.put("password","1234"); - - - View view = Struts.runAction(actionName,params); - - Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); - Assert.assertEquals("login successful", view.getParameters().get("message")); - } - - @Test - public void testLoginActionFailed() { - String actionName = "login"; - Map params = new HashMap(); - params.put("name","test"); - params.put("password","123456"); //密码和预设的不一致 - - View view = Struts.runAction(actionName,params); - - Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); - Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); - } -} diff --git a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/View.java b/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/View.java deleted file mode 100644 index 3271ab4ed1..0000000000 --- a/group11/252308879/dataStructure/src/main/java/org/pan/coding2017/parsingXML/View.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.pan.coding2017.parsingXML; - -import java.util.Map; - -public class View { - private String jsp; - private Map parameters; - - public String getJsp() { - return jsp; - } - public View setJsp(String jsp) { - this.jsp = jsp; - return this; - } - public Map getParameters() { - return parameters; - } - public View setParameters(Map parameters) { - this.parameters = parameters; - return this; - } -} diff --git a/group11/252308879/dataStructure/src/main/resources/struts.xml b/group11/252308879/dataStructure/src/main/resources/struts.xml deleted file mode 100644 index 35830922ba..0000000000 --- a/group11/252308879/dataStructure/src/main/resources/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/TestJavaUtilArrayList.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/TestJavaUtilArrayList.java deleted file mode 100644 index 281a5bf07b..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/TestJavaUtilArrayList.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.pan.coding2017; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by QiPan on 2017/2/23. - */ -public class TestJavaUtilArrayList { - - - @Test - public void testAdd() { - List arrayList = new ArrayList(5); - arrayList.add(new Object()); - System.out.println("sssssssssssss"); - } - - @Test - public void testRightShift() { - int x = 5; - - x = x << 1; - x = x >> 1; - System.out.println(x); - } - -} diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/array/ArrayUtilTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/array/ArrayUtilTest.java deleted file mode 100644 index 29ab6bf6dc..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/array/ArrayUtilTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.pan.coding2017.array; - -import org.junit.Test; - -import java.util.Arrays; - -/** - * Created by QiPan on 2017/2/27. - */ -public class ArrayUtilTest { - - @Test - public void removeZero() throws Exception { - int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; - System.out.println("removeZero 移除0之前: "+ Arrays.toString(oldArr)); - int[] newArrays = ArrayUtil.removeZero(oldArr); - System.out.println("removeZero 移除0之后: "+ Arrays.toString(newArrays)); - } - - @Test - public void removeZero_2() throws Exception { - int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; - System.out.println("removeZero_2 移除0之前: "+ Arrays.toString(oldArr)); - int[] newArrays = ArrayUtil.removeZero_2(oldArr); - System.out.println("removeZero_2 移除0之后: "+ Arrays.toString(newArrays)); - } - - @Test - public void reverseArray() throws Exception { - int[] array = new int[]{7, 9 , 30, 3}; - int[] array2 = new int[] {7, 9, 30, 3, 4}; - System.out.println("置换前: " + Arrays.toString(array)); - ArrayUtil.reverseArray(array); - System.out.println("置换后: "+ Arrays.toString(array)); - System.out.println("置换前: " + Arrays.toString(array2)); - ArrayUtil.reverseArray(array2); - System.out.println("置换后: "+ Arrays.toString(array2)); - } - - @Test - public void merge() throws Exception { - int[] a1 = {3, 5, 7,8}, a2 = {4, 5, 6,7}; - //则 a3 为[3,4,5,6,7,8] - int[] merge = ArrayUtil.merge(a1, a2); - System.out.println(Arrays.toString(merge)); - } - - @Test - public void grow() throws Exception { - int[] oldArray = {2,3,6} ; - int size = 3; - System.out.println("grow 之前:"+ Arrays.toString(oldArray)); - int[] newArrays = ArrayUtil.grow(oldArray, size); - System.out.println("grow 之后:"+ Arrays.toString(newArrays)); - - } - - @Test - public void fibonacci() throws Exception { - //max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - int[] fibonacci = ArrayUtil.fibonacci(988); - System.out.println(Arrays.toString(fibonacci)); - } - - @Test - public void getPrimes() throws Exception { - //例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - int[] primes = ArrayUtil.getPrimes(23); - System.out.println(Arrays.toString(primes)); - } - - @Test - public void getPerfectNumbers() throws Exception { - int[] primes = ArrayUtil.getPerfectNumbers(10000); - System.out.println(Arrays.toString(primes)); - } - - @Test - public void join() throws Exception { - int [] array= {3,8,9}; - String seperator = "-"; - String result = ArrayUtil.join(array, seperator); - System.out.println(result); - } - - - - -} \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/ArrayListTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/ArrayListTest.java deleted file mode 100644 index f93876522a..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/ArrayListTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.pan.coding2017.basic; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by Pan on 2017/2/26. - */ -public class ArrayListTest { - - ArrayList arrayList; - - @Before - public void before(){ - arrayList = new ArrayList(); - arrayList.add(1); - arrayList.add(2); - arrayList.add(3); - } - - @Test - public void add() throws Exception { - ArrayList arrayList = new ArrayList(); - arrayList.add(3); - System.out.println(arrayList); - } - - @Test - public void set() throws Exception { - arrayList.add(3); - arrayList.set(0, 4); - System.out.println(arrayList); - } - - @Test - public void get() throws Exception { - arrayList.add(1); - arrayList.add(2); - arrayList.add(3); - Object o = arrayList.get(1); - System.out.println(o); - } - - @Test - public void remove() throws Exception { - arrayList.add(1); - arrayList.add(2); - arrayList.add(3); - arrayList.remove(1); - System.out.println(arrayList); - } - - @Test - public void size() throws Exception { - System.out.println(arrayList.size()); - } - - @Test - public void isEmpty() throws Exception { - System.out.println(arrayList.isEmpty()); - } - - @Test - public void iterator() throws Exception { - Iterator iterator = arrayList.iterator(); - while (iterator.hasNext()){ - Object next = iterator.next(); - System.out.println(next); - iterator.remove(); - } - System.out.println(arrayList.isEmpty()); - } - -} \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/BinaryTreeNodeTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/BinaryTreeNodeTest.java deleted file mode 100644 index 4c3c01cd73..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/BinaryTreeNodeTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.pan.coding2017.basic; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by Pan on 2017/2/26. - */ -public class BinaryTreeNodeTest { - - BinaryTreeNode binaryTreeNode; - - @Before - public void setUp() throws Exception { - binaryTreeNode = new BinaryTreeNode(); - binaryTreeNode.push(1, "A"); - binaryTreeNode.push(2, "B"); - binaryTreeNode.push(3, "C"); - binaryTreeNode.push(4, "D"); - } - - @Test - public void size() throws Exception { - System.out.println(binaryTreeNode.size()); - } - - @Test - public void get() throws Exception { - System.out.println(binaryTreeNode.get(3)); - } - - @Test - public void push() throws Exception { - binaryTreeNode.push(5, "E"); - System.out.println(binaryTreeNode); - } - -} \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/LinkedListTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/LinkedListTest.java deleted file mode 100644 index 135e052218..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/LinkedListTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.pan.coding2017.basic; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by Pan on 2017/2/26. - */ -public class LinkedListTest { - - org.pan.coding2017.basic2.LinkedList linkedList; - - @Before - public void setUp() throws Exception { - linkedList = new org.pan.coding2017.basic2.LinkedList(); - linkedList.add(0); - linkedList.add(1); - linkedList.add(2); - linkedList.add(3); - } - - @Test - public void add() throws Exception { - linkedList.add(0); - System.out.println(linkedList); - } - - @Test - public void get() throws Exception { - Object o = linkedList.get(1); - System.out.println(o); - } - - @Test - public void remove() throws Exception { - linkedList.remove(1); - System.out.println(linkedList); - } - - @Test - public void size() throws Exception { - System.out.println(linkedList.size()); - } - - @Test - public void addFirst() throws Exception { - linkedList.addFirst(4); - System.out.println(linkedList); - } - - @Test - public void addLast() throws Exception { - linkedList.addLast(5); - System.out.println(linkedList); - } - - @Test - public void removeFirst() throws Exception { - linkedList.removeFirst(); - System.out.println(linkedList); - } - - @Test - public void removeLast() throws Exception { - linkedList.removeLast(); - System.out.println(linkedList); - } - - @Test - public void iterator() throws Exception { - Iterator iterator = linkedList.iterator(); - while (iterator.hasNext()){ - Object next = iterator.next(); - System.out.println(next); - iterator.remove(); - } - System.out.println(linkedList); - } - -} \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/QueueTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/QueueTest.java deleted file mode 100644 index c720e7d95e..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/QueueTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.pan.coding2017.basic; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by Pan on 2017/2/26. - */ -public class QueueTest { - - Queue queue; - - @Before - public void setUp() throws Exception { - queue = new Queue(); - queue.enQueue(1); - queue.enQueue(2); - queue.enQueue(3); - - } - - @Test - public void enQueue() throws Exception { - queue.enQueue(1); - System.out.println(queue); - } - - @Test - public void deQueue() throws Exception { - queue.deQueue(); - System.out.println(queue); - } - - @Test - public void isEmpty() throws Exception { - System.out.println(queue.isEmpty()); - } - - @Test - public void size() throws Exception { - System.out.println(queue.size()); - } - -} \ No newline at end of file diff --git a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/StackTest.java b/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/StackTest.java deleted file mode 100644 index df85b797d4..0000000000 --- a/group11/252308879/dataStructure/src/test/java/org/pan/coding2017/basic/StackTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.pan.coding2017.basic; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by Pan on 2017/2/26. - */ -public class StackTest { - - Stack stack; - - @Before - public void setUp() throws Exception { - stack = new Stack(3); - stack.push(1); - stack.push(2); - stack.push(3); - } - - @Test - public void isEmpty() throws Exception { - System.out.println(stack.isEmpty()); - } - - @Test - public void size() throws Exception { - System.out.println(stack.size()); - } - - @Test - public void push() throws Exception { - stack.push(1); - stack.push(2); - stack.push(3); - System.out.println(stack); - } - - @Test - public void pop() throws Exception { - stack.pop(); - System.out.println(stack); - } - -} \ No newline at end of file diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/alg/LRUPageFrame.java b/group11/252308879/mini-jvm/src/main/java/com/pan/alg/LRUPageFrame.java deleted file mode 100644 index d9455d3807..0000000000 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/alg/LRUPageFrame.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.pan.alg; - - -/* - * 用双向链表实现LRU算法 - */ -public class LRUPageFrame { - private static class Node{ - Node prev; - Node next; - int pageNum = -1;// 物理页 - - Node(){ - - } - } - - private int capacity; - - private Node first;// 链表头 - private Node last;// 链表尾 - boolean tag = false; - - public LRUPageFrame(int capacity){ - this.capacity = capacity; - - for(int i = 0; i < capacity; i++){ - Node curNode = new Node(); - if(null == first){ - last = first = curNode; - }else{ - last.next = curNode; - curNode.prev = last; - last = last.next; - } - last.next = null; - } - } - public void printList(){ - Node curNode = first; - while(curNode != null){ - curNode = curNode.next; - } - } - /* - * 获取缓存中对象 - * @param key - * @return - */ - public void access(int pageNum){ - printList(); - Node index = findLogicPage(pageNum); - modifyPhysicalPage(index,pageNum); - } - - /* - * @param pageNum 表示要查询的逻辑页面 - * @return 若在物理页中找到要查询的逻辑页面,则返回该物理页节点的引用,否则返回null - */ - public Node findLogicPage(int pageNum){ - - Node index = null; - Node curNode = first; - while(curNode != null){ - if(curNode.pageNum == pageNum){ - index = curNode; - tag = true; - } - curNode = curNode.next; - } - return index; - } - /* - * @prama index 代表了 有逻辑页的物理页的节点的引用 - */ - public void modifyPhysicalPage(Node index,int pageNum){ - push(pageNum,index); - } - /* - * @param pageNum 要 push的逻辑页面, 默认栈顶是 first, bottom 栈底 指定了栈的大小 - */ - public void push(int pageNum,Node bottom){ - Node index = checkWhichListNodeNotUsed(); - if(index != null){ - index.pageNum = pageNum; - return; - } - - Node lastNode; - if(null == bottom){ - lastNode = last; - }else{ - lastNode = bottom; - } - Node curNode = lastNode.prev; - while(curNode != null){ - lastNode.pageNum = curNode.pageNum; - lastNode = curNode; - curNode = curNode.prev; - } - lastNode.pageNum = pageNum; - return; - } - - /* - * @return 返回物理页中 pageNum 没有被使用的节点的引用(返回栈中最下面的),如果全部都被使用,则返回 null - */ - public Node checkWhichListNodeNotUsed(){ - Node node = first; - Node index = null; - while(node != null){ - if(node.pageNum == -1){ - index = node; - } - node = node.next; - } - return index; - } - - public String toString(){ - StringBuffer buffer = new StringBuffer(); - Node node = first; - while(node != null){ - buffer.append(node.pageNum); - - node = node.next; - if(node != null){ - buffer.append(","); - } - } - return buffer.toString(); - } -} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/alg/StackUtil.java b/group11/252308879/mini-jvm/src/main/java/com/pan/alg/StackUtil.java deleted file mode 100644 index 01a7f2da52..0000000000 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/alg/StackUtil.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.pan.alg; - - -import java.util.Stack; - -/** - * Created by QiPan on 2017/4/12. - */ -public class StackUtil { - - public static void bad_reverse(Stack s) { - if(s == null || s.isEmpty()){ - return; - } - Stack tmpStack = new Stack<>(); - while(!s.isEmpty()){ - tmpStack.push(s.pop()); - } - - s = tmpStack; - - } - - /** - * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 - * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - */ - public static void reverse(Stack s) { - if(s == null || s.isEmpty()){ - return; - } - Integer top = s.pop(); - reverse(s); - addToBottom(s,top); - - - } - public static void addToBottom(Stack s, Integer value){ - if(s.isEmpty()){ - s.push(value); - } else{ - Integer top = s.pop(); - addToBottom(s,value); - s.push(top); - } - - } - /** - * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - * - * @param o - */ - public static void remove(Stack s,Object o) { - if(s == null || s.isEmpty()){ - return; - } - Stack tmpStack = new Stack(); - - while(!s.isEmpty()){ - Object value = s.pop(); - if(!value.equals(o)){ - tmpStack.push(value); - } - } - - while(!tmpStack.isEmpty()){ - s.push(tmpStack.pop()); - } - } - - /** - * 从栈顶取得len个元素, 原来的栈中元素保持不变 - * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - * @param len - * @return - */ - public static Object[] getTop(Stack s,int len) { - - if(s == null || s.isEmpty() || s.size() stack = new Stack<>(); - for(int i=0;i 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 getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/CommandParser.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..a410ab2e85 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/CommandParser.java @@ -0,0 +1,129 @@ +package com.pan.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.pan.jvm.clz.ClassFile; + +public class CommandParser { + + + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + + if ((codes == null) || (codes.length() == 0) || (codes.length() % 2) != 0) { + throw new RuntimeException("the orignal code is not correct"); + + } + + codes = codes.toUpperCase(); + + CommandIterator iter = new CommandIterator(codes); + List cmds = new ArrayList(); + + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + + if (ByteCodeCommand.new_object.equals(opCode)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); + + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (ByteCodeCommand.invokespecial.equals(opCode)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + // System.out.println( cmd.toString(clzFile.getConstPool())); + cmds.add(cmd); + } else if (ByteCodeCommand.invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + + cmds.add(cmd); + } else if (ByteCodeCommand.getfield.equals(opCode)) { + GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.getstatic.equals(opCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.putfield.equals(opCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.ldc.equals(opCode)) { + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.bipush.equals(opCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (ByteCodeCommand.dup.equals(opCode) + || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) + || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) + || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) + || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); + cmds.add(cmd); + } else { + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); + } + + } + + 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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetFieldCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..a54a2f5fb8 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,38 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + + } + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetStaticFieldCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..0e44f1d8d5 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,42 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.constant.UTF8Info; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.Heap; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeSpecialCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..7cb42656eb --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,47 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.MethodArea; +import com.pan.jvm.engine.StackFrame; +import com.pan.jvm.method.Method; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + + + } + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeVirtualCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..ff43748c0d --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,86 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.MethodArea; +import com.pan.jvm.engine.StackFrame; +import com.pan.jvm.method.Method; + + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/LdcCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..a42b80a9b3 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/LdcCmd.java @@ -0,0 +1,50 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ConstantInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.StringInfo; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.Heap; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + ConstantInfo info = 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; + + } + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NewObjectCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..a5621d0f0d --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,39 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.Heap; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + + + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NoOperandCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..0605c466bd --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,146 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.Heap; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } + + + public int getLength(){ + return 1; + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/OneOperandCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..850d3e8d0b --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.pan.jvm.cmd; + +import com.pan.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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/PutFieldCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..ddd6007d46 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,44 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.constant.NameAndTypeInfo; +import com.pan.jvm.engine.ExecutionResult; +import com.pan.jvm.engine.JavaObject; +import com.pan.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/TwoOperandCmd.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..03771eabae --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.pan.jvm.cmd; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.constant.MethodRefInfo; + +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(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(){ + 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(){ + 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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ClassInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ClassInfo.java index b842755586..84b00f189d 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ClassInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ClassInfo.java @@ -2,27 +2,27 @@ public class ClassInfo extends ConstantInfo { private int type = ConstantInfo.CLASS_INFO; - private int utf8Index; - + 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); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantInfo.java index 464e44a79d..cc5fa84388 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantInfo.java @@ -28,4 +28,16 @@ public ConstantInfo getConstantInfo(int index) { return this.constantPool.getConstantInfo(index); } + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } + } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantPool.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantPool.java index c2da2637c5..f612dd6289 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantPool.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantPool.java @@ -26,7 +26,7 @@ public String getUTF8String(int index) { return ((UTF8Info) this.constantInfos.get(index)).getValue(); } - public Object getSize() { - return this.constantInfos.size() - 1; + public int getSize() { + return this.constantInfos.size() -1; } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/FieldRefInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/FieldRefInfo.java index 2aaced31d3..80e7a4054d 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/FieldRefInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/FieldRefInfo.java @@ -8,7 +8,6 @@ public class FieldRefInfo extends ConstantInfo { public FieldRefInfo(ConstantPool pool) { super(pool); } - public int getType() { return type; } @@ -16,43 +15,44 @@ public int getType() { 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() { + public String toString(){ - NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); - return getClassName() + " : " + typeInfo.getName() + ":" + typeInfo.getTypeInfo() + "]"; + return getClassName() +" : "+ typeInfo.getName() + ":" + typeInfo.getTypeInfo() +"]"; } - public String getClassName() { + public String getClassName(){ ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); - UTF8Info utf8Info = (UTF8Info) this.getConstantInfo(classInfo.getUtf8Index()); + UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index()); return utf8Info.getValue(); } - public String getFieldName() { - NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + public String getFieldName(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getName(); } - public String getFieldType() { - NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + 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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/MethodRefInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/MethodRefInfo.java index a3e6f969b0..00df28d40d 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/MethodRefInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/MethodRefInfo.java @@ -2,6 +2,7 @@ public class MethodRefInfo extends ConstantInfo { + private int type = ConstantInfo.METHOD_INFO; private int classInfoIndex; @@ -18,41 +19,44 @@ public int getType() { 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() { + public String toString(){ - return getClassName() + " : " + this.getMethodName() + " : " + this.getParamAndReturnType(); + return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ; } - - public String getClassName() { + public String getClassName(){ ConstantPool pool = this.getConstantPool(); - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(this.getClassInfoIndex()); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex()); return clzInfo.getClassName(); } - public String getMethodName() { + public String getMethodName(){ ConstantPool pool = this.getConstantPool(); - NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getName(); } - public String getParamAndReturnType() { + public String getParamAndReturnType(){ ConstantPool pool = this.getConstantPool(); - NameAndTypeInfo typeInfo = (NameAndTypeInfo) pool.getConstantInfo(this.getNameAndTypeIndex()); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + @Override + public void accept(Visitor visitor) { + visitor.visitMethodRef(this); + } + + + } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NameAndTypeInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NameAndTypeInfo.java index 30be83ef3a..d530f9f0c5 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NameAndTypeInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NameAndTypeInfo.java @@ -1,7 +1,7 @@ package com.pan.jvm.constant; public class NameAndTypeInfo extends ConstantInfo { - public int type = ConstantInfo.NAME_AND_TYPE_INFO; + public int type = ConstantInfo.NAME_AND_TYPE_INFO; private int index1; private int index2; @@ -13,37 +13,39 @@ public NameAndTypeInfo(ConstantPool 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() { + public String getName(){ ConstantPool pool = this.getConstantPool(); - UTF8Info utf8Info1 = (UTF8Info) pool.getConstantInfo(index1); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1); return utf8Info1.getValue(); } - public String getTypeInfo() { + public String getTypeInfo(){ ConstantPool pool = this.getConstantPool(); - UTF8Info utf8Info2 = (UTF8Info) pool.getConstantInfo(index2); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2); return utf8Info2.getValue(); } - public String toString() { - return "(" + getName() + "," + getTypeInfo() + ")"; + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NullConstantInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NullConstantInfo.java index cc6989bef7..d9d0c40b01 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NullConstantInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NullConstantInfo.java @@ -2,13 +2,16 @@ public class NullConstantInfo extends ConstantInfo { - public NullConstantInfo() { + public NullConstantInfo(){ } - @Override public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + + } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/StringInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/StringInfo.java index ad3f397949..d807321152 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/StringInfo.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/StringInfo.java @@ -3,7 +3,6 @@ public class StringInfo extends ConstantInfo { private int type = ConstantInfo.STRING_INFO; private int index; - public StringInfo(ConstantPool pool) { super(pool); } @@ -15,14 +14,18 @@ public int getType() { public int getIndex() { return index; } - public void setIndex(int index) { this.index = index; } - public String toString() { + public String toString(){ return this.getConstantPool().getUTF8String(index); } + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/UTF8Info.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/UTF8Info.java index 502adae968..d867b436e6 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/UTF8Info.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/UTF8Info.java @@ -2,37 +2,35 @@ public class UTF8Info extends ConstantInfo { private int type = ConstantInfo.UTF8_INFO; - private int length; + 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 + ")]"; + 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.visistUTF8(this); + + } } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutionResult.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..f33eaef159 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.pan.jvm.engine; + +import com.pan.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutorEngine.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..fdf4c48647 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/ExecutorEngine.java @@ -0,0 +1,83 @@ +package com.pan.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.pan.jvm.attr.CodeAttr; +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.cmd.ByteCodeCommand; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.empty()){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/Heap.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ba9d52f5 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.pan.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/JavaObject.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..cbe790796b --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.pan.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MethodArea.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..774968a48a --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MethodArea.java @@ -0,0 +1,88 @@ +package com.pan.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.loader.ClassFileLoader; +import com.pan.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MiniJVM.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..84e6403e5d --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.pan.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.pan.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i operands = new ArrayList(); + + public void push(JavaObject jo){ + operands.add(jo); + } + public JavaObject pop(){ + int index = size()-1; + JavaObject jo = (JavaObject)operands.get(index); + operands.remove(index); + return jo; + + } + public JavaObject top(){ + int index = size()-1; + return (JavaObject)operands.get(index); + } + public int size(){ + return operands.size(); + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/StackFrame.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..6603e1e1d1 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/engine/StackFrame.java @@ -0,0 +1,131 @@ +package com.pan.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.pan.jvm.cmd.ByteCodeCommand; +import com.pan.jvm.method.Method; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileParser.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileParser.java index b2bddb85c2..e2467d3885 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileParser.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileParser.java @@ -110,40 +110,40 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { switch (tag) { - case 7: //CONSTANT_Class + case ConstantInfo.CLASS_INFO: //CONSTANT_Class int utf8Index = iter.nextU2ToInt(); ClassInfo classInfo = new ClassInfo(pool); classInfo.setUtf8Index(utf8Index); pool.addConstantInfo(classInfo); break; - case 9: // CONSTANT_Fieldref + case ConstantInfo.FIELD_INFO: // CONSTANT_Fieldref FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(fieldRefInfo); break; - case 10: // CONSTANT_Methodref + case ConstantInfo.METHOD_INFO: // CONSTANT_Methodref MethodRefInfo methodRefInfo = new MethodRefInfo(pool); methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); pool.addConstantInfo(methodRefInfo); break; - case 8: + case ConstantInfo.STRING_INFO: StringInfo info = new StringInfo(pool); info.setIndex(iter.nextU2ToInt()); pool.addConstantInfo(info); break; - case 12: // CONSTANT_NameAndType + case ConstantInfo.NAME_AND_TYPE_INFO: // CONSTANT_NameAndType NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); pool.addConstantInfo(nameAndTypeInfo); break; - case 1: // CONSTANT_Utf8 + case ConstantInfo.UTF8_INFO: // CONSTANT_Utf8 int length = iter.nextU2ToInt(); byte[] data = iter.getBytes(length); String value = null; diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/method/Method.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/method/Method.java index 0fbb0f0946..0c0510426e 100644 --- a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/method/Method.java +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/method/Method.java @@ -4,8 +4,13 @@ import com.pan.jvm.attr.AttributeInfo; import com.pan.jvm.attr.CodeAttr; import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.cmd.ByteCodeCommand; +import com.pan.jvm.constant.UTF8Info; import com.pan.jvm.loader.ByteCodeIterator; +import java.util.ArrayList; +import java.util.List; + public class Method { private int accessFlag; @@ -68,4 +73,71 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ return method; } + + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + + private String getParamAndReturnType(){ + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } + + + } diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ClassFilePrinter.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..1d2d966358 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ClassFilePrinter.java @@ -0,0 +1,54 @@ +package com.pan.jvm.print; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.constant.NameAndTypeInfo; + +import com.pan.jvm.constant.StringInfo; +import com.pan.jvm.constant.UTF8Info; +import com.pan.jvm.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 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.pan.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinter.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..29d6416874 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,83 @@ +package com.pan.jvm.print; + +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.FieldRefInfo; +import com.pan.jvm.constant.MethodRefInfo; +import com.pan.jvm.constant.NameAndTypeInfo; +import com.pan.jvm.constant.StringInfo; +import com.pan.jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinterBad.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinterBad.java new file mode 100644 index 0000000000..8d703f83f7 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/print/ConstantPoolPrinterBad.java @@ -0,0 +1,40 @@ +package com.pan.jvm.print; + +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.UTF8Info; + +public class ConstantPoolPrinterBad { + ConstantPool pool; + ConstantPoolPrinterBad(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo cnstInfo = pool.getConstantInfo(i); + + System.out.print("#"+i+"="); + if(cnstInfo instanceof ClassInfo){ + ClassInfo info = (ClassInfo)cnstInfo; + // Class #2 com/pan/jvm/test/EmployeeV1 + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + } + if(cnstInfo instanceof UTF8Info){ + //UTF8 com/pan/jvm/test/EmployeeV1 + UTF8Info info = (UTF8Info)cnstInfo; + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + } + //其他的if else + } + } +} diff --git a/group11/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java b/group11/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java deleted file mode 100644 index 8f6803c11f..0000000000 --- a/group11/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.pan.alg; - -import org.junit.Assert; - -import org.junit.Test; - - -public class LRUPageFrameTest { - - @Test - public void testAccess() { - LRUPageFrame frame = new LRUPageFrame(3); - frame.access(7); - frame.access(0); - frame.access(1); - Assert.assertEquals("1,0,7", frame.toString()); - frame.access(2); - Assert.assertEquals("2,1,0", frame.toString()); - frame.access(0); - Assert.assertEquals("0,2,1", frame.toString()); - frame.access(0); - Assert.assertEquals("0,2,1", frame.toString()); - frame.access(3); - Assert.assertEquals("3,0,2", frame.toString()); - frame.access(0); - Assert.assertEquals("0,3,2", frame.toString()); - frame.access(4); - Assert.assertEquals("4,0,3", frame.toString()); - frame.access(5); - Assert.assertEquals("5,4,0", frame.toString()); - - } - -} diff --git a/group11/252308879/mini-jvm/src/test/java/com/pan/alg/StackUtilTest.java b/group11/252308879/mini-jvm/src/test/java/com/pan/alg/StackUtilTest.java deleted file mode 100644 index 71671c9b47..0000000000 --- a/group11/252308879/mini-jvm/src/test/java/com/pan/alg/StackUtilTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.pan.alg; - -import java.util.Stack; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -public class StackUtilTest { - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testAddToBottom() { - Stack s = new Stack<>(); - s.push(1); - s.push(2); - s.push(3); - - StackUtil.addToBottom(s, 0); - - Assert.assertEquals("[0, 1, 2, 3]", s.toString()); - - } - @Test - public void testReverse() { - Stack s = new Stack<>(); - s.push(1); - s.push(2); - s.push(3); - s.push(4); - s.push(5); - Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); - StackUtil.reverse(s); - Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); - } - - @Test - public void testRemove() { - Stack s = new Stack<>(); - s.push(1); - s.push(2); - s.push(3); - StackUtil.remove(s, 2); - Assert.assertEquals("[1, 3]", s.toString()); - } - - @Test - public void testGetTop() { - Stack s = new Stack<>(); - s.push(1); - s.push(2); - s.push(3); - s.push(4); - s.push(5); - { - Object[] values = StackUtil.getTop(s, 3); - Assert.assertEquals(5, values[0]); - Assert.assertEquals(4, values[1]); - Assert.assertEquals(3, values[2]); - } - } - - @Test - public void testIsValidPairs() { - Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); - Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); - } - -} diff --git a/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/ClassFileLoaderTest.java b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/ClassFileLoaderTest.java index d341553c70..79cda03ea3 100644 --- a/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/ClassFileLoaderTest.java +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/ClassFileLoaderTest.java @@ -4,255 +4,331 @@ import com.pan.jvm.clz.ClassFile; import com.pan.jvm.clz.ClassIndex; +import com.pan.jvm.cmd.BiPushCmd; +import com.pan.jvm.cmd.ByteCodeCommand; +import com.pan.jvm.cmd.OneOperandCmd; +import com.pan.jvm.cmd.TwoOperandCmd; import com.pan.jvm.constant.*; import com.pan.jvm.field.Field; import com.pan.jvm.loader.ClassFileLoader; import com.pan.jvm.method.Method; import com.pan.jvm.util.Util; import org.junit.After; -import org.junit.Assert; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; +public class ClassFileLoaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/pan/jvm/EmployeeV1"; + static String path1 = EmployeeV1.class.getClassLoader().getResource("").getPath() + .replace("test-classes", "classes"); + static String path2 = "C:/temp"; + + static ClassFile clzFile = null; + + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.pan.jvm.EmployeeV1"; + + clzFile = loader.loadClass(className); + clzFile.print(); + } + + + @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 = "com.pan.jvm.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1032, byteCodes.length); + + } + + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.pan.jvm.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + + String actualValue = Util.byteToHexString(codes); + + Assert.assertEquals("cafebabe", actualValue); + } -public class ClassFileLoaderTest { - - private static final String FULL_QUALIFIED_CLASS_NAME = "com/pan/jvm/EmployeeV1"; - - static String path1 = EmployeeV1.class.getClassLoader().getResource("").getPath() - .replace("test-classes", "classes"); - static String path2 = "C:/temp"; - - static ClassFile clzFile = null; - static { - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.pan.jvm.EmployeeV1"; - - clzFile = loader.loadClass(className); - clzFile.print(); - } - - - @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 = "com.pan.jvm.EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1032, byteCodes.length); - - } - - - @Test - public void testMagicNumber(){ - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - String className = "com.pan.jvm.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); - byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; - - - String actualValue = Util.byteToHexString(codes); - - Assert.assertEquals("cafebabe", actualValue); - } - - /** * ---------------------------------------------------------------------- */ @Test - public void testVersion(){ - Assert.assertEquals(0, clzFile.getMinorVersion()); - Assert.assertEquals(52, clzFile.getMajorVersion()); + public void testVersion() { + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); } @Test - public void testConstantPool(){ - - - ConstantPool pool = clzFile.getConstantPool(); - - Assert.assertEquals(53, pool.getSize()); - - { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); - Assert.assertEquals(2, clzInfo.getUtf8Index()); - - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); - Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); - } - { - ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); - Assert.assertEquals(4, clzInfo.getUtf8Index()); - - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); - Assert.assertEquals("java/lang/Object", utf8Info.getValue()); - } - { - UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); - Assert.assertEquals("name", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(6); - Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(7); - Assert.assertEquals("age", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(8); - Assert.assertEquals("I", utf8Info.getValue()); - - utf8Info = (UTF8Info) pool.getConstantInfo(9); - Assert.assertEquals("", 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()); - } + public void testConstantPool() { + + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", 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(){ + public void testClassIndex() { - ClassIndex clzIndex = clzFile.getClzIndex(); - ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); - ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + 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()); + 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()); - } + 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 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"); - } + 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 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); + 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/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/MiniJVMTest.java b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/MiniJVMTest.java new file mode 100644 index 0000000000..b403aa0e56 --- /dev/null +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/MiniJVMTest.java @@ -0,0 +1,33 @@ +package com.pan.jvm; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.pan.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/pan/jvm/EmployeeV1"; + + static String PATH = EmployeeV1.class.getClassLoader().getResource("").getPath() + .replace("test-classes", "classes"); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.pan.jvm.EmployeeV1"); + + } + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/AccessFlag.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassFile.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + 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 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(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassIndex.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ClassInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantPool.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/FieldRefInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/MethodRefInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NameAndTypeInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NullConstantInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/StringInfo.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/UTF8Info.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..514d85e08f --- /dev/null +++ b/group11/283091182/mini-jvm-week2-bk/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,87 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + private byte[] bytes; + private int pos = 0; + public ByteCodeIterator(byte[] byteCodes){ + this.bytes = byteCodes; + } + + public boolean hasNext(){ + return this.pos < bytes.length-1; + } + + public byte next(){ + byte b = bytes[pos]; + pos ++; + return b; + } + + public byte[] getBytes(int len){ + if(pos+len>bytes.length){ + throw new RuntimeException("Index out of bounds:"+(pos+len)); + } + byte[] bytes = new byte[len]; + int idx = 0; + while(hasNext() && idx 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", 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()); + } + + + +} diff --git a/group11/283091182/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group11/283091182/mini-jvm/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group11/283091182/mini-jvm/com/coderising/jvm/attr/CodeAttr.java b/group11/283091182/mini-jvm/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..f25743fb0d --- /dev/null +++ b/group11/283091182/mini-jvm/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,86 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.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,ConstantPool pool, ByteCodeIterator iter){ + int attrNameIdx = iter.nextU2AsInt(); + System.out.println("AttrName="+pool.getUTF8String(attrNameIdx)); + int attrLen = iter.nextU4AsInt(); + int maxStack = iter.nextU2AsInt(); + int maxLocal = iter.nextU2AsInt(); + int codeLen = iter.nextU4AsInt(); + String code = iter.getBytesAsHexString(codeLen); + CodeAttr codeAttr = new CodeAttr(attrNameIdx, attrLen, maxStack, maxLocal, codeLen, code); + + int exceptionTblLen = iter.nextU2AsInt(); + if(exceptionTblLen>0){ + throw new RuntimeException("ExceptionTable not supported!"); + } + int subAttrCount = iter.nextU2AsInt(); + for(int j=0;j 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(ByteCodeIterator iter){ + int nameIdx = iter.nextU2AsInt(); + int attrLen = iter.nextU4AsInt(); + LineNumberTable t = new LineNumberTable(nameIdx, attrLen); + int itemCount = iter.nextU2AsInt(); + 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 nameIdx = iter.nextU2AsInt(); + int attrLen = iter.nextU4AsInt(); + LocalVariableTable t = new LocalVariableTable(nameIdx, attrLen); + int itemCount = iter.nextU2AsInt(); + for(int i=0;i fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -48,7 +54,18 @@ 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(){ @@ -63,13 +80,23 @@ public void print(){ } - 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){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } } diff --git a/group11/283091182/mini-jvm/com/coderising/jvm/field/Field.java b/group11/283091182/mini-jvm/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..29ef91fbd3 --- /dev/null +++ b/group11/283091182/mini-jvm/com/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2AsInt(); + int nameIndex = iter.nextU2AsInt(); + int descIndex = iter.nextU2AsInt(); + int attribCount = iter.nextU2AsInt(); + //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/group11/283091182/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/283091182/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java index 514d85e08f..4dcd1d8040 100644 --- a/group11/283091182/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group11/283091182/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java @@ -84,4 +84,8 @@ private String byteToHexString(byte[] codes ){ } return buffer.toString(); } + + public void back(int offset){ + this.pos-=offset; + } } diff --git a/group11/283091182/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java b/group11/283091182/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java index 4c2cef5504..be823bf23f 100644 --- a/group11/283091182/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java +++ b/group11/283091182/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java @@ -12,6 +12,8 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFileParser { @@ -35,6 +37,9 @@ public ClassFile parse(byte[] codes) { clzFile.setAccessFlag(accFlag); ClassIndex clsIdx = parseClassIndex(iter); clzFile.setClassIndex(clsIdx); + parseInterfaces(iter,pool,clzFile); + parseFields(iter, pool, clzFile); + parseMethods(iter, pool, clzFile); return clzFile; } @@ -97,5 +102,31 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { } return cp; } + + private void parseInterfaces(ByteCodeIterator iter, ConstantPool pool, ClassFile clz){ + int interfaceCount = iter.nextU2AsInt(); + System.out.println("Total number of interface="+interfaceCount); + for(int i=0;iMethodName="+pool.getUTF8String(nameIndex)); + int descIndex = iter.nextU2AsInt(); + Method method = new Method(clzFile,accessFlag,nameIndex,descIndex); + int attrCount = iter.nextU2AsInt(); + System.out.println("AttrCount="+attrCount); + 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); + } -} +} \ No newline at end of file diff --git a/group11/283091182/src/com/coding/basic/stack/StackUtil.java b/group11/283091182/src/com/coding/basic/stack/StackUtil.java index cd5aa08d06..8062edc116 100644 --- a/group11/283091182/src/com/coding/basic/stack/StackUtil.java +++ b/group11/283091182/src/com/coding/basic/stack/StackUtil.java @@ -26,7 +26,26 @@ public static void reverse(Stack s) { counter--; } } - + + public static void reverse2(Stack s) { + if(s==null || s.isEmpty()){ + return; + }; + Stack temp = new Stack(); + int counter = s.size(); + while(counter>1){ + //Get the peek one + Object o = s.pop(); + for(int i=0;i1){ + //如果当前元素只有一个显然不需要移动 + Node compareNode = first.next; + //从头比较,找出node节点的位置,将其前移到开头 + while (compareNode!=last){ + if(compareNode.pageNum==node.pageNum)break; + compareNode = compareNode.next; + } + //删除当前node + compareNode.prev.next = compareNode.next; + compareNode.next.prev = compareNode.prev; + //将node插入到开头位置 + node.prev = first; + node.next = first.next; + first.next.prev = node; + first.next = node; + } + } + private boolean isEmpty(){ + return this.currentSize>0?false:true; + } + + public String toString(){ + ArrayList arrays = new ArrayList<>(); + if(this.currentSize>0){ + Node index = first.next; + while (index!=last){ + arrays.add(index.pageNum); + index = index.next; + } + return arrays.toString(); + } + return ""; + } + + + +} + diff --git a/group11/729245768/DataStructure/src/main/coding_170327/loader/ClassFileLoader.java b/group11/729245768/DataStructure/src/main/coding_170327/loader/ClassFileLoader.java new file mode 100644 index 0000000000..10cc7b400b --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170327/loader/ClassFileLoader.java @@ -0,0 +1,58 @@ +package main.coding_170327.loader; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/20. + */ +public class ClassFileLoader { + private List clzPaths = new ArrayList<>(); + + public byte[] readBinaryCodes(String className){ + className = className.replace('.', File.separatorChar)+".class"; + for(String singlePath:clzPaths){ + String clzFileName = singlePath + File.separatorChar +className; + byte[] codes = loadClassFile(clzFileName); + if(codes!=null){ + return codes; + } + } + return null; + } + public byte[] loadClassFile(String clzFileName){ + File file = new File(clzFileName); + + try { + return IOUtils.toByteArray(new FileInputStream(file)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + public void addClassPath(String path){ + if(this.clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + public String getClassPath_V1(){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i s) { + if (s == null || s.isEmpty()) { + return; + } + Stack temp = new Stack<>(); + while (!s.isEmpty()) { + temp.push(s.pop()); + } + while (!temp.isEmpty()) { + addToBottom(s, temp.pop()); + } + + } + + public static void addToBottom(Stack s, Integer value) { + if (s.isEmpty()) { + s.push(value); + } else { + Integer top = s.pop(); + addToBottom(s, value); + s.push(top); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + if (s == null || s.isEmpty()) { + return; + } else { + Stack stack = new Stack<>(); + while (!s.isEmpty()) { + Object data = s.pop(); + if (data != o) { + stack.push(o); + } else { + break; + } + } + while (!stack.isEmpty()) { + s.push(stack.pop()); + } + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + + if (s == null || s.isEmpty() || s.size() < len || len <= 0) { + return null; + } + + Stack tmpStack = new Stack(); + int i = 0; + Object[] result = new Object[len]; + while (!s.isEmpty()) { + Object value = s.pop(); + tmpStack.push(value); + result[i++] = value; + if (i == len) { + break; + } + } + while (!tmpStack.isEmpty()) { + s.push(tmpStack.pop()); + } + return result; + } + + /** + * 字符串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 stack = new Stack(); + for(int i=0;i constantInfos = new ArrayList<>(); + + public ConstantPool(){} + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSizes(){ + return this.constantInfos.size()-1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/FieldRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..3237e30cd3 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/MethodRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7731ab9374 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/MethodRefInfo.java @@ -0,0 +1,59 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NameAndTypeInfo.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..476fc48b57 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,53 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int indexA; + private int indexB; + + public NameAndTypeInfo(ConstantPool pool){ + super(pool); + } + + public int getIndexA() { + return indexA; + } + + public int getIndexB() { + return indexB; + } + + public void setIndexA(int indexA) { + this.indexA = indexA; + } + + public void setIndexB(int indexB) { + this.indexB = indexB; + } + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(indexA); + return utf8Info.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8_info =(UTF8Info) pool.getConstantInfo(indexB); + return utf8_info.getValue(); + } + + @Override + public String toString() { + return "("+getName()+","+getTypeInfo()+")"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NullConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..de967e29b5 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/NullConstantInfo.java @@ -0,0 +1,16 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/StringInfo.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..7bf8ecd14a --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/StringInfo.java @@ -0,0 +1,31 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/UTF8Info.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..69978afbfc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +package main.coding_170409.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170409/jvm/loader/ByteCodeIterator.java b/group11/729245768/DataStructure/src/main/coding_170409/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..1451c60491 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170409/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package main.coding_170409.jvm.loader; + +import main.coding_170409.jvm.util.Util; + +import java.util.Arrays; + +/** + * Created by peter on 2017/4/21. + */ +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[] temp = new byte[len]; + + for(int i=0;i clzPaths = new ArrayList<>(); + public byte[] readBinaryCode(String className){ + className = className.replace('.', File.pathSeparatorChar) +".class"; + for (String path:this.clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes!=null){ + return codes; + } + } + return null; + } + + public 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(clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + public ConstantPool loadClass(String className){ + byte[] codes = this.readBinaryCode(className); + ClassFileParse parser = new ClassFileParse(); + return parser.parse(codes); + } + public String getClassPath_V1(){ + StringBuffer sb = new StringBuffer(); + for(int i=0;i operator = new Stack<>();//存储操作数 + Stack opeCharacter = new Stack<>();//存储运算符 + StringBuffer sb = new StringBuffer("");//存储获取到的操作数 + int index = 0;// + while (index < expr.length()) { + + Character ch = expr.charAt(index); + if (!Character.isDigit(ch) && opeCharacter.size() == 0) { + opeCharacter.push(ch); + operator.push(Float.parseFloat(sb.toString())); + sb = new StringBuffer(""); + index++; + continue; + } + switch (ch) { + case '+': + case '-': + operator.push(Float.parseFloat(sb.toString())); + sb = new StringBuffer(""); + Character top = opeCharacter.pop(); + float op2 = operator.pop(); + float op1 = operator.pop(); + switch (top) { + case '+': + operator.push(op1 + op2); + break; + case '-': + operator.push(op1 - op2); + break; + case '*': + operator.push(op1 * op2); + break; + case '/': + operator.push(op1 / op2); + break; + } + opeCharacter.push(ch); + break; + case '*': + case '/': + operator.push(Float.parseFloat(sb.toString())); + sb = new StringBuffer(""); + Character top1 = opeCharacter.peek(); + if (top1 == '+' || top1 == '-') { + opeCharacter.push(ch); + } else { + opeCharacter.pop(); + float ope2 = operator.pop(); + float ope1 = operator.pop(); + if (top1 == '*') { + operator.push(ope1 * ope2); + } else { + operator.push(ope1 / ope2); + } + opeCharacter.push(ch); + } + break; + default: + sb.append(ch); + } + index++; + if (index == expr.length()) { + operator.push(Float.parseFloat(sb.toString())); + } + } + //计算运算符栈剩余的操作符 + while (opeCharacter.size()>0){ + float last2 = operator.pop(); + float last1 = operator.pop(); + switch (opeCharacter.pop()){ + case '+': operator.push(last1 + last2) ;break; + case '-': operator.push(last1 - last2);break; + case '*': operator.push(last1 * last2);break; + case '/': operator.push(last1/last2); + } + } + + return operator.pop(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/AttributeInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..199df4ccc9 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/AttributeInfo.java @@ -0,0 +1,21 @@ +package main.coding_170416.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVaribleTable"; + 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/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/CodeAttr.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..4a17d9cc2b --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/CodeAttr.java @@ -0,0 +1,93 @@ +package main.coding_170416.jvm.attr; + +import main.coding_170416.jvm.clz.ClassFile; +import main.coding_170416.jvm.constant.ConstantPool; +import main.coding_170416.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class CodeAttr extends AttributeInfo { + private int maxStack; + private int maxLocals; + private int codeLen; + private String code; + + public String getCode() { + return code; + } + + private LineNumberTable lineNumberTable; + private LocalVariableTable localVariableTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen, String code) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + } + + public void setLineNumberTable(LineNumberTable table) { + this.lineNumberTable = table; + } + + public void setLocalVariableTable(LocalVariableTable table) { + this.localVariableTable = table; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iterator) { + int attrNameIndex = iterator.nextU2ToInt(); + int attrLen = iterator.nextU4ToInt(); + int maxStack = iterator.nextU2ToInt(); + int maxLocals = iterator.nextU2ToInt(); + int codeLen = iterator.nextU4ToInt(); + + String code = iterator.nextUxToHexString(codeLen); + + System.out.println(code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + int exceptionTableLen = iterator.nextU2ToInt(); + //deal with exception + if (exceptionTableLen > 0) { + String exceptionTable = iterator.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table:just ignore " + exceptionTable); + } + int subAttrCount = iterator.nextU2ToInt(); + for (int i = 1; i < subAttrCount; i++) { + int subAttrIndex = iterator.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + iterator.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + LineNumberTable t = LineNumberTable.parse(iterator); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iterator); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iterator); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + } + return codeAttr; + } + + public String toString(ConstantPool pool) { + StringBuilder sb = new StringBuilder(); + sb.append("Code:").append(code).append("\n"); + sb.append("\n"); + sb.append(this.lineNumberTable.toString()); + sb.append(this.localVariableTable.toString(pool)); + return sb.toString(); + } + + public void setStackMapTable(StackMapTable stackMapTable) { + this.stackMapTable = stackMapTable; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LineNumberTable.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..181c88cccc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LineNumberTable.java @@ -0,0 +1,68 @@ +package main.coding_170416.jvm.attr; + +import main.coding_170416.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class LineNumberTable extends AttributeInfo { + List 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(ByteCodeIterator iterator) { + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + + LineNumberTable table = new LineNumberTable(index, len); + for (int i = 1; i < len; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLineNum(iterator.nextU2ToInt()); + table.addLineNumberItem(item); + } + return table; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Line Number Table:\n"); + for(LineNumberItem item:items){ + sb.append("startPC:"+item.getStartPC()).append(","); + sb.append("LineNum:"+item.getLineNum()).append("\n"); + } + sb.append("\n"); + return sb.toString(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableItem.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..5db0ff8ddb --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableItem.java @@ -0,0 +1,52 @@ +package main.coding_170416.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +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/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableTable.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..3963253cd1 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/LocalVariableTable.java @@ -0,0 +1,50 @@ +package main.coding_170416.jvm.attr; + +import main.coding_170416.jvm.constant.ConstantPool; +import main.coding_170416.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class LocalVariableTable extends AttributeInfo { + List items = new ArrayList<>(); + public LocalVariableTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public void addLocalVariableItem(LocalVariableItem item){ + this.items.add(item); + } + public static LocalVariableTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU1ToInt(); + int len = iterator.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iterator.nextU2ToInt(); + for(int i=0;i<=itemLen;i++){ + LocalVariableItem item =new LocalVariableItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLength(iterator.nextU2ToInt()); + item.setNameIndex(iterator.nextU2ToInt()); + item.setDescIndex(iterator.nextU2ToInt()); + item.setIndex(iterator.nextU2ToInt()); + table.addLocalVariableItem(item); + } + return table; + } + + public String toString(ConstantPool pool){ + StringBuffer buffer = new StringBuffer(); + 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/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/StackMapTable.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..4be892690b --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/attr/StackMapTable.java @@ -0,0 +1,23 @@ +package main.coding_170416.jvm.attr; + +import main.coding_170416.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class StackMapTable extends AttributeInfo { + private String originalCode; + + public StackMapTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public static StackMapTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + StackMapTable t = new StackMapTable(index,len); + return t; + } + private void setOriginalCode(String code){ + this.originalCode =code; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/AccessFlag.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..72a0931e04 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/AccessFlag.java @@ -0,0 +1,28 @@ +package main.coding_170416.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +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; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassFile.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..cb27ba2c2d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package main.coding_170416.jvm.clz; + +import main.coding_170416.jvm.constant.ClassInfo; +import main.coding_170416.jvm.constant.ConstantPool; +import main.coding_170416.jvm.field.Field; +import main.coding_170416.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private ConstantPool pool; + private AccessFlag accessFlag; + private ClassIndex clzIndex; + 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 setConstantPool(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.getClzIndex().getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassIndex.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..de3497ef86 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package main.coding_170416.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } + + public int getThisClassIndex() { + return thisClassIndex; + } + + public int getSuperClassIndex() { + return superClassIndex; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ClassInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b60723fc10 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ClassInfo.java @@ -0,0 +1,32 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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; + } + + @Override + public int getType() { + return type; + } + + public String getClassName(){ + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..699ee83f2f --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantInfo.java @@ -0,0 +1,33 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantPool.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..400379b5dc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/ConstantPool.java @@ -0,0 +1,26 @@ +package main.coding_170416.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ConstantPool { + private List constantInfos = new ArrayList<>(); + + public ConstantPool(){} + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSizes(){ + return this.constantInfos.size()-1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/FieldRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..c88917d99f --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/MethodRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..c00bc277c1 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/MethodRefInfo.java @@ -0,0 +1,59 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NameAndTypeInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..2a53baddab --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,53 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int indexA; + private int indexB; + + public NameAndTypeInfo(ConstantPool pool){ + super(pool); + } + + public int getIndexA() { + return indexA; + } + + public int getIndexB() { + return indexB; + } + + public void setIndexA(int indexA) { + this.indexA = indexA; + } + + public void setIndexB(int indexB) { + this.indexB = indexB; + } + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(indexA); + return utf8Info.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8_info =(UTF8Info) pool.getConstantInfo(indexB); + return utf8_info.getValue(); + } + + @Override + public String toString() { + return "("+getName()+","+getTypeInfo()+")"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NullConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..17af5d933c --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/NullConstantInfo.java @@ -0,0 +1,16 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/StringInfo.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..4586195556 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/StringInfo.java @@ -0,0 +1,31 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/UTF8Info.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..0dfe034217 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +package main.coding_170416.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/field/Field.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/field/Field.java new file mode 100644 index 0000000000..5d1801730c --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/field/Field.java @@ -0,0 +1,44 @@ +package main.coding_170416.jvm.field; + +import main.coding_170416.jvm.constant.ConstantPool; +import main.coding_170416.jvm.constant.UTF8Info; +import main.coding_170416.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptionIndex; + + private ConstantPool pool; + + public Field(int accessFlag,int nameIndex,int descriptionIndex,ConstantPool pool){ + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptionIndex = descriptionIndex; + this.pool = pool; + } + + @Override + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptionIndex)).getValue(); + return name+":"+desc; + } + + public static Field parse(ConstantPool pool, ByteCodeIterator iterator){ + int accessFlag = iterator.nextU2ToInt(); + int nameIndex = iterator.nextU2ToInt(); + int descIndex = iterator.nextU2ToInt(); + int attributeCount = iterator.nextU2ToInt(); + Field f = new Field(accessFlag,nameIndex,descIndex,pool); + + if(attributeCount>0){ + throw new RuntimeException("Field attribute has not implemented"); + } + return f; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170416/jvm/loader/ByteCodeIterator.java b/group11/729245768/DataStructure/src/main/coding_170416/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6d1a12af38 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170416/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package main.coding_170416.jvm.loader; + +import main.coding_170416.jvm.util.Util; + +import java.util.Arrays; + +/** + * Created by peter on 2017/4/21. + */ +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[] temp = new byte[len]; + + for(int i=0;i clzPaths = new ArrayList<>(); + public byte[] readBinaryCode(String className){ + className = className.replace('.', File.pathSeparatorChar) +".class"; + for (String path:this.clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes!=null){ + return codes; + } + } + return null; + } + + public 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(clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + public ClassFile loadClass(String className){ + byte[] codes = this.readBinaryCode(className); + ClassFileParse parser = new ClassFileParse(); + return parser.parse(codes); + } + public String getClassPath_V1(){ + StringBuffer sb = new StringBuffer(); + for(int i=0;i operator = new Stack();//存储操作数 + while (index < tokens.length){ + String s = tokens[index]; + if(Character.isDigit(s.charAt(0))){ + //如果是操作数,直接进栈 + operator.push(Float.parseFloat(s)); + }else{ + float ope2 = operator.pop(); + float ope1 = operator.pop(); + switch (s){ + case "+": + operator.push(ope1+ope2); + break; + case "-": + operator.push(ope1-ope2); + break; + case "*": + operator.push(ope1*ope2); + break; + case "/": + operator.push(ope1/ope2); + break; + default: + System.out.println("invalid operator"); + } + } + index++; + } + return operator.pop(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/PrefixExpr.java b/group11/729245768/DataStructure/src/main/coding_170423/PrefixExpr.java new file mode 100644 index 0000000000..5a2ef9a2a8 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/PrefixExpr.java @@ -0,0 +1,49 @@ +package main.coding_170423; + + +import java.util.Stack; + +/** + * Created by peter on 2017/4/23. + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + String[] tokens = expr.split(" "); + Stack operator = new Stack(); + int index = tokens.length - 1; + while (index >= 0) { + String s = tokens[index]; + if (Character.isDigit(s.charAt(0))) { + //说明是操作数 + operator.push(Float.parseFloat(s)); + } else { + //说明是操作符 + float opera1 = operator.pop(); + float opera2 = operator.pop(); + switch (s) { + case "+": + operator.push(opera1 + opera2); + break; + case "-": + operator.push(opera1 - opera2); + break; + case "*": + operator.push(opera1 * opera2); + break; + case "/": + operator.push(opera1 / opera2); + break; + + } + } + index--; + } + return operator.pop(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/Test.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/Test.java new file mode 100644 index 0000000000..8dcb8f3cf2 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/Test.java @@ -0,0 +1,7 @@ +package main.coding_170423.jvm; + +/** + * Created by peter on 2017/4/21. + */ +public class Test { +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/AttributeInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..5c7e7dbad0 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/AttributeInfo.java @@ -0,0 +1,21 @@ +package main.coding_170423.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVaribleTable"; + 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/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/CodeAttr.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..6afddedd42 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/CodeAttr.java @@ -0,0 +1,93 @@ +package main.coding_170423.jvm.attr; + +import main.coding_170423.jvm.clz.ClassFile; +import main.coding_170423.jvm.constant.ConstantPool; +import main.coding_170423.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class CodeAttr extends AttributeInfo { + private int maxStack; + private int maxLocals; + private int codeLen; + private String code; + + public String getCode() { + return code; + } + + private LineNumberTable lineNumberTable; + private LocalVariableTable localVariableTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen, String code) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + } + + public void setLineNumberTable(LineNumberTable table) { + this.lineNumberTable = table; + } + + public void setLocalVariableTable(LocalVariableTable table) { + this.localVariableTable = table; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iterator) { + int attrNameIndex = iterator.nextU2ToInt(); + int attrLen = iterator.nextU4ToInt(); + int maxStack = iterator.nextU2ToInt(); + int maxLocals = iterator.nextU2ToInt(); + int codeLen = iterator.nextU4ToInt(); + + String code = iterator.nextUxToHexString(codeLen); + + System.out.println(code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + int exceptionTableLen = iterator.nextU2ToInt(); + //deal with exception + if (exceptionTableLen > 0) { + String exceptionTable = iterator.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table:just ignore " + exceptionTable); + } + int subAttrCount = iterator.nextU2ToInt(); + for (int i = 1; i < subAttrCount; i++) { + int subAttrIndex = iterator.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + iterator.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + LineNumberTable t = LineNumberTable.parse(iterator); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iterator); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iterator); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + } + return codeAttr; + } + + public String toString(ConstantPool pool) { + StringBuilder sb = new StringBuilder(); + sb.append("Code:").append(code).append("\n"); + sb.append("\n"); + sb.append(this.lineNumberTable.toString()); + sb.append(this.localVariableTable.toString(pool)); + return sb.toString(); + } + + public void setStackMapTable(StackMapTable stackMapTable) { + this.stackMapTable = stackMapTable; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LineNumberTable.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..79c96934bc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LineNumberTable.java @@ -0,0 +1,68 @@ +package main.coding_170423.jvm.attr; + +import main.coding_170423.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class LineNumberTable extends AttributeInfo { + List 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(ByteCodeIterator iterator) { + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + + LineNumberTable table = new LineNumberTable(index, len); + for (int i = 1; i < len; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLineNum(iterator.nextU2ToInt()); + table.addLineNumberItem(item); + } + return table; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Line Number Table:\n"); + for(LineNumberItem item:items){ + sb.append("startPC:"+item.getStartPC()).append(","); + sb.append("LineNum:"+item.getLineNum()).append("\n"); + } + sb.append("\n"); + return sb.toString(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableItem.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..bf9bc16432 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableItem.java @@ -0,0 +1,52 @@ +package main.coding_170423.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +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/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableTable.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..72de32aad5 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/LocalVariableTable.java @@ -0,0 +1,50 @@ +package main.coding_170423.jvm.attr; + +import main.coding_170423.jvm.constant.ConstantPool; +import main.coding_170423.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class LocalVariableTable extends AttributeInfo { + List items = new ArrayList<>(); + public LocalVariableTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public void addLocalVariableItem(LocalVariableItem item){ + this.items.add(item); + } + public static LocalVariableTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU1ToInt(); + int len = iterator.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iterator.nextU2ToInt(); + for(int i=0;i<=itemLen;i++){ + LocalVariableItem item =new LocalVariableItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLength(iterator.nextU2ToInt()); + item.setNameIndex(iterator.nextU2ToInt()); + item.setDescIndex(iterator.nextU2ToInt()); + item.setIndex(iterator.nextU2ToInt()); + table.addLocalVariableItem(item); + } + return table; + } + + public String toString(ConstantPool pool){ + StringBuffer buffer = new StringBuffer(); + 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/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/StackMapTable.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..5db41e5a47 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/attr/StackMapTable.java @@ -0,0 +1,23 @@ +package main.coding_170423.jvm.attr; + +import main.coding_170423.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class StackMapTable extends AttributeInfo { + private String originalCode; + + public StackMapTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public static StackMapTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + StackMapTable t = new StackMapTable(index,len); + return t; + } + private void setOriginalCode(String code){ + this.originalCode =code; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/AccessFlag.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..bc010b3503 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/AccessFlag.java @@ -0,0 +1,28 @@ +package main.coding_170423.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +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; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassFile.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..a8f944ac9e --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package main.coding_170423.jvm.clz; + +import main.coding_170423.jvm.constant.ClassInfo; +import main.coding_170423.jvm.constant.ConstantPool; +import main.coding_170423.jvm.field.Field; +import main.coding_170423.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private ConstantPool pool; + private AccessFlag accessFlag; + private ClassIndex clzIndex; + 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 setConstantPool(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.getClzIndex().getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassIndex.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..6f455e0af4 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package main.coding_170423.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } + + public int getThisClassIndex() { + return thisClassIndex; + } + + public int getSuperClassIndex() { + return superClassIndex; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/BiPushCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..e267c6a140 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/BiPushCmd.java @@ -0,0 +1,20 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class BiPushCmd extends OneOperandCmd{ + public BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+":"+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/ByteCodeCommand.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..89e6cf40be --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,151 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; +import main.coding_170423.jvm.constant.ConstantInfo; +import main.coding_170423.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by peterchen on 2017/4/26. + */ +public abstract class ByteCodeCommand { + String opCode; + ClassFile clzFile; + private int offset; + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private 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 getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/CommandParser.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..b3f16102e0 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/CommandParser.java @@ -0,0 +1,127 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peterchen on 2017/4/26. + */ +public class CommandParser { + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + if (codes == null || codes.length() == 0 || (codes.length() % 2) != 0) { + throw new RuntimeException("the original code is not correct"); + } + + codes = codes.toUpperCase(); + + CommandIterator commandIterator = new CommandIterator(codes); + List byteCodeCommands = new ArrayList<>(); + while (commandIterator.hasNext()) { + String opCode = commandIterator.next2CharAsString(); + switch (opCode) { + case ByteCodeCommand.new_object: + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, opCode); + newObjectCmd.setOprand1(commandIterator.nextCharAsInt()); + newObjectCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(newObjectCmd); + break; + case ByteCodeCommand.invokespecial: + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, opCode); + invokeSpecialCmd.setOprand1(commandIterator.nextCharAsInt()); + invokeSpecialCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(invokeSpecialCmd); + break; + case ByteCodeCommand.invokevirtual: + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, opCode); + invokeVirtualCmd.setOprand1(commandIterator.nextCharAsInt()); + invokeVirtualCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(invokeVirtualCmd); + break; + case ByteCodeCommand.getfield: + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, opCode); + getFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + getFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(getFieldCmd); + break; + case ByteCodeCommand.getstatic: + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, opCode); + getStaticFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + getStaticFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(getStaticFieldCmd); + break; + case ByteCodeCommand.putfield: + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, opCode); + putFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + putFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(putFieldCmd); + break; + case ByteCodeCommand.ldc: + LdcCmd ldcCmd = new LdcCmd(clzFile, opCode); + ldcCmd.setOperand(commandIterator.nextCharAsInt()); + byteCodeCommands.add(ldcCmd); + break; + case ByteCodeCommand.bipush: + BiPushCmd biPushCmd = new BiPushCmd(clzFile, opCode); + biPushCmd.setOperand(commandIterator.nextCharAsInt()); + byteCodeCommands.add(biPushCmd); + break; + case ByteCodeCommand.dup: + case ByteCodeCommand.aload_0: + case ByteCodeCommand.aload_1: + case ByteCodeCommand.aload_2: + case ByteCodeCommand.iload_1: + case ByteCodeCommand.iload_2: + case ByteCodeCommand.iload_3: + case ByteCodeCommand.fload_3: + case ByteCodeCommand.voidreturn: + case ByteCodeCommand.astore_1: + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, opCode); + byteCodeCommands.add(noOperandCmd); + break; + default: + throw new RuntimeException("Sorry,the instruction " + opCode + " " + "has not implemented"); + + } + } + calcuateOffset(byteCodeCommands); + ByteCodeCommand[] result = new ByteCodeCommand[byteCodeCommands.size()]; + byteCodeCommands.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 code) { + 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 nextCharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..e1851171b4 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,19 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class GetFieldCmd extends TwoOperandCmd { + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetStaticFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e3a05ed1fd --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class GetStaticFieldCmd extends TwoOperandCmd { + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeSpecialCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..f1ea0979ec --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,19 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class InvokeSpecialCmd extends TwoOperandCmd { + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeVirtualCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..5012d18559 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,24 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class InvokeVirtualCmd extends TwoOperandCmd { + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/LdcCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..8642973dbd --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; +import main.coding_170423.jvm.constant.ConstantInfo; +import main.coding_170423.jvm.constant.StringInfo; + +/** + * Created by peterchen on 2017/4/26. + */ +public class LdcCmd extends OneOperandCmd { + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + ConstantInfo info = 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/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NewObjectCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..39caa72387 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class NewObjectCmd extends TwoOperandCmd { + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NoOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..18c4df13c4 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,22 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class NoOperandCmd extends ByteCodeCommand { + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + public int getLength(){ + return 1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/OneOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..c36211d19d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public 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/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/PutFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..18b0a46be9 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class PutFieldCmd extends TwoOperandCmd { + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/TwoOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..60123a3f52 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,68 @@ +package main.coding_170423.jvm.cmd; + +import main.coding_170423.jvm.clz.ClassFile; +import main.coding_170423.jvm.constant.ClassInfo; +import main.coding_170423.jvm.constant.ConstantInfo; +import main.coding_170423.jvm.constant.FieldRefInfo; +import main.coding_170423.jvm.constant.MethodRefInfo; + +/** + * Created by peterchen on 2017/4/26. + */ +public 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(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(){ + 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(){ + 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/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ClassInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..a476e01205 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ClassInfo.java @@ -0,0 +1,32 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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; + } + + @Override + public int getType() { + return type; + } + + public String getClassName(){ + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..d6a4322c16 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantInfo.java @@ -0,0 +1,33 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantPool.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..1cd269f915 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/ConstantPool.java @@ -0,0 +1,26 @@ +package main.coding_170423.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ConstantPool { + private List constantInfos = new ArrayList<>(); + + public ConstantPool(){} + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public Object getSizes(){ + return this.constantInfos.size()-1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/FieldRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..5770ed8d56 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/MethodRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..6eb445d9b9 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/MethodRefInfo.java @@ -0,0 +1,59 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NameAndTypeInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5e044a6612 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,53 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int indexA; + private int indexB; + + public NameAndTypeInfo(ConstantPool pool){ + super(pool); + } + + public int getIndexA() { + return indexA; + } + + public int getIndexB() { + return indexB; + } + + public void setIndexA(int indexA) { + this.indexA = indexA; + } + + public void setIndexB(int indexB) { + this.indexB = indexB; + } + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(indexA); + return utf8Info.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8_info =(UTF8Info) pool.getConstantInfo(indexB); + return utf8_info.getValue(); + } + + @Override + public String toString() { + return "("+getName()+","+getTypeInfo()+")"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NullConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..1b91bd4269 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/NullConstantInfo.java @@ -0,0 +1,16 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/StringInfo.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..1b163ca940 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/StringInfo.java @@ -0,0 +1,31 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/UTF8Info.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..05e2427a5c --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +package main.coding_170423.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/field/Field.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/field/Field.java new file mode 100644 index 0000000000..1d3b258374 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/field/Field.java @@ -0,0 +1,44 @@ +package main.coding_170423.jvm.field; + +import main.coding_170423.jvm.constant.ConstantPool; +import main.coding_170423.jvm.constant.UTF8Info; +import main.coding_170423.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptionIndex; + + private ConstantPool pool; + + public Field(int accessFlag,int nameIndex,int descriptionIndex,ConstantPool pool){ + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptionIndex = descriptionIndex; + this.pool = pool; + } + + @Override + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptionIndex)).getValue(); + return name+":"+desc; + } + + public static Field parse(ConstantPool pool, ByteCodeIterator iterator){ + int accessFlag = iterator.nextU2ToInt(); + int nameIndex = iterator.nextU2ToInt(); + int descIndex = iterator.nextU2ToInt(); + int attributeCount = iterator.nextU2ToInt(); + Field f = new Field(accessFlag,nameIndex,descIndex,pool); + + if(attributeCount>0){ + throw new RuntimeException("Field attribute has not implemented"); + } + return f; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170423/jvm/loader/ByteCodeIterator.java b/group11/729245768/DataStructure/src/main/coding_170423/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..8566c06b4d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170423/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package main.coding_170423.jvm.loader; + +import main.coding_170423.jvm.util.Util; + +import java.util.Arrays; + +/** + * Created by peter on 2017/4/21. + */ +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[] temp = new byte[len]; + + for(int i=0;i clzPaths = new ArrayList<>(); + public byte[] readBinaryCode(String className){ + className = className.replace('.', File.pathSeparatorChar) +".class"; + for (String path:this.clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes!=null){ + return codes; + } + } + return null; + } + + public 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(clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + public ClassFile loadClass(String className){ + byte[] codes = this.readBinaryCode(className); + ClassFileParse parser = new ClassFileParse(); + return parser.parse(codes); + } + public String getClassPath_V1(){ + StringBuffer sb = new StringBuffer(); + for(int i=0;i { + + private int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + public CircleQueue(){ + elementData =new Object[DEFAULT_SIZE]; + } + public CircleQueue(int capacity){ + this.DEFAULT_SIZE = capacity; + elementData = new Object[DEFAULT_SIZE]; + } + public boolean isEmpty() { + return front==rear; + + } + + public int size() { + return (rear-front+DEFAULT_SIZE)%DEFAULT_SIZE; + } + + + + public void enQueue(E data) { + if((rear+1)%DEFAULT_SIZE==front){ + throw new RuntimeException("queue has fulled"); + } + elementData[rear] = data; + rear = (rear+1)%DEFAULT_SIZE; + } + + public E deQueue() { + if(isEmpty()){ + throw new EmptyStackException(); + } + E data = (E)elementData[front]; + front = (front+1)%DEFAULT_SIZE; + return data; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/Josephus.java b/group11/729245768/DataStructure/src/main/coding_170430/Josephus.java new file mode 100644 index 0000000000..13ec4df57d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/Josephus.java @@ -0,0 +1,34 @@ +package main.coding_170430; +import java.util.ArrayList; +import java.util.List; +/** + * Created by peterchen on 2017/5/4. + */ +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + CircleQueue queue = new CircleQueue<>(n+1); + for(int i=1;i<=n;i++){ + queue.enQueue(i); + } + List list = new ArrayList<>(); + while (!queue.isEmpty()){ + int index = 1; + while (index { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + + public int size() { + return stack1.size(); + } + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + return null; + } + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + E data = stack2.pop(); + while (!stack2.isEmpty()) { + stack1.push(stack2.pop()); + } + return data; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/AttributeInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..a95d7f037a --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/AttributeInfo.java @@ -0,0 +1,21 @@ +package main.coding_170430.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +public abstract class AttributeInfo { + public static final String CODE = "Code"; + public static final String CONST_VALUE = "ConstantValue"; + public static final String EXCPTIONS = "Exceptions"; + public static final String LINE_NUM_TABLE = "LineNumberTable"; + public static final String LOCAL_VAR_TABLE = "LocalVaribleTable"; + 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/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/CodeAttr.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..8f13222925 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/CodeAttr.java @@ -0,0 +1,66 @@ +package main.coding_170430.jvm.attr; + +import main.coding_170430.jvm.clz.ClassFile; +import main.coding_170430.jvm.cmd.ByteCodeCommand; +import main.coding_170430.jvm.constant.ConstantPool; +import main.coding_170430.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +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){ + + return null; + } + + + 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 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 iterator) { + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + + LineNumberTable table = new LineNumberTable(index, len); + for (int i = 1; i < len; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLineNum(iterator.nextU2ToInt()); + table.addLineNumberItem(item); + } + return table; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Line Number Table:\n"); + for(LineNumberItem item:items){ + sb.append("startPC:"+item.getStartPC()).append(","); + sb.append("LineNum:"+item.getLineNum()).append("\n"); + } + sb.append("\n"); + return sb.toString(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableItem.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..6891c13bc6 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableItem.java @@ -0,0 +1,52 @@ +package main.coding_170430.jvm.attr; + +/** + * Created by peter on 2017/4/21. + */ +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/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableTable.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..7fe678d70d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/LocalVariableTable.java @@ -0,0 +1,50 @@ +package main.coding_170430.jvm.attr; + +import main.coding_170430.jvm.constant.ConstantPool; +import main.coding_170430.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class LocalVariableTable extends AttributeInfo { + List items = new ArrayList<>(); + public LocalVariableTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public void addLocalVariableItem(LocalVariableItem item){ + this.items.add(item); + } + public static LocalVariableTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU1ToInt(); + int len = iterator.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iterator.nextU2ToInt(); + for(int i=0;i<=itemLen;i++){ + LocalVariableItem item =new LocalVariableItem(); + item.setStartPC(iterator.nextU2ToInt()); + item.setLength(iterator.nextU2ToInt()); + item.setNameIndex(iterator.nextU2ToInt()); + item.setDescIndex(iterator.nextU2ToInt()); + item.setIndex(iterator.nextU2ToInt()); + table.addLocalVariableItem(item); + } + return table; + } + + public String toString(ConstantPool pool){ + StringBuffer buffer = new StringBuffer(); + 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/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/StackMapTable.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..69fc63ee81 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/attr/StackMapTable.java @@ -0,0 +1,23 @@ +package main.coding_170430.jvm.attr; + +import main.coding_170430.jvm.loader.ByteCodeIterator; + +/** + * Created by peter on 2017/4/21. + */ +public class StackMapTable extends AttributeInfo { + private String originalCode; + + public StackMapTable(int attrNameIndex,int attrLen){ + super(attrNameIndex,attrLen); + } + public static StackMapTable parse(ByteCodeIterator iterator){ + int index = iterator.nextU2ToInt(); + int len = iterator.nextU4ToInt(); + StackMapTable t = new StackMapTable(index,len); + return t; + } + private void setOriginalCode(String code){ + this.originalCode =code; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/AccessFlag.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..a9dbac985a --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/AccessFlag.java @@ -0,0 +1,28 @@ +package main.coding_170430.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +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; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassFile.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..3e91d99783 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassFile.java @@ -0,0 +1,96 @@ +package main.coding_170430.jvm.clz; + +import main.coding_170430.jvm.constant.ClassInfo; +import main.coding_170430.jvm.constant.ConstantPool; +import main.coding_170430.jvm.field.Field; +import main.coding_170430.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassFile { + private int minorVersion; + private int majorVersion; + + private ConstantPool pool; + private AccessFlag accessFlag; + private ClassIndex clzIndex; + 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 setConstantPool(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.getClzIndex().getSuperClassIndex()); + return superClass.getClassName(); + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassIndex.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..1612dbc29c --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package main.coding_170430.jvm.clz; + +/** + * Created by peter on 2017/4/21. + */ +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public void setThisClassIndex(int thisClassIndex) { + this.thisClassIndex = thisClassIndex; + } + + public void setSuperClassIndex(int superClassIndex) { + this.superClassIndex = superClassIndex; + } + + public int getThisClassIndex() { + return thisClassIndex; + } + + public int getSuperClassIndex() { + return superClassIndex; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/BiPushCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..14cd3f57c1 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/BiPushCmd.java @@ -0,0 +1,20 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class BiPushCmd extends OneOperandCmd { + public BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+":"+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/ByteCodeCommand.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..c085fdf2ce --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,151 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; +import main.coding_170430.jvm.constant.ConstantInfo; +import main.coding_170430.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by peterchen on 2017/4/26. + */ +public abstract class ByteCodeCommand { + String opCode; + ClassFile clzFile; + private int offset; + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private 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 getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + public abstract String toString(ConstantPool pool); + //public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/CommandParser.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..9e0fbcf994 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/CommandParser.java @@ -0,0 +1,127 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peterchen on 2017/4/26. + */ +public class CommandParser { + + public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { + if (codes == null || codes.length() == 0 || (codes.length() % 2) != 0) { + throw new RuntimeException("the original code is not correct"); + } + + codes = codes.toUpperCase(); + + CommandIterator commandIterator = new CommandIterator(codes); + List byteCodeCommands = new ArrayList<>(); + while (commandIterator.hasNext()) { + String opCode = commandIterator.next2CharAsString(); + switch (opCode) { + case ByteCodeCommand.new_object: + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, opCode); + newObjectCmd.setOprand1(commandIterator.nextCharAsInt()); + newObjectCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(newObjectCmd); + break; + case ByteCodeCommand.invokespecial: + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, opCode); + invokeSpecialCmd.setOprand1(commandIterator.nextCharAsInt()); + invokeSpecialCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(invokeSpecialCmd); + break; + case ByteCodeCommand.invokevirtual: + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, opCode); + invokeVirtualCmd.setOprand1(commandIterator.nextCharAsInt()); + invokeVirtualCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(invokeVirtualCmd); + break; + case ByteCodeCommand.getfield: + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, opCode); + getFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + getFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(getFieldCmd); + break; + case ByteCodeCommand.getstatic: + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, opCode); + getStaticFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + getStaticFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(getStaticFieldCmd); + break; + case ByteCodeCommand.putfield: + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, opCode); + putFieldCmd.setOprand1(commandIterator.nextCharAsInt()); + putFieldCmd.setOprand2(commandIterator.nextCharAsInt()); + byteCodeCommands.add(putFieldCmd); + break; + case ByteCodeCommand.ldc: + LdcCmd ldcCmd = new LdcCmd(clzFile, opCode); + ldcCmd.setOperand(commandIterator.nextCharAsInt()); + byteCodeCommands.add(ldcCmd); + break; + case ByteCodeCommand.bipush: + BiPushCmd biPushCmd = new BiPushCmd(clzFile, opCode); + biPushCmd.setOperand(commandIterator.nextCharAsInt()); + byteCodeCommands.add(biPushCmd); + break; + case ByteCodeCommand.dup: + case ByteCodeCommand.aload_0: + case ByteCodeCommand.aload_1: + case ByteCodeCommand.aload_2: + case ByteCodeCommand.iload_1: + case ByteCodeCommand.iload_2: + case ByteCodeCommand.iload_3: + case ByteCodeCommand.fload_3: + case ByteCodeCommand.voidreturn: + case ByteCodeCommand.astore_1: + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, opCode); + byteCodeCommands.add(noOperandCmd); + break; + default: + throw new RuntimeException("Sorry,the instruction " + opCode + " " + "has not implemented"); + + } + } + calcuateOffset(byteCodeCommands); + ByteCodeCommand[] result = new ByteCodeCommand[byteCodeCommands.size()]; + byteCodeCommands.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 code) { + 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 nextCharAsInt() { + String s = this.next2CharAsString(); + return Integer.valueOf(s, 16).intValue(); + } + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..d1403dddee --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,19 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class GetFieldCmd extends TwoOperandCmd { + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetStaticFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..936161fedd --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class GetStaticFieldCmd extends TwoOperandCmd { + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeSpecialCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..1bf5a75153 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,19 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class InvokeSpecialCmd extends TwoOperandCmd { + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeVirtualCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..90cb20b30a --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,24 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class InvokeVirtualCmd extends TwoOperandCmd { + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsMethod(); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/LdcCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..99796850c3 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; +import main.coding_170430.jvm.constant.ConstantInfo; +import main.coding_170430.jvm.constant.StringInfo; + +/** + * Created by peterchen on 2017/4/26. + */ +public class LdcCmd extends OneOperandCmd { + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + ConstantInfo info = 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/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NewObjectCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..902253fe7c --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class NewObjectCmd extends TwoOperandCmd { + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsClassInfo(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NoOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..1ce1e735bc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,22 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class NoOperandCmd extends ByteCodeCommand { + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString() { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + public int getLength(){ + return 1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/OneOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..7905036bcc --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public 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/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/PutFieldCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..edd22d9504 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; + +/** + * Created by peterchen on 2017/4/26. + */ +public class PutFieldCmd extends TwoOperandCmd { + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString() { + + return super.getOperandAsField(); + } + +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/TwoOperandCmd.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..42efb560cb --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,68 @@ +package main.coding_170430.jvm.cmd; + +import main.coding_170430.jvm.clz.ClassFile; +import main.coding_170430.jvm.constant.ClassInfo; +import main.coding_170430.jvm.constant.ConstantInfo; +import main.coding_170430.jvm.constant.FieldRefInfo; +import main.coding_170430.jvm.constant.MethodRefInfo; + +/** + * Created by peterchen on 2017/4/26. + */ +public 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(){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(){ + 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(){ + 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/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ClassInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..708c83e991 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ClassInfo.java @@ -0,0 +1,32 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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; + } + + @Override + public int getType() { + return type; + } + + public String getClassName(){ + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..842a4e4901 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantInfo.java @@ -0,0 +1,33 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantPool.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..ec965ecc2e --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/ConstantPool.java @@ -0,0 +1,26 @@ +package main.coding_170430.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by peter on 2017/4/21. + */ +public class ConstantPool { + private List constantInfos = new ArrayList<>(); + + public ConstantPool(){} + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public ConstantInfo getConstantInfo(int index){ + return this.constantInfos.get(index); + } + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + public int getSizes(){ + return this.constantInfos.size()-1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/FieldRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..8c970d95da --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class FieldRefInfo extends ConstantInfo { + private int type = ConstantInfo.FIELD_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + public int getClassInfoIndex() { + return classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/MethodRefInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..faf2d2d289 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/MethodRefInfo.java @@ -0,0 +1,59 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 getClassInfoIndex() { + return classInfoIndex; + } + + public void setClassInfoIndex(int classInfoIndex) { + this.classInfoIndex = classInfoIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } + + public void setNameAndTypeIndex(int nameAndTypeIndex) { + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + 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 int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NameAndTypeInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..11d4530770 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,53 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NameAndTypeInfo extends ConstantInfo { + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int indexA; + private int indexB; + + public NameAndTypeInfo(ConstantPool pool){ + super(pool); + } + + public int getIndexA() { + return indexA; + } + + public int getIndexB() { + return indexB; + } + + public void setIndexA(int indexA) { + this.indexA = indexA; + } + + public void setIndexB(int indexB) { + this.indexB = indexB; + } + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(indexA); + return utf8Info.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8_info =(UTF8Info) pool.getConstantInfo(indexB); + return utf8_info.getValue(); + } + + @Override + public String toString() { + return "("+getName()+","+getTypeInfo()+")"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NullConstantInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..c8d73b5213 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/NullConstantInfo.java @@ -0,0 +1,16 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/StringInfo.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..e21a1cfcc3 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/StringInfo.java @@ -0,0 +1,31 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/UTF8Info.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..6d83893eda --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +package main.coding_170430.jvm.constant; + +/** + * Created by peter on 2017/4/21. + */ +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 String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + return "UTF8Info [type=" + type + ", length=" + length + ", value=" + value + "]"; + } + + @Override + public int getType() { + return type; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutionResult.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..199452fc8a --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutionResult.java @@ -0,0 +1,46 @@ +package main.coding_170430.jvm.engine; + +import main.coding_170430.jvm.method.Method; + +/** + * Created by peterchen on 2017/5/5. + */ +public class ExecutionResult { + private static final int RUN_NEXT_CMD = 1; + private static final int JUMP = 2; + private static final int EXIT_CURRENT_FRAME = 3; + private static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + private int nextCmdOffset = 0; + private Method nextMethod; + + public Method getNextMethod(){ + return nextMethod; + } + public void setNextMethod(Method method){ + this.nextMethod = nextMethod; + } + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction==PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + public boolean isJump(){ + return this.nextAction == JUMP; + } + public int getNextCmdOffset(){ + return nextCmdOffset; + } + public void setNextCmdOffset(int nextCmdOffset){ + this.nextCmdOffset = nextCmdOffset; + } +} + diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutorEngine.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..b59825da4d --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/ExecutorEngine.java @@ -0,0 +1,20 @@ +package main.coding_170430.jvm.engine; + +import main.coding_170430.jvm.method.Method; + +import java.util.Stack; + +/** + * Created by peterchen on 2017/5/5. + */ +public class ExecutorEngine { + private Stack stack = new Stack<>(); + public ExecutorEngine(){ + + } + public void execute(Method mainMethod){ + } + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame){ + + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/Heap.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/Heap.java new file mode 100644 index 0000000000..bcfb809b36 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/Heap.java @@ -0,0 +1,34 @@ +package main.coding_170430.jvm.engine; + +/** + * Created by peterchen on 2017/5/5. + */ +public class Heap { + private static Heap instance = new Heap(); + private Heap(){ + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setClassName(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/JavaObject.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..4fab5af177 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/JavaObject.java @@ -0,0 +1,70 @@ +package main.coding_170430.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by peterchen on 2017/5/5. + */ +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + private Map fieldValues = new HashMap<>(); + + private String stringValue; + private int intValue; + private float floatValue; + + public void setFieldValues(String fieldName,JavaObject fieldValue){ + fieldValues.put(fieldName,fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch (this.getType()){ + case INT: + return String.valueOf(this.getType()); + case STRING: + return this.stringValue; + case OBJECT: + return this.className+":"+this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default:return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value){ + this.floatValue = value; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MethodArea.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..5b76c3cecb --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MethodArea.java @@ -0,0 +1,52 @@ +package main.coding_170430.jvm.engine; + +import main.coding_170430.jvm.clz.ClassFile; +import main.coding_170430.jvm.constant.MethodRefInfo; +import main.coding_170430.jvm.loader.ClassFileLoader; +import main.coding_170430.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by peterchen on 2017/5/5. + */ +public class MethodArea { + public static final MethodArea instance = new MethodArea(); + + private ClassFileLoader clzLoader = null; + Map map = new HashMap<>(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) { + ClassFile clzFile = findClassFile(className); + return clzFile.getMainMethod(); + } + + public ClassFile findClassFile(String className) { + if (map.get(className) != null) { + return map.get(className); + } + ClassFile classFile = clzLoader.loadClass(className); + map.put(className, classFile); + return classFile; + } + + public Method getMethod(String className, String methodName, String paramANDrETURNtYPE) { + return null; + } + + public Method getMethod(MethodRefInfo methodRefInfo) { + return null; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MinJVM.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MinJVM.java new file mode 100644 index 0000000000..813264c5c4 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/engine/MinJVM.java @@ -0,0 +1,20 @@ +package main.coding_170430.jvm.engine; + +import main.coding_170430.jvm.loader.ClassFileLoader; + +/** + * Created by peterchen on 2017/5/5. + */ +public class MinJVM { + public void run(String[] classPaths,String className){ + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList<>(); + private Stack operatorStack = new Stack<>(); + + int index = 0; + private Method m = null; + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame(){ + return callerFrame; + } + public void setCallerFrame(StackFrame callerFrame){ + this.callerFrame = callerFrame; + } + public static StackFrame create(Method m){ + StackFrame frame = new StackFrame(m); + return frame; + } + private StackFrame(Method m){ + this.m = m; + } + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + public Stack getOperatorStack(){ + return this.operatorStack; + } + public int getNextCommandIndex(int offset){ + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for (int i=0;i values){ + this.localVariableTable = values; + } + public void setLocalVariableValue(int index,JavaObject jo){ + if(localVariableTable.size()-10){ + throw new RuntimeException("Field attribute has not implemented"); + } + return f; + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170430/jvm/loader/ByteCodeIterator.java b/group11/729245768/DataStructure/src/main/coding_170430/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..53cce63392 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170430/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package main.coding_170430.jvm.loader; + +import main.coding_170430.jvm.util.Util; + +import java.util.Arrays; + +/** + * Created by peter on 2017/4/21. + */ +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + public 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[] temp = new byte[len]; + + for(int i=0;i clzPaths = new ArrayList<>(); + public byte[] readBinaryCode(String className){ + className = className.replace('.', File.pathSeparatorChar) +".class"; + for (String path:this.clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes!=null){ + return codes; + } + } + return null; + } + + public 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(clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + public String getClassPath(){ + return StringUtils.join(this.clzPaths,";"); + } + public ClassFile loadClass(String className){ + byte[] codes = this.readBinaryCode(className); + ClassFileParse parser = new ClassFileParse(); + return parser.parse(codes); + } + public String getClassPath_V1(){ + StringBuffer sb = new StringBuffer(); + for(int i=0;i stack = new ArrayList<>(); + private ArrayList minStack= new ArrayList<>(); + public void push(int data) { + stack.add(data); + if(minStack.size()==0){ + minStack.add(data); + }else{ + if(minStack.get(minStack.size()-1)>data){ + minStack.add(data); + } + } + } + + public int pop() { + int data = stack.remove(stack.size()-1); + if(data==minStack.get(minStack.size()-1)){ + minStack.remove(minStack.size()-1); + } + return data; + } + + public int findMin() { + return minStack.get(minStack.size()-1); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170507/StackWithTwoQueues.java b/group11/729245768/DataStructure/src/main/coding_170507/StackWithTwoQueues.java new file mode 100644 index 0000000000..c196d950f3 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170507/StackWithTwoQueues.java @@ -0,0 +1,65 @@ +package main.coding_170507; + +import java.util.EmptyStackException; +import java.util.LinkedList; + +/** + * Created by peterchen on 2017/5/5. + */ +public class StackWithTwoQueues { + private Queue queue1; + private Queue queue2; + + public StackWithTwoQueues() { + queue1 = new Queue(); + queue2 = new Queue(); + } + + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + if (queue1.isEmpty()) { + throw new EmptyStackException(); + } + int currentLength = queue1.size(); + for (int i = 0; i < currentLength - 1; i++) { + queue2.enQueue(queue1.deQueue()); + } + int data = queue1.deQueue(); + while (!queue2.isEmpty()) { + queue1.enQueue(queue2.deQueue()); + } + return data; + } + + private class Queue { + private LinkedList linkedList = new LinkedList<>(); + + public boolean isEmpty() { + return linkedList.size() == 0; + } + + public int size() { + return linkedList.size(); + } + + public void enQueue(Integer data) { + linkedList.add(data); + } + + public Integer deQueue() { + int data = linkedList.removeFirst(); + return data; + } + } + + public static void main(String[] args) { + StackWithTwoQueues stackWithTwoQueues = new StackWithTwoQueues(); + stackWithTwoQueues.push(10); + stackWithTwoQueues.push(20); + stackWithTwoQueues.push(30); + System.out.println(stackWithTwoQueues.pop()); + } +} diff --git a/group11/729245768/DataStructure/src/main/coding_170507/TwoStackInOneArray.java b/group11/729245768/DataStructure/src/main/coding_170507/TwoStackInOneArray.java new file mode 100644 index 0000000000..4c7bb70348 --- /dev/null +++ b/group11/729245768/DataStructure/src/main/coding_170507/TwoStackInOneArray.java @@ -0,0 +1,85 @@ +package main.coding_170507; + +import java.util.EmptyStackException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + private int start = 0; + private int end = data.length-1; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + if(start==end){ + throw new RuntimeException("栈满"); + } + data[start++] = o; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if(start==0){ + throw new EmptyStackException(); + } + return data[--start]; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + if(start==0){ + throw new EmptyStackException(); + } + return data[start-1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + if(start==end){ + throw new RuntimeException("栈满"); + } + data[end--] = o; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if(end==data.length-1){ + throw new EmptyStackException(); + } + return data[++end]; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + if(end==data.length-1){ + throw new EmptyStackException(); + } + return data[end+1]; + } +} diff --git a/group11/729245768/DataStructure/tests/main/coding_170327/Employee.java b/group11/729245768/DataStructure/tests/main/coding_170327/Employee.java new file mode 100644 index 0000000000..29c364810d --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170327/Employee.java @@ -0,0 +1,28 @@ +package main.coding_170327; + +/** + * Created by peter on 2017/4/20. + */ +public class Employee { + private String name; + private int age; + public Employee(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(String name){ + System.out.println("Hello, "+name); + } + + public static void main(String[] args) { + + } +} diff --git a/group11/729245768/DataStructure/tests/main/coding_170327/LRUPageFrameTest.java b/group11/729245768/DataStructure/tests/main/coding_170327/LRUPageFrameTest.java new file mode 100644 index 0000000000..4a4e4b0a27 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170327/LRUPageFrameTest.java @@ -0,0 +1,35 @@ +package main.coding_170327; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/19. + */ +public class LRUPageFrameTest extends TestCase { + @Test + public void testAccess() throws Exception { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("[1, 0, 7]", frame.toString()); + frame.access(2); + Assert.assertEquals("[2, 1, 0]", frame.toString()); + frame.access(0); + Assert.assertEquals("[0, 2, 1]", frame.toString()); + frame.access(0); + Assert.assertEquals("[0, 2, 1]", frame.toString()); + frame.access(3); + Assert.assertEquals("[3, 0, 2]", frame.toString()); + frame.access(0); + Assert.assertEquals("[0, 3, 2]", frame.toString()); + frame.access(4); + Assert.assertEquals("[4, 0, 3]", frame.toString()); + frame.access(5); + Assert.assertEquals("[5, 4, 0]", frame.toString()); + } + + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170327/loader/ClassFileLoaderTest.java b/group11/729245768/DataStructure/tests/main/coding_170327/loader/ClassFileLoaderTest.java new file mode 100644 index 0000000000..4cbdc85daf --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170327/loader/ClassFileLoaderTest.java @@ -0,0 +1,54 @@ +package main.coding_170327.loader; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/20. + */ +public class ClassFileLoaderTest extends TestCase { + public static final String FULL_QUALIFIED_CLASS_NAME = "main/coding_170327/Employee"; + static String path1 = "E:\\IDEASpace\\coding2017\\group11\\729245768\\DataStructure\\tests"; + static String path2 = "C:\temp"; + + @Test + public void testClassPath(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + Assert.assertEquals(path1+";"+path2,loader.getClassPath()); + } + @Test + public void testClassFileLength(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "main.coding_170327.Employee"; + byte[] codes = loader.readBinaryCodes(className); + Assert.assertEquals(891,codes.length); + } + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "main.coding_170327.Employee"; + byte[] codes = loader.readBinaryCodes(className); + byte[] magicNumbers = new byte[]{codes[0],codes[1],codes[2],codes[3]}; + String magic = byteToHexString(magicNumbers); + Assert.assertEquals("cafebabe",magic); + } + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i stack = new Stack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + StackUtil.reverse(stack); + Assert.assertArrayEquals(new Integer[]{3,2,1},new Integer[]{stack.pop(),stack.pop(),stack.pop()}); + } + + @Test + public void testAddToBottom() throws Exception { + Stack stack = new Stack<>(); + stack.push(1); + stack.push(2); + StackUtil.addToBottom(stack,1); + Assert.assertEquals(1,stack.peek().intValue()); + } + + @Test + public void testRemove() throws Exception { + Stack stack = new Stack<>(); + stack.push(10); + stack.push(20); + stack.push(30); + StackUtil.remove(stack,20); + Assert.assertEquals(2,stack.size()); + } + + @Test + public void testGetTop() throws Exception { + Stack stack = new Stack<>(); + stack.push(10); + stack.push(15); + stack.push(21); + stack.push(19); + stack.push(89); + StackUtil.getTop(stack,2); + Assert.assertEquals(3,stack.size()); + } + + @Test + public void testIsValidPairs() throws Exception { + String s1 = "([e{d}f])"; + String s2 = "([b{x]y})"; + Assert.assertTrue(StackUtil.isValidPairs(s1)); + Assert.assertFalse(StackUtil.isValidPairs(s2)); + + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/ClassFileParseTest.java b/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/ClassFileParseTest.java new file mode 100644 index 0000000000..57f922caf4 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/ClassFileParseTest.java @@ -0,0 +1,25 @@ +package main.coding_170409.jvm.loader; + +import junit.framework.TestCase; +import main.coding_170409.jvm.constant.ConstantPool; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/23. + */ +public class ClassFileParseTest extends TestCase { + static String path1 = "E:\\IDEASpace\\coding2017\\group11\\729245768\\DataStructure\\tests"; + + @Test + public void testParse() throws Exception { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String clzName = "main.coding_170409.Employee"; + byte[] codes = loader.readBinaryCode(clzName); + ClassFileParse parse = new ClassFileParse(); + ConstantPool pool = parse.parse(codes); + Assert.assertEquals(54,pool.getSizes()); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/Employee.java b/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/Employee.java new file mode 100644 index 0000000000..98cf9bb578 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170409/jvm/loader/Employee.java @@ -0,0 +1,28 @@ +package main.coding_170409.jvm.loader; + +/** + * Created by peter on 2017/4/20. + */ +public class Employee { + private String name; + private int age; + public Employee(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(String name){ + System.out.println("Hello, "+name); + } + + public static void main(String[] args) { + + } +} diff --git a/group11/729245768/DataStructure/tests/main/coding_170416/Employee.java b/group11/729245768/DataStructure/tests/main/coding_170416/Employee.java new file mode 100644 index 0000000000..267ce99495 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170416/Employee.java @@ -0,0 +1,28 @@ +package main.coding_170416; + +/** + * Created by peter on 2017/4/20. + */ +public class Employee { + private String name; + private int age; + public Employee(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(String name){ + System.out.println("Hello, "+name); + } + + public static void main(String[] args) { + + } +} diff --git a/group11/729245768/DataStructure/tests/main/coding_170416/InfixExprTest.java b/group11/729245768/DataStructure/tests/main/coding_170416/InfixExprTest.java new file mode 100644 index 0000000000..90de74d213 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170416/InfixExprTest.java @@ -0,0 +1,17 @@ +package main.coding_170416; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/23. + */ +public class InfixExprTest extends TestCase { + @Test + public void testEvalute() throws Exception { + InfixExpr infixExpr = new InfixExpr("2+10*2-14/2"); + Assert.assertEquals(15,infixExpr.evalute(),0.001f); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170416/jvm/loader/ClassFileParseTest.java b/group11/729245768/DataStructure/tests/main/coding_170416/jvm/loader/ClassFileParseTest.java new file mode 100644 index 0000000000..f519d09a46 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170416/jvm/loader/ClassFileParseTest.java @@ -0,0 +1,42 @@ +package main.coding_170416.jvm.loader; + +import junit.framework.TestCase; +import main.coding_170416.jvm.clz.ClassFile; +import main.coding_170416.jvm.field.Field; +import main.coding_170416.jvm.method.Method; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +/** + * Created by peter on 2017/4/23. + */ +public class ClassFileParseTest extends TestCase { + static String path1 = "E:\\IDEASpace\\coding2017\\group11\\729245768\\DataStructure\\tests"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "main.coding_170416.Employee"; + clzFile = loader.loadClass(className); + } + + @Test + public void testParseFields() throws Exception { + List fields = clzFile.getFields(); + Assert.assertEquals(2,fields.size()); + Field f1 = fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f1.toString()); + Field f2 = fields.get(1); + Assert.assertEquals("age:;I", f2.toString()); + } + + @Test + public void testParseMethods() throws Exception { + List methods = clzFile.getMethods(); + Assert.assertEquals(5,methods.size()); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170423/PostfixExprTest.java b/group11/729245768/DataStructure/tests/main/coding_170423/PostfixExprTest.java new file mode 100644 index 0000000000..9630beb57a --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170423/PostfixExprTest.java @@ -0,0 +1,21 @@ +package main.coding_170423; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/23. + */ +public class PostfixExprTest extends TestCase { + @Test + public void testEvaluate() throws Exception { + PostfixExpr post1 = new PostfixExpr("3 4 + 5 * 6 -"); + Assert.assertEquals(29,post1.evaluate(),0.001f); + + PostfixExpr post2 = new PostfixExpr("2 8 4 / + 5 -"); + Assert.assertEquals(-1,post2.evaluate(),0.001f); + + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170423/PrefixExprTest.java b/group11/729245768/DataStructure/tests/main/coding_170423/PrefixExprTest.java new file mode 100644 index 0000000000..a258260bef --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170423/PrefixExprTest.java @@ -0,0 +1,17 @@ +package main.coding_170423; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by peter on 2017/4/23. + */ +public class PrefixExprTest extends TestCase { + @Test + public void testEvaluate() throws Exception { + PrefixExpr pre = new PrefixExpr("- * + 3 4 5 6"); + Assert.assertEquals(29,pre.evaluate(),0.001f); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170430/CircleQueueTest.java b/group11/729245768/DataStructure/tests/main/coding_170430/CircleQueueTest.java new file mode 100644 index 0000000000..916eeb45db --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170430/CircleQueueTest.java @@ -0,0 +1,56 @@ +package main.coding_170430; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by peterchen on 2017/5/4. + */ +public class CircleQueueTest extends TestCase { + @Test + public void testIsEmpty() throws Exception { + CircleQueue queue = new CircleQueue<>(); + Assert.assertTrue(queue.isEmpty()); + } + + @Test + public void testSize() throws Exception { + CircleQueue queue = new CircleQueue<>(); + Assert.assertEquals(queue.size(),0); + queue.enQueue(12); + queue.enQueue(23); + Assert.assertEquals(queue.size(),2); + } + + @Test + public void testEnQueue() throws Exception { + CircleQueue queue = new CircleQueue<>(); + for(int i=0;i<9;i++){ + queue.enQueue(i); + } + Assert.assertEquals(queue.size(),9); + queue.deQueue(); + queue.enQueue(10); + } + + @Test + public void testDeQueue() throws Exception { + CircleQueue queue = new CircleQueue<>(); + for(int i=0;i<5;i++){ + queue.enQueue(i); + } + Assert.assertEquals(queue.size(),5); + queue.deQueue(); + queue.deQueue(); + queue.deQueue(); + Assert.assertEquals(queue.size(),2); + for(int i=10;i<17;i++){ + queue.enQueue(i); + } + Assert.assertEquals(queue.size(),9); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170430/JosephusTest.java b/group11/729245768/DataStructure/tests/main/coding_170430/JosephusTest.java new file mode 100644 index 0000000000..afe90e4fff --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170430/JosephusTest.java @@ -0,0 +1,25 @@ +package main.coding_170430; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.*; + +/** + * Created by peterchen on 2017/5/4. + */ +public class JosephusTest extends TestCase { + @Test + public void testExecute() throws Exception { + List list = Josephus.execute(8,3); + int[] arrays = new int[list.size()]; + for(int i=0;i twoStacks = new QueueWithTwoStacks<>(); + Assert.assertTrue(twoStacks.isEmpty()); + } + + @Test + public void testSize() throws Exception { + QueueWithTwoStacks twoStacks = new QueueWithTwoStacks<>(); + twoStacks.enQueue(10); + twoStacks.enQueue(5); + Assert.assertEquals(twoStacks.size(),2); + } + + @Test + public void testEnQueue() throws Exception { + QueueWithTwoStacks twoStacks = new QueueWithTwoStacks<>(); + twoStacks.enQueue(10); + twoStacks.enQueue(5); + twoStacks.enQueue(15); + } + + @Test + public void testDeQueue() throws Exception { + QueueWithTwoStacks twoStacks = new QueueWithTwoStacks<>(); + twoStacks.enQueue(10); + twoStacks.enQueue(5); + twoStacks.enQueue(15); + twoStacks.enQueue(1); + twoStacks.enQueue(51); + twoStacks.enQueue(12); + twoStacks.enQueue(11); + twoStacks.enQueue(50); + twoStacks.enQueue(150); + while (!twoStacks.isEmpty()){ + System.out.print(" "+twoStacks.deQueue()); + } + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170507/QuickMinStackTest.java b/group11/729245768/DataStructure/tests/main/coding_170507/QuickMinStackTest.java new file mode 100644 index 0000000000..2b2c4bd5c1 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170507/QuickMinStackTest.java @@ -0,0 +1,45 @@ +package main.coding_170507; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by peterchen on 2017/5/5. + */ +public class QuickMinStackTest extends TestCase { + @Test + public void testPush() throws Exception { + QuickMinStack minStack = new QuickMinStack(); + minStack.push(5); + minStack.push(10); + minStack.push(3); + Assert.assertEquals(minStack.pop(),3); + Assert.assertEquals(minStack.pop(),10); + Assert.assertEquals(minStack.pop(),5); + } + + @Test + public void testPop() throws Exception { + QuickMinStack minStack = new QuickMinStack(); + minStack.push(5); + minStack.push(10); + Assert.assertEquals(minStack.pop(),10); + Assert.assertEquals(minStack.pop(),5); + } + + @Test + public void testFindMin() throws Exception { + QuickMinStack minStack = new QuickMinStack(); + minStack.push(15); + minStack.push(10); + Assert.assertEquals(minStack.findMin(),10); + minStack.pop(); + minStack.push(20); + Assert.assertEquals(minStack.findMin(),15); + + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170507/StackWithTwoQueuesTest.java b/group11/729245768/DataStructure/tests/main/coding_170507/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..ee8ef3bda8 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170507/StackWithTwoQueuesTest.java @@ -0,0 +1,34 @@ +package main.coding_170507; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by peterchen on 2017/5/5. + */ +public class StackWithTwoQueuesTest extends TestCase { + @Test + public void testPush() throws Exception { + StackWithTwoQueues twoQueues = new StackWithTwoQueues(); + twoQueues.push(1); + twoQueues.push(2); + twoQueues.push(3); + Assert.assertEquals(3,twoQueues.pop()); + Assert.assertEquals(2,twoQueues.pop()); + } + + @Test + public void testPop() throws Exception { + StackWithTwoQueues twoQueues = new StackWithTwoQueues(); + twoQueues.push(15); + twoQueues.pop(); + twoQueues.push(20); + twoQueues.push(30); + Assert.assertEquals(30,twoQueues.pop()); + Assert.assertEquals(20,twoQueues.pop()); + } + +} \ No newline at end of file diff --git a/group11/729245768/DataStructure/tests/main/coding_170507/TwoStackInOneArrayTest.java b/group11/729245768/DataStructure/tests/main/coding_170507/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..5764cf5923 --- /dev/null +++ b/group11/729245768/DataStructure/tests/main/coding_170507/TwoStackInOneArrayTest.java @@ -0,0 +1,77 @@ +package main.coding_170507; + +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by peterchen on 2017/5/5. + */ +public class TwoStackInOneArrayTest extends TestCase { + @Test + public void testPush1() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push1(1); + inOneArray.push1(2); + inOneArray.push1(3); + Assert.assertEquals(3,inOneArray.peek1()); + inOneArray.pop1(); + Assert.assertEquals(2,inOneArray.peek1()); + } + + @Test + public void testPop1() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push1(10); + inOneArray.push1(20); + inOneArray.pop1(); + inOneArray.push1(30); + inOneArray.push1(50); + Assert.assertEquals(50,inOneArray.peek1()); + inOneArray.pop1(); + Assert.assertEquals(30,inOneArray.peek1()); + } + + @Test + public void testPeek1() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push1(100); + Assert.assertEquals(100,inOneArray.peek1()); + } + + @Test + public void testPush2() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push2(10); + inOneArray.push2(20); + inOneArray.push1(15); + inOneArray.push1(25); + Assert.assertEquals(20,inOneArray.peek2()); + Assert.assertEquals(25,inOneArray.peek1()); + } + + @Test + public void testPop2() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push2(10); + inOneArray.push2(20); + inOneArray.pop2(); + inOneArray.pop2(); + inOneArray.push2(25); + inOneArray.push2(24); + Assert.assertEquals(24,inOneArray.peek2()); + inOneArray.pop2(); + Assert.assertEquals(25,inOneArray.peek2()); + } + + @Test + public void testPeek2() throws Exception { + TwoStackInOneArray inOneArray = new TwoStackInOneArray(); + inOneArray.push2(100); + inOneArray.push2(200); + Assert.assertEquals(200,inOneArray.peek2()); + } + +} \ No newline at end of file diff --git a/group11/996108220/src/com/coderising/jvm/attr/AttributeInfo.java b/group11/996108220/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..89fb53394e --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group11/996108220/src/com/coderising/jvm/attr/CodeAttr.java b/group11/996108220/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..dfc85bdb8e --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,74 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.LdcCmd; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + + +public class CodeAttr extends AttributeInfo { + private int maxStack ;//u4 + private int maxLocals ;//u2 + 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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + +// public ByteCodeCommand[] getCmds() { +// // TODO Auto-generated method stub +// int index=0; +// ArrayList list=new ArrayList<>(); +// while (index<=code.length()) { +// String opCode=code.substring(index,index+1); +// if (opCode.equals("2a")) { +// list.add(new LdcCmd(clzFile, opCode)); +// } +// +// } +// return null; +// } + + + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/attr/LineNumberTable.java b/group11/996108220/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..415c7b329b --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,48 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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 void parse(ByteCodeIterator iter){ + int count=iter.nextU2ToInt(); + for (int j = 0; j items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public void parse(ByteCodeIterator iter){ + int count=iter.nextU2ToInt(); + for (int i = 0; i < count; i++) { + LocalVariableItem item=new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + this.addLocalVariableItem(item); + } + + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group11/996108220/src/com/coderising/jvm/attr/StackMapTable.java b/group11/996108220/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..b1da6c79f7 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.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/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java b/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java index 8575f5641a..94056eb2e0 100644 --- a/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java +++ b/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java @@ -1,7 +1,13 @@ package com.coderising.jvm.clz; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; public class ClassFile { @@ -10,7 +16,8 @@ public class ClassFile { private AccessFlag accessFlag; private ClassIndex clzIndex; private ConstantPool pool; - + private List fields = new ArrayList(); + private List methods = new ArrayList(); public ClassIndex getClzIndex() { return clzIndex; @@ -46,7 +53,18 @@ public void setConstPool(ConstantPool 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; + } @@ -62,13 +80,26 @@ public void print(){ } - 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 getMainMethod() { + return getMethod("main", null); + } + public Method getMethod(String string, String string2) { + for (int i = 0; i < methods.size(); i++) { + Method method=methods.get(i); + UTF8Info utf8Info=(UTF8Info)pool.getConstantInfo(method.getNameIndex()); + if (utf8Info.getValue().equals(string)) { + return method; + } + } + return null; + } } diff --git a/group11/996108220/src/com/coderising/jvm/cmd/AstoreCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/AstoreCmd.java new file mode 100644 index 0000000000..ea84805be1 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/AstoreCmd.java @@ -0,0 +1,12 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; + +public class AstoreCmd extends NoOperandCmd{ + + public AstoreCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + // TODO Auto-generated constructor stub + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/BiPushCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..1f60641d2d --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +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(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group11/996108220/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..892bfcd51d --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +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");//3 + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield");//3 + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0");//1 + codeMap.put("2B", "aload_1");//1 + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode.toUpperCase()); + if(txt == null){ + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame,ExecutionResult result); +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/CommandParser.java b/group11/996108220/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..fb48eb2910 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,163 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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) { + ArrayList list=new ArrayList<>(); + CommandIterator iterator=new CommandIterator(codes); + while (iterator.hasNext()) { + String opCode=iterator.next2CharAsString(); + if (opCode.equalsIgnoreCase(aload_0)) { + list.add(new LoadCmd(clzFile, opCode)); + } + else if (opCode.equalsIgnoreCase(invokespecial)) { + InvokeSpecialCmd invokeSpecialCmd=new InvokeSpecialCmd(clzFile, opCode); + invokeSpecialCmd.setOprand1(iterator.next2CharAsInt()); + invokeSpecialCmd.setOprand2(iterator.next2CharAsInt()); + list.add(invokeSpecialCmd); + + } + else if (opCode.equalsIgnoreCase(aload_1)) { + list.add(new LoadCmd(clzFile, opCode)); + } + else if (opCode.equalsIgnoreCase(putfield)){ + PutFieldCmd putFieldCmd=new PutFieldCmd(clzFile, opCode); + putFieldCmd.setOprand1(iterator.next2CharAsInt()); + putFieldCmd.setOprand2(iterator.next2CharAsInt()); + list.add(putFieldCmd); + + } + else if (opCode.equalsIgnoreCase(iload_2)) { + list.add(new LoadCmd(clzFile, opCode)); + } + else if (opCode.equalsIgnoreCase(new_object)) { + NewObjectCmd newObjectCmd=new NewObjectCmd(clzFile, opCode); + newObjectCmd.setOprand1(iterator.next2CharAsInt()); + newObjectCmd.setOprand2(iterator.next2CharAsInt()); + list.add(newObjectCmd); + } + else if (opCode.equalsIgnoreCase(dup)) { + + list.add(new DupCmd(clzFile, opCode)); + } + else if (opCode.equalsIgnoreCase(bipush)) { + BiPushCmd biPushCmd=new BiPushCmd(clzFile, opCode); + biPushCmd.setOperand(iterator.next2CharAsInt()); + list.add(biPushCmd); + } + else if (opCode.equalsIgnoreCase(invokevirtual)) { + InvokeVirtualCmd invokeVirtualCmd=new InvokeVirtualCmd(clzFile, opCode); + invokeVirtualCmd.setOprand1(iterator.next2CharAsInt()); + invokeVirtualCmd.setOprand2(iterator.next2CharAsInt()); + list.add(invokeVirtualCmd); + } + else if (opCode.equalsIgnoreCase(voidreturn)) { + list.add(new VoidReturnCmd(clzFile, opCode)); + } + else if (opCode.equalsIgnoreCase(getstatic)) { + GetStaticFieldCmd getStaticFieldCmd=new GetStaticFieldCmd(clzFile, opCode); + getStaticFieldCmd.setOprand1(iterator.next2CharAsInt()); + getStaticFieldCmd.setOprand2(iterator.next2CharAsInt()); + list.add(getStaticFieldCmd); + } + else if (opCode.equalsIgnoreCase(getfield)) { + GetFieldCmd getFieldCmd=new GetFieldCmd(clzFile, opCode); + getFieldCmd.setOprand1(iterator.next2CharAsInt()); + getFieldCmd.setOprand2(iterator.next2CharAsInt()); + list.add(getFieldCmd); + } + else if (opCode.equalsIgnoreCase(ldc)) { + LdcCmd ldcCmd=new LdcCmd(clzFile, opCode); + ldcCmd.setOperand(iterator.next2CharAsInt()); + list.add(ldcCmd); + } + else if (opCode.equalsIgnoreCase(astore_1)) { + list.add(new AstoreCmd(clzFile, opCode)); + } + } + calcuateOffset(list); + ByteCodeCommand [] byteCodeCommands=new ByteCodeCommand [list.size()]; + for (int i = 0; i < byteCodeCommands.length; i++) { + byteCodeCommands[i]=list.get(i); + } + return byteCodeCommands; + } + + 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/group11/996108220/src/com/coderising/jvm/cmd/DupCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/DupCmd.java new file mode 100644 index 0000000000..6ad1802585 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/DupCmd.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class DupCmd extends NoOperandCmd{ + + public DupCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + // TODO Auto-generated constructor stub + } + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..c771d535f7 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6876c36bb --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..8d60e72341 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..a1f2d1a1c6 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/LdcCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..d6b102981b --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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; + + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} \ No newline at end of file diff --git a/group11/996108220/src/com/coderising/jvm/cmd/LoadCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/LoadCmd.java new file mode 100644 index 0000000000..8597ec613d --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/LoadCmd.java @@ -0,0 +1,12 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; + +public class LoadCmd extends NoOperandCmd { + + public LoadCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + // TODO Auto-generated constructor stub + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..caa2609928 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..c3cda9b52e --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..71e09f7578 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +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/group11/996108220/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..dc31cf084d --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile,String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + + } + + +} diff --git a/group11/996108220/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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/group11/996108220/src/com/coderising/jvm/cmd/VoidReturnCmd.java b/group11/996108220/src/com/coderising/jvm/cmd/VoidReturnCmd.java new file mode 100644 index 0000000000..ffc06f8fa1 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/cmd/VoidReturnCmd.java @@ -0,0 +1,12 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; + +public class VoidReturnCmd extends NoOperandCmd{ + + public VoidReturnCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + // TODO Auto-generated constructor stub + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java b/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java index 86c0445695..93506b1e20 100644 --- a/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java +++ b/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java @@ -23,7 +23,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group11/996108220/src/com/coderising/jvm/engine/ExecutionResult.java b/group11/996108220/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..8f6c51e52a --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/engine/ExecutorEngine.java b/group11/996108220/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..9b671c4cdb --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + StackFrame mainFrame=StackFrame.create(mainMethod); + stack.push(mainFrame); + while (!stack.isEmpty()) { + StackFrame frame=stack.peek(); + ExecutionResult result=frame.execute(); + if (result.isPauseAndRunNewFrame()) { + Method nextMethod=result.getNextMethod(); + StackFrame nextFrame=StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + //设置传入参数 + setupFunctionCallParams(frame, nextFrame); + stack.push(nextFrame); + } + else { + stack.pop(); + } + + } + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + Method nextMethod=nextFrame.getMethod(); + n + + + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/engine/Heap.java b/group11/996108220/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/engine/JavaObject.java b/group11/996108220/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/engine/MethodArea.java b/group11/996108220/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..781e81acf1 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,68 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/group11/996108220/src/com/coderising/jvm/engine/MiniJVM.java b/group11/996108220/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..443524cc5f --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group11/996108220/src/com/coderising/jvm/field/Field.java b/group11/996108220/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..5c58695b9a --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,38 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag;//u2 + private int nameIndex;//u2 + private int descriptorIndex;//u2 + + + + 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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + public String toString() { + UTF8Info name=(UTF8Info)(pool.getConstantInfo(nameIndex)); + UTF8Info descriptor=(UTF8Info)(pool.getConstantInfo(descriptorIndex)); + return name.getValue()+":"+descriptor.getValue(); + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java index a151decad8..e9400b2cfd 100644 --- a/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ b/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -1,6 +1,7 @@ package com.coderising.jvm.loader; import java.util.Arrays; + import com.coderising.jvm.util.Util; @@ -47,5 +48,10 @@ public byte[] getByte(int length) { cursor=cursor+length; return Arrays.copyOfRange(codes,i, cursor); } + public String getString(int codeLen) { + int i=cursor; + cursor=cursor+codeLen; + return Arrays.copyOfRange(codes,i, cursor).toString(); + } } diff --git a/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java b/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java index ac55f25e0e..cbe619c4a5 100644 --- a/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java +++ b/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java @@ -1,4 +1,7 @@ package com.coderising.jvm.loader; +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.attr.LineNumberTable; +import com.coderising.jvm.attr.LocalVariableTable; import com.coderising.jvm.clz.AccessFlag; import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.clz.ClassIndex; @@ -10,7 +13,10 @@ import com.coderising.jvm.constant.NullConstantInfo; import com.coderising.jvm.constant.StringInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; import com.coderising.jvm.util.Util; +import com.sun.org.apache.bcel.internal.classfile.LineNumber; public class ClassFileParser { @@ -23,12 +29,80 @@ public ClassFile parse(byte[] codes) { ClassFile classFile=new ClassFile(); classFile.setMinorVersion(iter.nextU2ToInt()); classFile.setMajorVersion(iter.nextU2ToInt()); - classFile.setConstPool(parseConstantPool(iter)); + ConstantPool pool=parseConstantPool(iter); + classFile.setConstPool(pool); classFile.setAccessFlag(parseAccessFlag(iter)); classFile.setClassIndex(parseClassInfex(iter)); + parseInterfaces(iter); + int fieldCount=iter.nextU2ToInt(); + 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); + } + @Test + public void testByteCodeCommand(){ + { + Method initMethod = 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 = 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 = 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 = 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/group11/996108220/src/com/coderising/jvm/test/MiniJVMTest.java b/group11/996108220/src/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..787c0d954d --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} diff --git a/group11/996108220/src/com/coding/basic/queue/CircleQueue.java b/group11/996108220/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..cfb51ef3b1 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,54 @@ +package com.coding.basic.queue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return front==rear; + + } + + public int size() { + return (rear-front)%DEFAULT_SIZE; + } + + + + public void enQueue(E data) { + if ((rear+1)%DEFAULT_SIZE==front) { + throw(new ArrayIndexOutOfBoundsException()); + } + else { + elementData[rear]=data; + rear=(rear+1)%DEFAULT_SIZE; + } + } + + public E deQueue() { + if (isEmpty()) { + throw(new NullPointerException()); + + } + else { + int index=front; + front=(front+1)%DEFAULT_SIZE; + return (E) elementData[index] ; + } + + } +} diff --git a/group11/996108220/src/com/coding/basic/queue/Josephus.java b/group11/996108220/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..2816df89b7 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,33 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +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){ + List list=new ArrayList(); + for (int i = 1; i <= n; i++) { + list.add(fun(n,m,i)); + } + return list; + } + + private static Integer fun(int n, int m, int i) { + if (i==1) { + return (n+m-1)%n; + } + else { + return (fun(n-1, m, i-1)+m)%n; + } + } + +} diff --git a/group11/996108220/src/com/coding/basic/queue/JosephusTest.java b/group11/996108220/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group11/996108220/src/com/coding/basic/queue/Queue.java b/group11/996108220/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/group11/996108220/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group11/996108220/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group11/996108220/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..5d4a25fb96 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,55 @@ +package com.coding.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 size()==0; + } + + + + public int size() { + return stack1.size()+stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(isEmpty()){ + throw(new NullPointerException()); + } + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + return stack2.pop(); + } + + + + } + diff --git a/group11/996108220/src/com/coding/basic/stack/InfixExpr.java b/group11/996108220/src/com/coding/basic/stack/InfixExpr.java new file mode 100644 index 0000000000..0f333d6a00 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/InfixExpr.java @@ -0,0 +1,92 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; +import java.util.StringTokenizer; + +public class InfixExpr { + ArrayList list=new ArrayList<>(); + Stack numStack=new Stack(); + Stack operStack=new Stack(); + public InfixExpr(String s) { + StringTokenizer st = new StringTokenizer(s, "\\+|\\-|\\*|\\/", true); + + while(st.hasMoreElements()){ + list.add(st.nextToken()); + } + } + //5-2+3 6/2*3 5-2+3*4 2+3-5 + public float evaluate() { + + for (int i = 0; i < list.size(); i++) { + + if (list.get(i).charAt(0)=='+') { + if (operStack.size()==0) { + operStack.push(list.get(i).charAt(0)); + continue; + } + if ((char)operStack.peek()=='-'||(char)operStack.peek()=='*'||(char)operStack.peek()=='/') { + numStack.push(caculate()); + } + operStack.push(list.get(i).charAt(0)); + } + else if (list.get(i).charAt(0)=='-') { + if (operStack.size()==0) { + operStack.push(list.get(i).charAt(0)); + continue; + } + if ((char)operStack.peek()=='*'||(char)operStack.peek()=='/') { + numStack.push(caculate()); + } + operStack.push(list.get(i).charAt(0)); + } + else if (list.get(i).charAt(0)=='*') { + if (operStack.size()==0) { + operStack.push(list.get(i).charAt(0)); + continue; + } + if ((char)operStack.peek()=='/') { + numStack.push(caculate()); + } + operStack.push(list.get(i).charAt(0)); + } + else if (list.get(i).charAt(0)=='/') { + if (operStack.size()==0) { + operStack.push(list.get(i).charAt(0)); + continue; + } + operStack.push(list.get(i).charAt(0)); + } + else { + numStack.push(Float.parseFloat(list.get(i))); + } + + } + while (operStack.size()!=0) { + + numStack.push(caculate()); + } + return (float) numStack.pop(); + } + public float caculate(){ + char opf=(char) operStack.pop(); + float op2=(float) numStack.pop(); + float op1=(float) numStack.pop(); + float tmpResult = 0; + switch(opf){ + case '+': + tmpResult = op1 + op2; + break; + case '-': + tmpResult = op1 - op2; + break; + case '*': + tmpResult = op1 * op2; + break; + case '/': + tmpResult = op1 / op2; + break; + } + return tmpResult; + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/QuickMinStack.java b/group11/996108220/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..1b124ab005 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + Stack stack=null; + Stack min=null; + public QuickMinStack() { + stack=new Stack(); + min=new Stack(); + } + public void push(int data){ + if (stack.isEmpty()) { + int copy=data; + push(data); + push(copy); + + } + else { + if (data<(int)min.peek()) { + int copy=data; + push(data); + push(copy); + } + else { + stack.push(data); + min.push(min.peek()); + } + } + } + public int pop(){ + if (stack.isEmpty()) { + throw(new NullPointerException()); + } + min.pop(); + return (int) stack.pop(); + } + public int findMin(){ + return (int) min.peek(); + } +} diff --git a/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java b/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java index 91e3211683..6d7d2e013f 100644 --- a/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java +++ b/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java @@ -9,6 +9,8 @@ import org.junit.BeforeClass; import org.junit.Test; +import com.coding.basic.stack.expr.InfixExpr; + public class StackUtilTest { Stack s; @Before @@ -78,5 +80,24 @@ public void testIsValidPairs() { String s="([e{df])" ; Assert.assertEquals(false, StackUtil.isValidPairs(s)); } + //5-2+3 6/2*3 5-2+3*4 2+3-5 + @Test + public void testevaluate() { + InfixExpr expr = new InfixExpr("2+3*4+5"); + System.out.println(expr.evaluate()); + Assert.assertEquals(19, expr.evaluate(), 0.001f); + InfixExpr expr1 = new InfixExpr("5-2+3"); + System.out.println(expr1.evaluate()); + Assert.assertEquals(6, expr1.evaluate(), 0.001f); + InfixExpr expr2 = new InfixExpr("6/2*3"); + System.out.println(expr2.evaluate()); + Assert.assertEquals(9, expr2.evaluate(), 0.001f); + InfixExpr expr3 = new InfixExpr("50-2+3*4"); + System.out.println(expr3.evaluate()); + Assert.assertEquals(60, expr3.evaluate(), 0.001f); + InfixExpr expr4 = new InfixExpr("20+30-50"); + System.out.println(expr4.evaluate()); + Assert.assertEquals(0, expr4.evaluate(), 0.001f); + } } diff --git a/group11/996108220/src/com/coding/basic/stack/StackWithTwoQueues.java b/group11/996108220/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..15eba7add3 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,42 @@ +package com.coding.basic.stack; + +import com.coding.basic.Queue; + + +public class StackWithTwoQueues { + Queue queue1=new Queue<>(); + Queue queue2=new Queue<>(); + + public void push(int data) { + if (queue1.isEmpty()&&queue2.isEmpty()) { + queue1.enQueue(data); + } + else if (queue1.isEmpty()&&!queue2.isEmpty()) { + queue2.enQueue(data); + } + else if (!queue1.isEmpty()&&queue2.isEmpty()) { + queue1.enQueue(data); + } + } + + public int pop() { + if (queue1.isEmpty()&&queue2.isEmpty()) { + throw(new RuntimeException()); + } + else if (queue1.isEmpty()&&!queue2.isEmpty()) { + for (int i = 0; i < queue2.size()-1; i++) { + queue1.enQueue((int)queue2.deQueue()); + } + return (int) queue2.deQueue(); + } + else if (!queue1.isEmpty()&&queue2.isEmpty()) { + for (int i = 0; i < queue1.size()-1; i++) { + queue2.enQueue((int)queue1.deQueue()); + } + return (int) queue1.deQueue(); + } + return 0; + } + + +} diff --git a/group11/996108220/src/com/coding/basic/stack/TwoStackInOneArray.java b/group11/996108220/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..83e8f611dc --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,84 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + int top1=-1; + int top2=10; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if (top1+1==top2) { + grow(data,top1,top2); + } + data[++top1]=o; + } + private void grow(Object[] data2,int top1, int top2) { + // TODO Auto-generated method stub + Object[] data=new Object[data2.length+data2.length/2]; + System.arraycopy(data2,0,data,0,top1+1); + System.arraycopy(data2,top2,data,top2+data2.length/2,data2.length-top2+1); + this.top2=top2+data2.length/2; + this.data=data; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if (top1+1>0) { + return data[top1--]; + } + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if (top1+1>0) { + return data[top1]; + } + return null; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if (top1+1==top2) { + grow(data,top1,top2); + } + data[--top2]=o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if (top2 tokens= tokenParser.parse(expr); + Stack opStack=new Stack<>(); + Stack numStack=new Stack<>(); + for (Token token : tokens) { + if (token.isNumber()) { + numStack.push((float)(token.getIntValue())); + } + else { + while (!opStack.isEmpty()&&!token.hasHigherPriority(opStack.peek())) { + float op2=numStack.pop(); + float op1= numStack.pop(); + + char op=opStack.pop().toString().charAt(0); + numStack.add(caculate(op1,op2,op)); + + } + opStack.push(token); + } + } + + while (opStack.size()!=0) { + + float op2=numStack.pop(); + float op1= numStack.pop(); + char op=opStack.pop().toString().charAt(0); + numStack.add(caculate(op1,op2,op)); + } + return (float) numStack.pop(); + } + public float caculate(float op1,float op2,char op){ + + + float tmpResult = 0; + switch(op){ + case '+': + tmpResult = op1 + op2; + break; + case '-': + tmpResult = op1 - op2; + break; + case '*': + tmpResult = op1 * op2; + break; + case '/': + tmpResult = op1 / op2; + break; + } + return tmpResult; + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/InfixExprTest.java b/group11/996108220/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..02af48b92b --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300* 20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3 *4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3* 20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/ 2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group11/996108220/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..e53af75714 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,46 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +public class InfixToPostfix { + + public static List convert(String expr) { + TokenParser tokenParser=new TokenParser(); + List tokens=tokenParser.parse(expr); + List postfixTokens=new ArrayList<>(); + Stack opStack=new Stack<>(); + for (Token token : tokens) { + if (token.isNumber()) { + postfixTokens.add(token); + } + else { + while (!opStack.isEmpty()&&opStack.peek().hasHigherPriority(token)) { + postfixTokens.add(opStack.pop()); + } + opStack.add(token); + } + } + while (!opStack.isEmpty()) { + postfixTokens.add(opStack.pop()); + + } + return postfixTokens; + } + + public static void main(String[] args) { + List post=InfixToPostfix.convert("4*2 + 6+9*2/3 -8"); + for (Token token : post) { + if (token.isNumber()) { + System.out.println(token.getIntValue()); + } + else { + System.out.println(token.toString()); + } + } + + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/PostfixExpr.java b/group11/996108220/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..d32b346ef0 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser tokenParser =new TokenParser(); + List tokens=tokenParser.parse(expr); + Stack numStack =new Stack<>(); + for (Token token : tokens) { + if (token.isOperator()) { + float op2=(float)numStack.pop(); + float op1=(float)numStack.pop(); + char op =token.toString().charAt(0); + numStack.push(caculate(op1, op2, op)); + } + else { + numStack.push((float)token.getIntValue()); + } + } + + return numStack.pop(); + } + private float caculate(float op1,float op2,char op){ + + + float tmpResult = 0; + switch(op){ + case '+': + tmpResult = op1 + op2; + break; + case '-': + tmpResult = op1 - op2; + break; + case '*': + tmpResult = op1 * op2; + break; + case '/': + tmpResult = op1 / op2; + break; + } + return tmpResult; + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group11/996108220/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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/group11/996108220/src/com/coding/basic/stack/expr/PrefixExpr.java b/group11/996108220/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..b545cd0d64 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,55 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + TokenParser tokenParser =new TokenParser(); + List tokens=tokenParser.parse(expr); + Stack numStack =new Stack<>(); + for (int i = tokens.size()-1; i >=0; i--) { + Token token=tokens.get(i); + if (token.isOperator()) { + float op1=(float)numStack.pop(); + float op2=(float)numStack.pop(); + char op =token.toString().charAt(0); + numStack.push(caculate(op1, op2, op)); + } + else { + numStack.push((float)token.getIntValue()); + } + + } + return numStack.pop(); + + } + private float caculate(float op1,float op2,char op){ + + + float tmpResult = 0; + switch(op){ + case '+': + tmpResult = op1 + op2; + break; + case '-': + tmpResult = op1 - op2; + break; + case '*': + tmpResult = op1 * op2; + break; + case '/': + tmpResult = op1 / op2; + break; + } + return tmpResult; + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group11/996108220/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group11/996108220/src/com/coding/basic/stack/expr/Token.java b/group11/996108220/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..296e67e04a --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,51 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group11/996108220/src/com/coding/basic/stack/expr/TokenParser.java b/group11/996108220/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..29f81b457c --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class TokenParser { + + + public List parse(String expr) { + List tokens = new ArrayList<>(); + + + StringTokenizer st = new StringTokenizer(expr, "\\+|\\-|\\*|\\/|\\ ", true); + + while(st.hasMoreElements()){ + String value=st.nextToken(); + //可能有空格 + if (isOperator(value)) { + tokens.add(new Token(Token.OPERATOR, value)); + } + else if (isNumber(value)) { + tokens.add(new Token(Token.NUMBER, value)); + } + } + + return tokens; + } + + + + private boolean isOperator(String value) { + + return value.length()==1&&Token.OPERATORS.contains(value); + } + private boolean isNumber(String value) { + + return value.matches("[0-9]+"); + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/expr/TokenParserTest.java b/group11/996108220/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..4ddb3669a6 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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"); + 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/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java index 03db32ccc9..cff93f9f9b 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -1,7 +1,10 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -11,11 +14,14 @@ public BiPushCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + return this.getOffset()+":"+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + public void execute(StackFrame frame,ExecutionResult result){ + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } - - - } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java index 4c8b21ab09..d763dbfbd8 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -6,6 +6,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public abstract class ByteCodeCommand { @@ -13,6 +15,40 @@ public abstract class ByteCodeCommand { ClassFile clzFile; private int offset; + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; private static Map codeMap = new HashMap(); static{ @@ -103,18 +139,6 @@ public String getOpCode() { public abstract int getLength(); - - - - public String toString(){ - - StringBuffer buffer = new StringBuffer(); - buffer.append(this.opCode); - - return buffer.toString(); - } - public abstract String toString(ConstantPool pool); - public String getReadableCodeText(){ String txt = codeMap.get(opCode); if(txt == null){ @@ -122,4 +146,6 @@ public String getReadableCodeText(){ } return txt; } + + public abstract void execute(StackFrame frame,ExecutionResult result); } \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java index 0dd0573ae5..d1bfdeb21b 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/CommandParser.java @@ -7,40 +7,7 @@ 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) { @@ -57,51 +24,58 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { while (iter.hasNext()) { String opCode = iter.next2CharAsString(); - if (new_object.equals(opCode)) { + if (ByteCodeCommand.new_object.equals(opCode)) { NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); cmds.add(cmd); - } else if (invokespecial.equals(opCode)) { + } else if (ByteCodeCommand.invokespecial.equals(opCode)) { InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); // System.out.println( cmd.toString(clzFile.getConstPool())); cmds.add(cmd); - } else if (invokevirtual.equals(opCode)) { + } else if (ByteCodeCommand.invokevirtual.equals(opCode)) { InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); cmds.add(cmd); - } else if (getfield.equals(opCode)) { + } else if (ByteCodeCommand.getfield.equals(opCode)) { GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); cmds.add(cmd); - } else if (getstatic.equals(opCode)) { + } else if (ByteCodeCommand.getstatic.equals(opCode)) { GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); cmds.add(cmd); - } else if (putfield.equals(opCode)) { + } else if (ByteCodeCommand.putfield.equals(opCode)) { PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); cmds.add(cmd); - } else if (ldc.equals(opCode)) { + } else if (ByteCodeCommand.ldc.equals(opCode)) { LdcCmd cmd = new LdcCmd(clzFile, opCode); cmd.setOperand(iter.next2CharAsInt()); cmds.add(cmd); - } else if (bipush.equals(opCode)) { + } else if (ByteCodeCommand.bipush.equals(opCode)) { BiPushCmd cmd = new BiPushCmd(clzFile, opCode); cmd.setOperand(iter.next2CharAsInt()); cmds.add(cmd); - } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) - || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) - || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + } else if (ByteCodeCommand.dup.equals(opCode) + || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) + || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) + || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) + || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode)) { NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); cmds.add(cmd); diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java index 92fe286363..f5b6932613 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -1,7 +1,10 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -10,12 +13,22 @@ public GetFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } - - - + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + + } } \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java index 52a7550d12..26ab9c8be0 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -1,7 +1,11 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -11,9 +15,24 @@ public GetStaticFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); + } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 } - } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java index c6efbae530..01390d7b5a 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -1,7 +1,11 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -11,11 +15,27 @@ public InvokeSpecialCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } - - } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java index a17c51a81d..80071ef1c5 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -1,7 +1,12 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -10,12 +15,70 @@ public InvokeVirtualCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } - + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java index 00f9a5a699..5d1985868a 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -12,9 +16,9 @@ public LdcCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + ConstantInfo info = getConstantInfo(this.getOperand()); String value = "TBD"; if(info instanceof StringInfo){ @@ -25,5 +29,22 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } - + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java index a43c8bd964..f675956919 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -1,7 +1,11 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -10,10 +14,22 @@ public NewObjectCmd(ClassFile clzFile, String opCode){ } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsClassInfo(pool); + return super.getOperandAsClassInfo(); } - - + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + } } diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java index 461bb4e2a5..d5c7b87481 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -1,7 +1,10 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -10,10 +13,129 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } public int getLength(){ diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java index 00b29e1fbc..cd93fba1d1 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -1,7 +1,12 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; -import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -10,10 +15,29 @@ public PutFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } + -} +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java index 6cb42d2a83..6f4250f920 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -2,7 +2,6 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ClassInfo; -import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.MethodRefInfo; @@ -38,21 +37,22 @@ public int getIndex(){ return index; } - protected String getOperandAsClassInfo(ConstantPool pool){ + protected String getOperandAsClassInfo(){ int index = getIndex(); String codeTxt = getReadableCodeText(); - ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + ClassInfo info = (ClassInfo)getConstantInfo(index); return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); } - protected String getOperandAsMethod(ConstantPool pool){ + protected String getOperandAsMethod(){ 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){ + protected String getOperandAsField(){ int index = getIndex(); String codeTxt = getReadableCodeText(); @@ -62,4 +62,4 @@ protected String getOperandAsField(ConstantPool pool){ public int getLength(){ return 3; } -} +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutionResult.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..368ab4ea31 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,52 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutorEngine.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..e22bb77838 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,68 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.method.Method; +import com.coding.basic.stack.Stack; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + //为main函数创建一个栈帧 + StackFrame mainFrame = StackFrame.create(mainMethod); + //main函数帧压栈 + stack.push(mainFrame); + + while(!stack.isEmpty()){ + + StackFrame frame = stack.peek(); + ExecutionResult result = frame.execute(); + + //判断执行结果是否暂停或者有新的函数帧生成 + if(result.isPauseAndRunNewFrame()){ + + Method method = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(method); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + stack.push(nextFrame); + }else{ + stack.pop(); + } + } + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + Method nextMethod = nextFrame.getMethod(); + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + int paramNum = paramList.size() + 1; + List values = new ArrayList(); + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + nextFrame.setLocalVariableTable(params); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/Heap.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..7df6548625 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/JavaObject.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..e48667b9d2 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} \ No newline at end of file diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MethodArea.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..87b9d425f8 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,94 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.exception.NotAClassFileException; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + ClassFile clzFile = null; + try { + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + + } catch (NotAClassFileException e) { + e.printStackTrace(); + } + return clzFile; + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MiniJVM.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..9d255d7ea6 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.engine; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.exception.NotAClassFileException; +import com.coderising.jvm.loader.ClassFileLoader; + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException, NotAClassFileException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCmds(); + for(int i=0;iindex){ + + ExecutionResult result = new ExecutionResult(); + //缺省值是执行下一条命令 + result.setNextAction(ExecutionResult.RUN_NEXT_CMD); + + System.out.println(cmds[index].toString()); + + cmds[index].execute(this,result); + + if(result.isRunNextCmd()){ + index++; + } + else if(result.isExitCurrentFrame()){ + return result; + } + else if(result.isPauseAndRunNewFrame()){ + index++; + return result; + } + else if(result.isJump()){ + int offset = result.getNextCmdOffset(); + this.index = getNextCommandIndex(offset); + } else{ + index++; + } + + } + + //当前StackFrmae的指令全部执行完毕,可以退出了 + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + } + + + + + public void setLocalVariableTable(List values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java index 245ccdc558..05eb77e802 100644 --- a/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java +++ b/group12/2258659044/zj-2017/src/com/coderising/jvm/method/Method.java @@ -7,6 +7,7 @@ import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.cmd.ByteCodeCommand; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; public class Method { @@ -47,6 +48,66 @@ public ByteCodeCommand[] getCmds() { return null; } + private String getParamAndReturnType(){ + UTF8Info nameAndTypeInfo = (UTF8Info)pool.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } + public int getAccessFlag() { return accessFlag; } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTree.java b/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTree.java index 3fe9965b5e..53c4e92013 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTree.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/BinaryTree.java @@ -2,24 +2,23 @@ import com.coding.basic.array.ArrayList; -public class BinaryTree { +public class BinaryTree> { //根节点 - private BinaryTreeNode root; - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public > BinaryTreeNode insert(T o){ + private BinaryTreeNode root; + + public BinaryTreeNode insert(T o){ - BinaryTreeNode treeNode = new BinaryTreeNode(); + BinaryTreeNode treeNode = new BinaryTreeNode(); treeNode.setData(o); if(root == null){ root = treeNode; }else{ - BinaryTreeNode currentNode = root; - BinaryTreeNode parent; + BinaryTreeNode currentNode = root; + BinaryTreeNode parent; while(true){ parent = currentNode; - if(((Comparable)currentNode.getData()).compareTo(o)>0){//向左放 + if((currentNode.getData()).compareTo(o)>0){//向左放 currentNode = currentNode.getLeft(); if(currentNode == null){ parent.setLeft(treeNode); @@ -44,12 +43,12 @@ public > BinaryTreeNode insert(T o){ * @param node * @return */ - public List traversalBefore(BinaryTreeNode node){ + public List traversalBefore(BinaryTreeNode node){ //所有数据集合 - List datas = new ArrayList<>(); + List datas = new ArrayList<>(); return traversal(node,datas); } - private List traversal(BinaryTreeNode node,List datas){ + private List traversal(BinaryTreeNode node,List datas){ if(node !=null){ datas.add(node.getData()); @@ -59,8 +58,22 @@ private List traversal(BinaryTreeNode node,List datas return datas; } - public BinaryTreeNode getRoot() { + public BinaryTreeNode getRoot() { return root; } + + /** + * 获取比obj大的最小值 + * @param obj + * @return + */ + public T getLeastBigger (T obj){ + BinaryTreeNode left = root; + while(left.getLeft()!=null){ + left = left.getLeft(); + } + return left.getData(); + } + } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java b/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java deleted file mode 100644 index 169fc0dcb9..0000000000 --- a/group12/2258659044/zj-2017/src/com/coding/basic/Queue.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.linklist.LinkedList; - -public class Queue { - - private LinkedList element = new LinkedList(); - - public void enQueue(E o){ - - element.add(o); - } - - public E deQueue(){ - - return element.removeFirst(); - } - - public boolean isEmpty(){ - - return element.size()==0; - } - - public int size(){ - - return element.size(); - } -} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java index 73f3b9649e..0333ac61b8 100644 --- a/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java +++ b/group12/2258659044/zj-2017/src/com/coding/basic/array/ArrayList.java @@ -64,6 +64,16 @@ public Object[] toArray(){ return objArr; } + @Override + public String toString() { + + StringBuilder str = new StringBuilder(); + str.append("["); + for (int i = 0; i < size; i++) { + str.append(elementData[i].toString()+","); + } + return str.toString().substring(0, str.length()-1)+"]"; + } /** * 扩容,扩容因子为10 */ diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/queue/CircleQueue.java b/group12/2258659044/zj-2017/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..260f1735e7 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,80 @@ +package com.coding.basic.queue; + +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + + return front == rear; + } + + public int size() { + + return rear-front>0?(rear-front):(rear-front+DEFAULT_SIZE); + } + + + + public void enQueue(E data) { + + rangeCheck(rear); + elementData[rear] = data; + rear = (rear+1)%DEFAULT_SIZE; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + + if(isEmpty()){ + return null; + } + Object obj = elementData[front]; + front = (front+1)%DEFAULT_SIZE; + return (E) obj; + } + + /** + * 数组最后一个空间不存放数据
+ * 用来区分队列的空或者满 + * @param rear + */ + private void rangeCheck(int rear) { + + if ((rear+1)%DEFAULT_SIZE == front) { + throw new IndexOutOfBoundsException("队列数据已满!"); + } + } + + @Override + public String toString() { + + if(isEmpty()){ + return "[]"; + } + + Object[] temp = new Object[DEFAULT_SIZE]; + System.arraycopy(elementData, 0, temp, 0, DEFAULT_SIZE); + + int frontTemp = front; + int rearTemp = rear; + + StringBuilder str = new StringBuilder(); + str.append("["); + while(!isEmpty()){ + str.append(this.deQueue().toString()+","); + } + + front = frontTemp; + rear = rearTemp; + return str.toString().substring(0, str.length()-1)+"]"; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/queue/Josephus.java b/group12/2258659044/zj-2017/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..22c8214373 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,33 @@ +package com.coding.basic.queue; + +import com.coding.basic.List; +import com.coding.basic.array.ArrayList; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + + CircleQueue queue = new CircleQueue<>(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + + List ls = new ArrayList<>(); + while(!queue.isEmpty()){ + int position = (m-1)%queue.size(); + for (int i = 0; i < position; i++) { + queue.enQueue(queue.deQueue()); + } + ls.add(queue.deQueue()); + } + return ls; + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/queue/Queue.java b/group12/2258659044/zj-2017/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..f7761a384b --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,28 @@ +package com.coding.basic.queue; + +import com.coding.basic.linklist.LinkedList; + +public class Queue { + + private LinkedList element = new LinkedList(); + + public void enQueue(E o){ + + element.add(o); + } + + public E deQueue(){ + + return element.removeFirst(); + } + + public boolean isEmpty(){ + + return element.size()==0; + } + + public int size(){ + + return element.size(); + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group12/2258659044/zj-2017/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c844a2e1ca --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,50 @@ +package com.coding.basic.queue; + +import com.coding.basic.stack.Stack; + +public class QueueWithTwoStacks { + + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return (stack1.isEmpty()&&stack2.isEmpty()); + } + + + + public int size() { + return (stack1.size()+stack2.size()); + } + + public void enQueue(E item) { + + if(item!=null){ + + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + stack1.push(item); + } + } + + public E deQueue() { + + if(isEmpty()){ + return null; + } + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + return stack2.pop(); + } + + + + } diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/QuickMinStack.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..56dee25531 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack; + + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author zj + * @param + * + */ +public class QuickMinStack> { + + + private Stack dataStack = new Stack(); + + private Stack minStack = new Stack(); + + public void push(T item){ + + if(minStack.isEmpty()||item.compareTo(minStack.peek())<0){ + minStack.push(item); + }else{ + minStack.push(minStack.peek()); + } + + dataStack.push(item); + } + + public T pop(){ + + minStack.pop(); + return dataStack.pop(); + } + + public T findMin(){ + + return minStack.peek(); + } + +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackWithTwoQueues.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..8a76830563 --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,38 @@ +package com.coding.basic.stack; + +import com.coding.basic.queue.Queue; + +/** + * + * @author zj + * + * @param + */ +public class StackWithTwoQueues { + + + private final Queue q1 = new Queue(); + + private final Queue q2 = new Queue(); + + public void push(E data) { + + q1.enQueue(data); + } + + public E pop() { + + while(q1.size()>1){ + q2.enQueue(q1.deQueue()); + } + return q1.deQueue(); + } + + public int size(){ + return q1.size()+q2.size(); + } + + public boolean isEmpty(){ + return q1.size()+q2.size()==0; + } +} diff --git a/group12/2258659044/zj-2017/src/com/coding/basic/stack/TwoStackInOneArray.java b/group12/2258659044/zj-2017/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..9c00bfbbbb --- /dev/null +++ b/group12/2258659044/zj-2017/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,127 @@ +package com.coding.basic.stack; + +import java.util.EmptyStackException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @@author zj + * + */ +public class TwoStackInOneArray { + + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2=data.length-1; + + /*扩容因子*/ + private static final int FACTOR = 10; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + if(index1-1==index2){ + grow(); + } + data[index1++] = o; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + + rangeCheck(index1); + + return data[--index1]; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + + rangeCheck(index1); + + int popIndex = index1-1; + + return data[popIndex]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + if(index2+1==index1){ + grow(); + } + data[index2--] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + + rangeCheck(index2); + + return data[++index2]; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + + rangeCheck(index2); + + int popIndex = index2+1; + + return data[popIndex]; + } + + /** + * 扩容 + */ + private void grow(){ + + //原来数组长度 + int origLen = data.length; + + //扩容后现在的长度 + int curLen = origLen+FACTOR; + + //栈2中数据个数 + + int num = origLen - index2-1; + + //新建临时数组 + Object[] temp = new Object[curLen]; + + //将栈1的内容拷贝到新数组中 + System.arraycopy(data, 0, temp, 0, index1); + + //将栈2的内容拷贝到新数组中 + System.arraycopy(data, index1, temp,curLen-num , num); + + //更新index2与数组 + this.index2 = curLen-num-1; + this.data = temp; + } + + private void rangeCheck(int index){ + + if(index==0||index == data.length-1){ + throw new EmptyStackException(); + } + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java index 2a18bee6d7..d6c9284201 100644 --- a/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coderising/jvm/ClassFileloaderTest.java @@ -28,8 +28,8 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "test/com/coderising/jvm/EmployeeV1"; - static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; - //static String path1 = "E:\\githubRepository\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + //static String path1 = "F:\\githubRes\\coding2017\\group12\\2258659044\\zj-2017\\bin"; + static String path1 = "E:\\githubRepository\\coding2017\\group12\\2258659044\\zj-2017\\bin"; static String path2 = "C:\temp"; diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/BinaryTreeTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/BinaryTreeTest.java index 98b79b3b6b..edc13f5ba6 100644 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/BinaryTreeTest.java +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/BinaryTreeTest.java @@ -10,20 +10,21 @@ public class BinaryTreeTest { - BinaryTree tree ; + BinaryTree tree ; @Before public void setup() { - tree = new BinaryTree(); + tree = new BinaryTree<>(); Assert.assertEquals(tree.getRoot(), null); tree.insert(5); tree.insert(2); tree.insert(7); tree.insert(1); tree.insert(6); + } - @SuppressWarnings("unchecked") + @Test public void insert(){ @@ -36,7 +37,7 @@ public void insert(){ Assert.assertEquals((int)node2.getParent().getLeft().getData(), 6); } - @Test + //@Test public void traversal(){ insert(); diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java deleted file mode 100644 index b12d23cdbd..0000000000 --- a/group12/2258659044/zj-2017/src/test/com/coding/basic/QueueTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package test.com.coding.basic; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.coding.basic.Queue; - -public class QueueTest { - - Queue qe ; - - @Before - public void setup() { - qe = new Queue<>(); - for (int i = 0; i < 10; i++) { - qe.enQueue(i); - } - } - - @Test - public void enQueue(){ - - Assert.assertEquals(qe.size(), 10); - qe.enQueue("abcd"); - Assert.assertEquals(qe.size(), 11); - } - - @Test//(expected = IndexOutOfBoundsException.class) - public void deQueue(){ - - Assert.assertEquals(qe.size(), 10); - for (int i = 0; i < 10; i++) { - Assert.assertEquals(qe.deQueue(), i); - } - Assert.assertEquals(qe.size(), 0); - //打开下列语句与期望异常测试 - //qe.deQueue(); - } - - public void isEmpty(){ - - Assert.assertEquals(qe.isEmpty(),false); - for (int i = 0; i < 10; i++) { - qe.deQueue(); - } - Assert.assertEquals(qe.isEmpty(),true); - Queue qe1 = new Queue<>(); - Assert.assertEquals(qe1.isEmpty(), true); - } - - public void size(){ - - Assert.assertEquals(qe.size(),10); - qe.enQueue("lk"); - qe.enQueue('h'); - Assert.assertEquals(qe.size(),12); - for (int i = 0; i < 12; i++) { - qe.deQueue(); - } - Assert.assertEquals(qe.size(),0); - Queue qe1 = new Queue<>(); - Assert.assertEquals(qe1.size(), 0); - } -} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/CircleQueueTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..1da8ca1957 --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,87 @@ +package test.com.coding.basic.queue; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.queue.CircleQueue; + +public class CircleQueueTest { + + CircleQueue qe;; + + @Before + public void setup() { + qe = new CircleQueue<>(); + } + + @Test + public void testIsEmpty() { + + Assert.assertEquals(true, qe.isEmpty()); + } + + @Test + public void testSize() { + + for (int i = 0; i < 9; i++) { + qe.enQueue(i); + } + Assert.assertEquals(9, qe.size()); + } + + @Test//(expected = IndexOutOfBoundsException.class) + public void testEnQueue() { + + for (int i = 0; i < 7; i++) { + qe.enQueue(i); + } + Assert.assertEquals("[0,1,2,3,4,5,6]", qe.toString()); + + //打开下面测试一场 + /*for (int i = 7; i < 10; i++) { + qe.enQueue(i); + }*/ + } + + @Test + public void testDeQueue() { + + for (int i = 0; i < 9; i++) { + qe.enQueue(i); + } + Assert.assertEquals(9,qe.size()); + + Assert.assertEquals(0,qe.deQueue()); + Assert.assertEquals("[1,2,3,4,5,6,7,8]", qe.toString()); + Assert.assertEquals(8,qe.size()); + + Assert.assertEquals(1,qe.deQueue()); + Assert.assertEquals("[2,3,4,5,6,7,8]", qe.toString()); + Assert.assertEquals(7,qe.size()); + + qe.enQueue(1); + Assert.assertEquals("[2,3,4,5,6,7,8,1]", qe.toString()); + Assert.assertEquals(8,qe.size()); + + qe.enQueue(0); + Assert.assertEquals("[2,3,4,5,6,7,8,1,0]", qe.toString()); + Assert.assertEquals(9,qe.size()); + + for (int i = 0; i < 9; i++) { + qe.deQueue(); + qe.enQueue(i); + } + Assert.assertEquals(9,qe.size()); + + qe.deQueue();qe.deQueue(); + Assert.assertEquals(7,qe.size()); + + qe.enQueue(4); + Assert.assertEquals(8,qe.size()); + + qe.enQueue(4); + Assert.assertEquals(9,qe.size()); + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/JosephusTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..44865ae373 --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package test.com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.queue.Josephus; + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1,3,5,0,4,2,6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueTest.java new file mode 100644 index 0000000000..ef471b8c4e --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueTest.java @@ -0,0 +1,64 @@ +package test.com.coding.basic.queue; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.queue.Queue; + +public class QueueTest { + + Queue qe ; + + @Before + public void setup() { + qe = new Queue<>(); + for (int i = 0; i < 10; i++) { + qe.enQueue(i); + } + } + + @Test + public void enQueue(){ + + Assert.assertEquals(qe.size(), 10); + qe.enQueue("abcd"); + Assert.assertEquals(qe.size(), 11); + } + + @Test//(expected = IndexOutOfBoundsException.class) + public void deQueue(){ + + Assert.assertEquals(qe.size(), 10); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(qe.deQueue(), i); + } + Assert.assertEquals(qe.size(), 0); + //打开下列语句与期望异常测试 + //qe.deQueue(); + } + + public void isEmpty(){ + + Assert.assertEquals(qe.isEmpty(),false); + for (int i = 0; i < 10; i++) { + qe.deQueue(); + } + Assert.assertEquals(qe.isEmpty(),true); + Queue qe1 = new Queue<>(); + Assert.assertEquals(qe1.isEmpty(), true); + } + + public void size(){ + + Assert.assertEquals(qe.size(),10); + qe.enQueue("lk"); + qe.enQueue('h'); + Assert.assertEquals(qe.size(),12); + for (int i = 0; i < 12; i++) { + qe.deQueue(); + } + Assert.assertEquals(qe.size(),0); + Queue qe1 = new Queue<>(); + Assert.assertEquals(qe1.size(), 0); + } +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueWithTwoStacksTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..07e277912f --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,72 @@ +package test.com.coding.basic.queue; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.queue.QueueWithTwoStacks; + +public class QueueWithTwoStacksTest { + + private QueueWithTwoStacks queue; + + @Before + public void setUp() throws Exception { + queue = new QueueWithTwoStacks<>(); + } + + @Test + public void testIsEmpty() { + + Assert.assertEquals(true, queue.isEmpty()); + } + + @Test + public void testSize() { + + Assert.assertEquals(0, queue.size()); + + queue.enQueue("zj"); + Assert.assertEquals(1, queue.size()); + + for (int i = 0; i < 10; i++) { + queue.enQueue(i); + } + Assert.assertEquals(11, queue.size()); + + for (int i = 0; i < 5; i++) { + queue.deQueue(); + } + Assert.assertEquals(6, queue.size()); + } + + @Test + public void testEnQueue() { + + for (int i = 0; i < 10; i++) { + queue.enQueue(i); + } + + for (int i = 0; i < 10; i++) { + Assert.assertEquals(i, queue.deQueue()); + } + } + + @Test + public void testDeQueue() { + + Assert.assertEquals(null, queue.deQueue()); + + for (int i = 0; i < 10; i++) { + queue.enQueue(i); + } + + for (int i = 0; i < 5; i++) { + queue.deQueue(); + } + Assert.assertEquals(5, queue.size()); + Assert.assertEquals(false, queue.isEmpty()); + + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/QuickMinStackTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..8e48a74f20 --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/QuickMinStackTest.java @@ -0,0 +1,60 @@ +package test.com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.QuickMinStack; + +public class QuickMinStackTest { + + QuickMinStack stack ; + @Before + public void setUp() throws Exception { + + stack = new QuickMinStack<>(); + } + + @Test + public void testPush() { + + for (int i = 0; i < 15; i++) { + stack.push(i); + } + Assert.assertEquals(14, (int)stack.pop()); + } + + @Test + public void testPop() { + + for (int i = 0; i < 10; i++) { + stack.push(i); + } + for (int i = 9; i >= 0; i--) { + Assert.assertEquals(i, (int)stack.pop()); + } + } + + @Test + public void testFindMin() { + + for (int i = 5; i < 15; i++) { + stack.push(i); + } + Assert.assertEquals(5, (int)stack.findMin()); + + stack.push(5); + stack.push(3); + stack.push(4); + + stack.pop(); + Assert.assertEquals(3, (int)stack.findMin()); + + stack.pop(); + Assert.assertEquals(5, (int)stack.findMin()); + + stack.pop(); + Assert.assertEquals(5, (int)stack.findMin()); + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackWithTwoQueuesTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..8ff6dc83de --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,72 @@ +package test.com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.StackWithTwoQueues; + +public class StackWithTwoQueuesTest { + + StackWithTwoQueues stack; + + @Before + public void setUp() throws Exception { + + stack = new StackWithTwoQueues<>(); + } + + @Test + public void testPush() { + + stack.push(123); + Assert.assertEquals(1, stack.size()); + + stack.push("zj"); + stack.push('Y'); + Assert.assertEquals(3, stack.size()); + + } + + @Test + public void testPop() { + + stack.push(123); + stack.push("zj"); + Assert.assertEquals("zj", stack.pop()); + Assert.assertEquals(1, stack.size()); + + stack.push('H'); + stack.push('Y'); + Assert.assertEquals('Y', stack.pop()); + Assert.assertEquals(2, stack.size()); + + } + + @Test + public void testSize() { + + Assert.assertEquals(0, stack.size()); + + stack.push("zj"); + stack.push('H'); + stack.push('y'); + Assert.assertEquals(3, stack.size()); + + stack.pop(); + Assert.assertEquals(2, stack.size()); + } + + @Test + public void testIsEmpty() { + + Assert.assertEquals(true, stack.isEmpty()); + + stack.push("zj"); + stack.push('H'); + stack.push('y'); + + Assert.assertEquals(false, stack.isEmpty()); + } + +} diff --git a/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/TwoStackInOneArrayTest.java b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..377dcf8286 --- /dev/null +++ b/group12/2258659044/zj-2017/src/test/com/coding/basic/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,130 @@ +package test.com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coding.basic.stack.TwoStackInOneArray; + +public class TwoStackInOneArrayTest { + + + TwoStackInOneArray stack; + + @Before + public void setUp() throws Exception { + + stack = new TwoStackInOneArray(); + } + + //@Test(expected = EmptyStackException.class) + public void testPush1() { + + stack.push1("zj"); + Assert.assertEquals("zj", stack.peek1()); + + stack.push1("hy"); + Assert.assertEquals("hy", stack.peek1()); + + stack.pop1(); + stack.pop1(); + + stack.peek1(); + } + + //@Test(expected = EmptyStackException.class) + public void testPop1() { + + stack.push1("zj"); + Assert.assertEquals("zj", stack.pop1()); + stack.pop1(); + + } + + //@Test + public void testPeek1() { + + stack.push1("zj"); + Assert.assertEquals("zj", stack.peek1()); + + stack.push1("hh"); + stack.push1("hy"); + Assert.assertEquals("hy", stack.peek1()); + + } + + //@Test(expected = EmptyStackException.class) + public void testPush2() { + + stack.push2("zj"); + Assert.assertEquals("zj", stack.peek2()); + + stack.push2("hy"); + Assert.assertEquals("hy", stack.peek2()); + + stack.pop2(); + stack.pop2(); + + stack.peek2(); + } + + //@Test(expected = EmptyStackException.class) + public void testPop2() { + + stack.push2("zj"); + Assert.assertEquals("zj", stack.pop2()); + stack.pop2(); + } + + //@Test + public void testPeek2() { + + stack.push2("zj"); + Assert.assertEquals("zj", stack.peek2()); + + stack.push2("hh"); + stack.push2("hy"); + Assert.assertEquals("hy", stack.peek2()); + } + + @Test + public void testGrow() throws Exception{ + + for (int i = 0; i < 5; i++) { + stack.push1(i); + } + + for (int i = 0; i < 5; i++) { + stack.push2(i); + } + Assert.assertEquals(4, stack.peek1()); + Assert.assertEquals(4, stack.peek2()); + + //重置栈 + setUp(); + for (int i = 0; i < 11; i++) { + stack.push1(i); + } + Assert.assertEquals(10, stack.peek1()); + + setUp(); + for (int i = 0; i < 11; i++) { + stack.push2(i); + } + Assert.assertEquals(10, stack.peek2()); + + setUp(); + for (int i = 0; i < 5; i++) { + stack.push1(i); + } + for (int i = 0; i < 10; i++) { + stack.push2(i); + } + Assert.assertEquals(4, stack.peek1()); + Assert.assertEquals(9, stack.peek2()); + stack.pop1(); + stack.pop2(); + Assert.assertEquals(3, stack.peek1()); + Assert.assertEquals(8, stack.peek2()); + } +} diff --git a/group12/382266293/coding/basic/queue/CircleQueue.java b/group12/382266293/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..65d6f77c65 --- /dev/null +++ b/group12/382266293/coding/basic/queue/CircleQueue.java @@ -0,0 +1,71 @@ +package queue; + +/** + * 用数组实现循环队列 + * + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 11; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + return size() == 0; + + } + + public int size() { + return getArrIndex(front - rear); + } + + private int getArrIndex(int i) { + return i % DEFAULT_SIZE; + } + + public void enQueue(E data) { + checkCapacity(); + elementData[getArrIndex(front)] = data; + front++; + } + + private void checkCapacity() { + if (getArrIndex(front - rear + 1) == 0) { + throw new RuntimeException("Queue is full"); + } + } + + public E deQueue() { + if (size() == 0) { + return null; + } + Object o = elementData[getArrIndex(rear)]; + rear++; + return (E) o; + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < size(); i++) { + sb.append(elementData[getArrIndex(rear + i)]); + if (i != size() - 1) { + sb.append(","); + } + } + sb.append("]"); + return sb.toString(); + } + +} diff --git a/group12/382266293/coding/basic/queue/CircleQueueTest.java b/group12/382266293/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..f74954c6d8 --- /dev/null +++ b/group12/382266293/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,64 @@ +package queue; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Test; + +public class CircleQueueTest { + + CircleQueue cq = new CircleQueue(); + + @After + public void tearDown() throws Exception { + cq = null; + } + + @Test + public void testIsEmpty() { + assertEquals(cq.size(),0); + } + + @Test + public void testSize() { + for (int i = 0; i < 10; i++) { + cq.enQueue(i); + } + + cq.deQueue(); + cq.deQueue(); + System.out.println(cq); + cq.enQueue(10); + cq.enQueue(11); + assertEquals(10,cq.size()); + System.out.println(cq); + + int i = 2; + while(cq.size() > 0) { + assertEquals(i++, cq.deQueue()); + } + } + + @Test + public void testEnQueue() { + for (int i = 0; i < 5; i++) { + cq.enQueue(i); + } + assertEquals(5,cq.size()); + } + + @Test + public void testDeQueue() { + for (int i = 0; i < 10; i++) { + cq.enQueue(i); + } + + int i = 0; + while(cq.size() > 0) { + assertEquals(i++, cq.deQueue()); + } + + + } + +} diff --git a/group12/382266293/coding/basic/queue/Josephus.java b/group12/382266293/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..4eef15ab13 --- /dev/null +++ b/group12/382266293/coding/basic/queue/Josephus.java @@ -0,0 +1,32 @@ +package queue; + +import java.util.ArrayList; +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){ + + QueueWithTwoStacks cq = new QueueWithTwoStacks(); + for (int i = 0; i < n; i++) { + cq.enQueue(i); + } + List result = new ArrayList<>(); + while (cq.size() > 0) { + for (int i = 0; i < m-1; i++) { + cq.enQueue(cq.deQueue()); + } + result.add(cq.deQueue()); + } + + return result; + } + +} diff --git a/group12/382266293/coding/basic/queue/JosephusTest.java b/group12/382266293/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..ac258383db --- /dev/null +++ b/group12/382266293/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group12/382266293/coding/basic/queue/Queue.java b/group12/382266293/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..5b720fc5e3 --- /dev/null +++ b/group12/382266293/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group12/382266293/coding/basic/queue/QueueWithTwoStacks.java b/group12/382266293/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..03d243d8c0 --- /dev/null +++ b/group12/382266293/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,58 @@ +package 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 size() == 0; + } + + public int size() { + return stack2.size() + stack1.size(); + } + + public void enQueue(E item) { + if (stack2.size() != 0) { + drop(stack2, stack1, stack2.size()); + } + + stack1.push(item); + } + + private void drop(Stack stack2, Stack stack1, int num) { + for (int i = 0; i < num; i++) { + stack1.push(stack2.pop()); + } + } + + public E deQueue() { + if (size() <= 0) { + return null; + } + + if (stack1.size() != 0) { + drop(stack1, stack2, stack1.size() - 1); + return stack1.pop(); + } + + return stack2.pop(); + + } + +} diff --git a/group12/382266293/coding/basic/queue/Stack.java b/group12/382266293/coding/basic/queue/Stack.java new file mode 100644 index 0000000000..4a6884ef37 --- /dev/null +++ b/group12/382266293/coding/basic/queue/Stack.java @@ -0,0 +1,106 @@ +package queue; + +import java.util.EmptyStackException; +import java.util.NoSuchElementException; + +import collection.AbstractList; +import collection.Iterator; +import collection.concrete.ArrayList; + +public class Stack extends AbstractList { + + private ArrayList myList; + + public Stack() { + this.myList = new ArrayList(); + } + + public void push(E e) { + myList.addLast(e); + } + + public E pop() { + checkEmpty(); + return myList.removeLast(); + } + + private void checkEmpty() { + if (0 == size()) + throw new EmptyStackException(); + } + + public E peek() { + checkEmpty(); + return myList.getLast(); + } + + @Override + public int size() { + return myList.size(); + } + + @Override + public void add(E e) { + push(e); + } + + @Override + public E get(int index) { + checkEmpty(); + return myList.get(size() - index - 1); + } + + @Override + protected Iterator iterator() { + return new StackIterator(myList); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((myList == null) ? 0 : myList.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Stack other = (Stack) obj; + if (myList == null) { + if (other.myList != null) + return false; + } else if (!myList.equals(other.myList)) + return false; + return true; + } + + private class StackIterator implements Iterator { + + private ArrayList myArrayList; + private int pos; + + public StackIterator(ArrayList myList) { + myArrayList = myList; + pos = 0; + } + + @Override + public boolean hasNext() { + return pos < size(); + } + + @Override + public E next() { + if (hasNext()) + return (E) get(pos); + throw new NoSuchElementException(); + } + } + +} diff --git a/group12/382266293/coding/basic/stack/QuickMinStack.java b/group12/382266293/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..f474104ba8 --- /dev/null +++ b/group12/382266293/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,74 @@ +package stack; + +import java.util.NoSuchElementException; +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + Stack s1 = new Stack<>(); + private Stack min = new Stack<>(); + + + public void push(int data){ + s1.push(data); + if (size() == 0) { + + min.push(data); + } else { + Stack temp = new Stack(); + while(!min.isEmpty() && data >min.peek()) { + temp.push(min.pop()); + } + min.push(data); + while(!temp.isEmpty()) { + min.push(temp.pop()); + } + } + } + + @Override + public String toString() { + return "QuickMinStack [s1=" + s1 + ", min=" + min + "]"; + } + + public int pop(){ + + checkEmpty(); + int result = s1.pop(); + Stack temp = new Stack(); + + while(!min.isEmpty() && min.peek() != result) { + temp.push(min.pop()); + } + + min.pop(); + + while(!temp.isEmpty()) { + min.push(temp.pop()); + } + + return result; + } + + private void checkEmpty() { + if (size() <= 0) { + throw new NoSuchElementException("stack is empty"); + } + + } + + public int size() { + return s1.size(); + } + + public int findMin(){ + return min.peek(); + } + +} diff --git a/group12/382266293/coding/basic/stack/QuickMinStackTest.java b/group12/382266293/coding/basic/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..23fa14c947 --- /dev/null +++ b/group12/382266293/coding/basic/stack/QuickMinStackTest.java @@ -0,0 +1,68 @@ +package stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class QuickMinStackTest { + + QuickMinStack qs; + + @Before + public void setUp() throws Exception { + qs = new QuickMinStack(); + } + + @After + public void tearDown() throws Exception { + qs = null; + } + + @Test + public void testPush() { + qs.push(1); + qs.push(2); + } + + @Test + public void testPop() { + qs.push(1); + qs.push(2); + assertEquals(2,qs.pop()); + assertEquals(1,qs.pop()); + } + + @Test + public void testSize() { + assertEquals(0,qs.size()); + qs.push(1); + qs.push(2); + assertEquals(2,qs.size()); + } + + @Test + public void testFindMin() { + for (int i = 0; i < 8; i++) { + qs.push(i); + } + + qs.push(-19); + qs.push(100); + + assertEquals(-19,qs.findMin()); + qs.pop(); + qs.pop(); + assertEquals(0,qs.findMin()); + qs.push(-1); + qs.push(-1); + assertEquals(-1,qs.findMin()); + qs.pop(); + assertEquals(-1,qs.findMin()); + qs.pop(); + assertEquals(0,qs.findMin()); + + } + +} diff --git a/group12/382266293/coding/basic/stack/StackWithTwoQueues.java b/group12/382266293/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..05ee36d22a --- /dev/null +++ b/group12/382266293/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,42 @@ +package stack; + +import queue.Queue; + +public class StackWithTwoQueues { + + private Queue q1 = new Queue() ; + private Queue q2 = new Queue() ; + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return q1.size() + q2.size(); + } + + public void push(int data) { + q1.enQueue(data); + } + + public int pop() { + if (size() <= 0) { + throw new RuntimeException("stack is empty"); + } + + if (q1.size() >= 1) { + while (q1.size() > 1) { + q2.enQueue(q1.deQueue()); + } + return q1.deQueue(); + } else { + while (q2.size() > 1) { + q1.enQueue(q2.deQueue()); + } + return q2.deQueue(); + } + + } + + +} diff --git a/group12/382266293/coding/basic/stack/StackWithTwoQueuesTest.java b/group12/382266293/coding/basic/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..49258a7a47 --- /dev/null +++ b/group12/382266293/coding/basic/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,51 @@ +package stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class StackWithTwoQueuesTest { + + StackWithTwoQueues sq; + @Before + public void setUp() throws Exception { + sq = new StackWithTwoQueues<>(); + } + + @After + public void tearDown() throws Exception { + sq = null; + } + + @Test + public void testIsEmpty() { + assertEquals(true,sq.isEmpty()); + } + + @Test + public void testPush() { + sq.push(1); + assertEquals(1,sq.size()); + sq.push(2); + assertEquals(2,sq.size()); + sq.pop(); + assertEquals(1,sq.size()); + sq.pop(); + assertEquals(0,sq.size()); + } + + @Test + public void testPop() { + sq.push(1); + sq.push(2); + sq.push(-3); + assertEquals(-3,sq.pop()); + sq.push(4); + assertEquals(4,sq.pop()); + assertEquals(2,sq.pop()); + assertEquals(1,sq.pop()); + } + +} diff --git a/group12/382266293/coding/basic/stack/TwoStackInOneArray.java b/group12/382266293/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..87ceff35c7 --- /dev/null +++ b/group12/382266293/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,116 @@ +package stack; + +import java.util.Arrays; +import java.util.NoSuchElementException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private int size1 = 0; + private int size2 = 0; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + checkCapacity(); + data[size1++] = o; + } + + @Override + public String toString() { + return "TwoStackInOneArray [data=" + Arrays.toString(data) + "]"; + } + + public int size1() { + return size1; + } + + public int size2() { + return size2; + } + + private void checkCapacity() { + if (size() + 1 >= data.length) { + grow(); + } + } + private int size() { + return size1 + size2; + } + + private void grow() { + int newCapacity = size() * 2; + Object[] target = new Object[newCapacity]; + System.arraycopy(data, 0, target, 0, size1); + System.arraycopy(data, data.length - size2, target, target.length - size2, size2); + data = target; + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + + checkEmpty(size1); + Object o = data[size1-1]; + data[size1-1] = null; + size1--; + return o; + + } + + private void checkEmpty(int size) { + if (size <= 0) { + throw new NoSuchElementException("stack is empty"); + } + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + + checkEmpty(size1); + return data[size1-1]; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + checkCapacity(); + data[data.length - size2 - 1] = o; + size2++; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + checkEmpty(size2); + Object o = data[data.length - size2]; + data[data.length - size2] = null; + size2--; + return o; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + checkEmpty(size2); + return data[data.length - size2]; + } + +} diff --git a/group12/382266293/coding/basic/stack/TwoStackInOneArrayTest.java b/group12/382266293/coding/basic/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..6ce6125b46 --- /dev/null +++ b/group12/382266293/coding/basic/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,142 @@ +package stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class TwoStackInOneArrayTest { + + TwoStackInOneArray ts; + @Before + public void setUp() throws Exception { + ts = new TwoStackInOneArray(); + } + + @After + public void tearDown() throws Exception { + ts = null; + } + + @Test + public void testPush1() { + ts.push1(1); + ts.push1(2); + } + + @Test + public void testSize1() { + assertEquals(0,ts.size1()); + ts.push1(1); + ts.push1(2); + assertEquals(2,ts.size1()); + } + + @Test + public void testSize2() { + assertEquals(0,ts.size2()); + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.size2()); + } + + @Test + public void testSize12() { + assertEquals(0,ts.size1()); + ts.push1(1); + ts.push1(2); + assertEquals(2,ts.size1()); + assertEquals(0,ts.size2()); + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.size2()); + } + + @Test + public void testPush2() { + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.pop2()); + assertEquals(1,ts.pop2()); + } + + @Test + public void testPush12() { + ts.push1(1); + ts.push1(2); + assertEquals(2,ts.pop1()); + assertEquals(1,ts.pop1()); + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.pop2()); + assertEquals(1,ts.pop2()); + } + + + @Test + public void testPop1() { + + ts.push1(1); + ts.push1(2); + assertEquals(2,ts.pop1()); + assertEquals(1,ts.pop1()); + + } + + + + @Test + public void testPop2() { + + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.pop2()); + assertEquals(1,ts.pop2()); + + } + + @Test + public void testPeek2() { + + ts.push1(1); + ts.push1(2); + assertEquals(2,ts.pop1()); + assertEquals(1,ts.pop1()); + + ts.push2(1); + ts.push2(2); + assertEquals(2,ts.pop2()); + assertEquals(1,ts.pop2()); + } + + @Test + public void testPeek1() { + + ts.push1(1); + assertEquals(1,ts.peek1()); + ts.push1(2); + assertEquals(2,ts.peek1()); + + } + + @Test + public void testGrow() { + + for(int i = 1; i < 101; i++) { + ts.push1(i); + ts.push2(i); + assertEquals(i,ts.size1()); + assertEquals(i,ts.size2()); + } + + for (int i = 100; i >0; i--) { + assertEquals(i, ts.pop1()); + assertEquals(i, ts.pop2()); + } + + } + + + +} diff --git a/group12/382266293/src/ThreadTest.java b/group12/382266293/src/ThreadTest.java new file mode 100644 index 0000000000..de8c8825e0 --- /dev/null +++ b/group12/382266293/src/ThreadTest.java @@ -0,0 +1,23 @@ +public class ThreadTest extends Thread { + boolean stop = false; + Integer value = 0; + public void run() { + while (!stop) { + + value++; + } + } + + public static void main(String[] args) + throws Exception { + + ThreadTest t = new ThreadTest(); + t.start(); + Thread.sleep(2000); + t.stop = true; + System.out.println("value =" + t.value); + Thread.sleep(2000); + System.out.println("value =" + t.value); + + } +} diff --git a/group12/382266293/src/com/coderising/download/FileDownloader.java b/group12/382266293/src/com/coderising/download/FileDownloader.java index 311ebede84..ea8b3dce85 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloader.java +++ b/group12/382266293/src/com/coderising/download/FileDownloader.java @@ -71,7 +71,7 @@ public void execute() { int length = conn.getContentLength(); System.out.println("file length:" + length); - setLocation("C:\\"); + setLocation("d:\\"); String name = conn.getFileName(); setFileName(name); diff --git a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java index b9c458d2a6..fb681c4c0e 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java +++ b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java @@ -15,6 +15,8 @@ public class FileDownloaderTest { public static String foxmail = "http://sw.bos.baidu.com/sw-search-sp/software/6c7bb8b6674d0/fm728chb379_7.2.8.379_setup.exe"; + public static String Git = "https://github.com/onlyliuxin/coding2017/archive/master.zip"; + boolean downloadFinished = false; @Before public void setUp() throws Exception { @@ -28,7 +30,7 @@ public void testDownload() { String url = "http://localhost:8080/test.jpg"; - FileDownloader downloader = new FileDownloader(foxmail); + FileDownloader downloader = new FileDownloader(Git); ConnectionManager cm = new ConnectionManagerImpl(); downloader.setConnectionManager(cm); diff --git a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java index 7c772bc665..2c89e4c883 100644 --- a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java +++ b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java @@ -3,12 +3,12 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URL; import com.coderising.download.api.Connection; import com.coderising.download.api.ConnectionManager; -import sun.net.www.protocol.http.HttpURLConnection; public class ConnectionImpl implements Connection { diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java index 111cb247d3..f5698f0dd1 100644 --- a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java @@ -5,6 +5,7 @@ import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.field.Field; import com.coderising.jvm.method.Method; @@ -134,19 +135,20 @@ public Method getMethod(String methodName, String paramAndReturnType){ return null; } + public Method getMainMethod(){ - for (Method m : methods) { - - int nameIndex = m.getNameIndex(); - int descriptorIndex= m.getDescriptorIndex(); - String name = ((UTF8Info)pool.getConstantInfo(nameIndex)).getValue(); - String desc = ((UTF8Info)pool.getConstantInfo(descriptorIndex)).getValue(); - if (name.equals("main") && desc.equals("([Ljava/lang/String;)V")) { - return m; - } - } - - return null; + return getMethod("main", "([Ljava/lang/String;)V"); + } + + public Method getMethod(MethodRefInfo methodRef){ + + String methodName = methodRef.getMethodName(); + String paramAndReturnType = methodRef.getParamAndReturnType(); + + return getMethod(methodName, paramAndReturnType); + + } + } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java index cd0fbd4848..b4682ad51d 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -3,6 +3,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -18,6 +22,14 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } + @Override + public void execute(StackFrame frame,ExecutionResult result){ + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + + } + } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java index a3abeacc82..eec01a4cd7 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -6,6 +6,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public abstract class ByteCodeCommand { @@ -14,6 +16,41 @@ public abstract class ByteCodeCommand { ClassFile clzFile; private int offset; + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private static Map codeMap = new HashMap(); static{ @@ -124,5 +161,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java index 2e6061edd2..70a44b9bae 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -16,7 +20,17 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java index e6cf9d5960..1a1332b7e4 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -5,6 +5,10 @@ import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -19,5 +23,21 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java index ac228d0e4d..07af9a6a95 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -3,6 +3,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -18,6 +22,23 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java index c15d827797..362006f04a 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -2,6 +2,12 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -16,6 +22,66 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + } + + private boolean isSystemOutPrintlnMethod(String className, String methodName) { + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java index ffb66f811c..6fee3f6ef6 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -26,4 +30,23 @@ public String toString(ConstantPool pool) { } + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + + } + } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java index 33813b5d59..3a6f062803 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -1,7 +1,12 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -15,5 +20,19 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java index 56c28fefe2..2c41ca7827 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -15,9 +19,130 @@ public String toString(ConstantPool pool) { } - + @Override public int getLength(){ return 1; } + + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } } diff --git a/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java index 85bb369c19..3ef736b39e 100644 --- a/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/group12/382266293/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -1,7 +1,13 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -15,5 +21,23 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } } diff --git a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java index 05882cd5f2..267abbf577 100644 --- a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -13,9 +13,6 @@ public MethodRefInfo(ConstantPool pool) { super(pool); } - public int getClassInfoIndex() { - return classInfoIndex; - } public String getClassName() { ConstantPool pool = this.getConstantPool(); @@ -29,6 +26,11 @@ public String getMethodName() { return typeInfo.getName(); } + + public int getClassInfoIndex() { + return classInfoIndex; + } + public int getNameAndTypeIndex() { return nameAndTypeIndex; } diff --git a/group12/382266293/src/com/coderising/jvm/engine/ExecutionResult.java b/group12/382266293/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..73ba9f51b1 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/ExecutorEngine.java b/group12/382266293/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..7e1f5c1261 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,73 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.isEmpty()) { + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if (result.isPauseAndRunNewFrame()) { + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + } + + } + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method nextMethod = nextFrame.getMethod(); + + List paramList = nextMethod.getParameterList(); + + int paramNum = paramList.size() + 1; + + List params = new ArrayList(); + + while(paramNum > 0) { + params.add(currentFrame.getOprandStack().pop()); + paramNum--; + } + + Collections.reverse(params); + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/Heap.java b/group12/382266293/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..82ad210cef --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/JavaObject.java b/group12/382266293/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..71ba382d9a --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/MethodArea.java b/group12/382266293/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..42f3a71f28 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,80 @@ +package com.coderising.jvm.engine; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = null; + try { + clzFile = this.clzLoader.loadClass(className); + } catch (UnsupportedEncodingException e) { + + e.printStackTrace(); + } + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMethod(methodName, paramAndReturnType); + } + + + public Method getMethod(MethodRefInfo methodRef){ + + String className = methodRef.getClassName(); + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMethod(methodRef); + + } +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/MiniJVM.java b/group12/382266293/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..de8961cac0 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[] classPaths, String className) throws FileNotFoundException, IOException { + + ClassFileLoader loader = new ClassFileLoader(); + for (int i = 0; i < classPaths.length; i++) { + loader.addClassPath(classPaths[i]); + } + + MethodArea methodArea = MethodArea.getInstance(); + + methodArea.setClassFileLoader(loader); + + ExecutorEngine engine = new ExecutorEngine(); + + className = className.replace(".", "/"); + + engine.execute(methodArea.getMainMethod(className)); + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/engine/StackFrame.java b/group12/382266293/src/com/coderising/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..435f025831 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/engine/StackFrame.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.method.Method; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group12/382266293/src/com/coderising/jvm/method/Method.java b/group12/382266293/src/com/coderising/jvm/method/Method.java index 2bb53cdf06..46322f16e8 100644 --- a/group12/382266293/src/com/coderising/jvm/method/Method.java +++ b/group12/382266293/src/com/coderising/jvm/method/Method.java @@ -1,5 +1,8 @@ package com.coderising.jvm.method; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; @@ -107,4 +110,67 @@ public String toString() { return buffer.toString(); } + + public List getParameterList() { + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } + + + private String getParamAndReturnType() { + + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + } diff --git a/group12/382266293/src/com/coderising/jvm/test/MiniJVMTest.java b/group12/382266293/src/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..88de6c179e --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "C:\\Users\\steve\\workspace\\coding2017n\\group12\\382266293\\bin"; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} diff --git a/group12/495473393/Code/src/week2/litestruts/Configuration.java b/group12/495473393/Code/src/week2/litestruts/Configuration.java new file mode 100644 index 0000000000..990df538f9 --- /dev/null +++ b/group12/495473393/Code/src/week2/litestruts/Configuration.java @@ -0,0 +1,113 @@ +package week2.litestruts; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.jdom2.input.SAXBuilder; + +public class Configuration { + + Map actions = new HashMap<>(); + + public Configuration(String fileName) { + + String packageName = this.getClass().getPackage().getName(); + + packageName = packageName.replace('.', '/'); + + InputStream is = this.getClass().getResourceAsStream("/" + packageName + "/" + fileName); + + parseXML(is); + + try { + is.close(); + } catch (IOException e) { + throw new ConfigurationException(e); + } + } + + private void parseXML(InputStream is){ + + SAXBuilder builder = new SAXBuilder(); + + try { + + Document doc = builder.build(is); + + Element root = doc.getRootElement(); + + for(Element actionElement : root.getChildren("action")){ + + String actionName = actionElement.getAttributeValue("name"); + String clzName = actionElement.getAttributeValue("class"); + + ActionConfig ac = new ActionConfig(actionName, clzName); + + for(Element resultElement : actionElement.getChildren("result")){ + + String resultName = resultElement.getAttributeValue("name"); + String viewName = resultElement.getText().trim(); + + ac.addViewResult(resultName, viewName); + + } + + this.actions.put(actionName, ac); + } + + + } catch (JDOMException e) { + throw new ConfigurationException(e); + + } catch (IOException e) { + throw new ConfigurationException(e); + + } + + + } + + public String getClassName(String action) { + ActionConfig ac = this.actions.get(action); + if(ac == null){ + return null; + } + return ac.getClassName(); + } + + public String getResultView(String action, String resultName) { + ActionConfig ac = this.actions.get(action); + if(ac == null){ + return null; + } + return ac.getViewName(resultName); + } + + private static class ActionConfig{ + + String name; + String clzName; + Map viewResult = new HashMap<>(); + + + public ActionConfig(String actionName, String clzName) { + this.name = actionName; + this.clzName = clzName; + } + public String getClassName(){ + return clzName; + } + public void addViewResult(String name, String viewName){ + viewResult.put(name, viewName); + } + public String getViewName(String resultName){ + return viewResult.get(resultName); + } + } + +} diff --git a/group12/495473393/Code/src/week2/litestruts/ConfigurationException.java b/group12/495473393/Code/src/week2/litestruts/ConfigurationException.java new file mode 100644 index 0000000000..943454e813 --- /dev/null +++ b/group12/495473393/Code/src/week2/litestruts/ConfigurationException.java @@ -0,0 +1,21 @@ +package week2.litestruts; + +import java.io.IOException; + +import org.jdom2.JDOMException; + +public class ConfigurationException extends RuntimeException { + + public ConfigurationException(String msg) { + super(msg); + } + + public ConfigurationException(JDOMException e) { + super(e); + } + + public ConfigurationException(IOException e) { + super(e); + } + +} diff --git a/group12/495473393/Code/src/week2/litestruts/ConfigurationTest.java b/group12/495473393/Code/src/week2/litestruts/ConfigurationTest.java new file mode 100644 index 0000000000..d07f9945fe --- /dev/null +++ b/group12/495473393/Code/src/week2/litestruts/ConfigurationTest.java @@ -0,0 +1,41 @@ +package week2.litestruts; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ConfigurationTest { + Configuration cfg = new Configuration("struts.xml"); + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetClassName() { + String clzName = cfg.getClassName("login"); + Assert.assertEquals("com.coderising.litestruts.LoginAction", clzName); + clzName = cfg.getClassName("logout"); + Assert.assertEquals("com.coderising.litestruts.LogoutAction", clzName); + } + + @Test + public void testGetResultView() { + String jsp = cfg.getResultView("login", "success"); + Assert.assertEquals("/jsp/homepage.jsp", jsp); + + jsp = cfg.getResultView("login", "fail"); + Assert.assertEquals("/jsp/showLogin.jsp", jsp); + + jsp = cfg.getResultView("logout", "success"); + Assert.assertEquals("/jsp/welcome.jsp", jsp); + + jsp = cfg.getResultView("logout", "error"); + Assert.assertEquals("/jsp/error.jsp", jsp); + } +} diff --git a/group12/495473393/Code/src/week2/litestruts/LoginAction.java b/group12/495473393/Code/src/week2/litestruts/LoginAction.java index d8daf1c835..b4e7662119 100644 --- a/group12/495473393/Code/src/week2/litestruts/LoginAction.java +++ b/group12/495473393/Code/src/week2/litestruts/LoginAction.java @@ -2,7 +2,6 @@ /** * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * @author liuxin * */ public class LoginAction{ diff --git a/group12/495473393/Code/src/week2/litestruts/ReflectionUtil.java b/group12/495473393/Code/src/week2/litestruts/ReflectionUtil.java new file mode 100644 index 0000000000..917edfb1f9 --- /dev/null +++ b/group12/495473393/Code/src/week2/litestruts/ReflectionUtil.java @@ -0,0 +1,83 @@ +package week2.litestruts; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReflectionUtil { + + public static List getSetterMethods(Class clz) { + return getMethods(clz, "set"); + } + + public static void setParameters(Object o, Map params) { + List methods = getSetterMethods(o.getClass()); + for (String name : params.keySet()) { + String methodName = "set" + name; + for (Method m : methods) { + if (m.getName().equalsIgnoreCase(methodName)) { + try { + m.invoke(o, params.get(name)); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + } + + public static List getGetterMethods(Class clz) { + return getMethods(clz, "get"); + } + + private static List getMethods(Class clz, String startWithName) { + List methods = new ArrayList<>(); + for (Method m : clz.getDeclaredMethods()) { + if (m.getName().startsWith(startWithName)) { + methods.add(m); + } + } + return methods; + } + + public static Map getParamterMap(Object o) { + Map params = new HashMap<>(); + List methods = getGetterMethods(o.getClass()); + for (Method m : methods) { + String methodName = m.getName(); + String name = methodName.replaceFirst("get", "").toLowerCase(); + try { + Object value = m.invoke(o); + params.put(name, value); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + } + return params; + } + + //////////////////////// Backup /////////////////////////////////// + + public static List getGetterMethods_V1(Class clz) { + List methods = new ArrayList<>(); + for (Method m : clz.getDeclaredMethods()) { + if (m.getName().startsWith("get")) { + methods.add(m); + } + } + return methods; + } + + public static List getSetterMethods_V1(Class clz) { + List methods = new ArrayList<>(); + for (Method m : clz.getDeclaredMethods()) { + if (m.getName().startsWith("set")) { + methods.add(m); + } + } + return methods; + } +} diff --git a/group12/495473393/Code/src/week2/litestruts/ReflectionUtilTest.java b/group12/495473393/Code/src/week2/litestruts/ReflectionUtilTest.java new file mode 100644 index 0000000000..c112ef9a38 --- /dev/null +++ b/group12/495473393/Code/src/week2/litestruts/ReflectionUtilTest.java @@ -0,0 +1,108 @@ +package week2.litestruts; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ReflectionUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetSetterMethod() throws Exception { + + String name = "com.coderising.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getSetterMethods(clz); + + Assert.assertEquals(2, methods.size()); + + List expectedNames = new ArrayList<>(); + expectedNames.add("setName"); + expectedNames.add("setPassword"); + + Set acctualNames = new HashSet<>(); + for(Method m : methods){ + acctualNames.add(m.getName()); + } + + Assert.assertTrue(acctualNames.containsAll(expectedNames)); + } + + @Test + public void testSetParameters() throws Exception{ + + String name = "com.coderising.litestruts.LoginAction"; + Class clz = Class.forName(name); + Object o = clz.newInstance(); + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + ReflectionUtil.setParameters(o,params); + + + + Field f = clz.getDeclaredField("name"); + f.setAccessible(true); + Assert.assertEquals("test", f.get(o)); + + f = clz.getDeclaredField("password"); + f.setAccessible(true); + Assert.assertEquals("1234", f.get(o)); + } + @Test + public void testGetGetterMethod() throws Exception{ + String name = "com.coderising.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getGetterMethods(clz); + + Assert.assertEquals(3, methods.size()); + + List expectedNames = new ArrayList<>(); + expectedNames.add("getMessage"); + expectedNames.add("getName"); + expectedNames.add("getPassword"); + + Set acctualNames = new HashSet<>(); + for(Method m : methods){ + acctualNames.add(m.getName()); + } + + Assert.assertTrue(acctualNames.containsAll(expectedNames)); + } + + @Test + public void testGetParamters() throws Exception{ + String name = "com.coderising.litestruts.LoginAction"; + Class clz = Class.forName(name); + LoginAction action = (LoginAction)clz.newInstance(); + action.setName("test"); + action.setPassword("123456"); + + Map params = ReflectionUtil.getParamterMap(action); + + Assert.assertEquals(3, params.size()); + + Assert.assertEquals(null, params.get("messaage") ); + Assert.assertEquals("test", params.get("name") ); + Assert.assertEquals("123456", params.get("password") ); + } +} diff --git a/group12/495473393/Code/src/week2/litestruts/Struts.java b/group12/495473393/Code/src/week2/litestruts/Struts.java index bafaaafd8c..e240afc83b 100644 --- a/group12/495473393/Code/src/week2/litestruts/Struts.java +++ b/group12/495473393/Code/src/week2/litestruts/Struts.java @@ -1,11 +1,12 @@ package week2.litestruts; +import java.lang.reflect.Method; import java.util.Map; - - public class Struts { + private final static Configuration cfg = new Configuration("struts.xml"); + public static View runAction(String actionName, Map parameters) { /* @@ -27,8 +28,29 @@ public static View runAction(String actionName, Map parameters) { 放到View对象的jsp字段中。 */ - + + String clzName = cfg.getClassName(actionName); + if(clzName == null){ + return null; + } + try { + Class clz = Class.forName(clzName); + Object action = clz.newInstance(); + + ReflectionUtil.setParameters(action, parameters); + + Method m = clz.getDeclaredMethod("execute"); + String resultName = (String)m.invoke(action); + + Map params = ReflectionUtil.getParamterMap(action); + String resultView = cfg.getResultView(actionName, resultName); + View view = new View(); + view.setParameters(params); + view.setJsp(resultView); + return view; + } catch (Exception e) { + e.printStackTrace(); + } return null; } - } diff --git a/group12/495473393/Code/src/week2/litestruts/StrutsTest.java b/group12/495473393/Code/src/week2/litestruts/StrutsTest.java index 9187ef02f2..e048bf9d6e 100644 --- a/group12/495473393/Code/src/week2/litestruts/StrutsTest.java +++ b/group12/495473393/Code/src/week2/litestruts/StrutsTest.java @@ -6,10 +6,6 @@ import org.junit.Assert; import org.junit.Test; - - - - public class StrutsTest { @Test diff --git a/group12/495473393/Code/src/week2/litestruts/struts.xml b/group12/495473393/Code/src/week2/litestruts/struts.xml index a6cfe43e6c..638a5f1f15 100644 --- a/group12/495473393/Code/src/week2/litestruts/struts.xml +++ b/group12/495473393/Code/src/week2/litestruts/struts.xml @@ -1,11 +1,11 @@ - + - + /jsp/homepage.jsp /jsp/showLogin.jsp - - /jsp/welcome.jsp - /jsp/error.jsp + + /jsp/welcome.jsp + /jsp/error.jsp \ No newline at end of file diff --git a/group12/495473393/Code/src/week3/DownloadThread.java b/group12/495473393/Code/src/week3/DownloadThread.java new file mode 100644 index 0000000000..53d7ed3101 --- /dev/null +++ b/group12/495473393/Code/src/week3/DownloadThread.java @@ -0,0 +1,20 @@ +package week3; + +import week3.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + public DownloadThread( Connection conn, int startPos, int endPos){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + public void run(){ + + } +} diff --git a/group12/495473393/Code/src/week3/FileDownloader.java b/group12/495473393/Code/src/week3/FileDownloader.java new file mode 100644 index 0000000000..7a6b104245 --- /dev/null +++ b/group12/495473393/Code/src/week3/FileDownloader.java @@ -0,0 +1,72 @@ +package week3; + +import week3.api.Connection; +import week3.api.ConnectionException; +import week3.api.ConnectionManager; +import week3.api.DownloadListener; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + new DownloadThread(conn,0,length-1).start(); + + } catch (ConnectionException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group12/495473393/Code/src/week3/FileDownloaderTest.java b/group12/495473393/Code/src/week3/FileDownloaderTest.java new file mode 100644 index 0000000000..b6ddb18069 --- /dev/null +++ b/group12/495473393/Code/src/week3/FileDownloaderTest.java @@ -0,0 +1,61 @@ +package week3; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import week3.api.ConnectionManager; +import week3.api.DownloadListener; +import week3.impl.ConnectionManagerImpl; + + + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "http://localhost:8080/test.jpg"; + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group12/495473393/Code/src/week3/api/Connection.java b/group12/495473393/Code/src/week3/api/Connection.java new file mode 100644 index 0000000000..bba3230710 --- /dev/null +++ b/group12/495473393/Code/src/week3/api/Connection.java @@ -0,0 +1,23 @@ +package week3.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group12/495473393/Code/src/week3/api/ConnectionException.java b/group12/495473393/Code/src/week3/api/ConnectionException.java new file mode 100644 index 0000000000..e760e23ddb --- /dev/null +++ b/group12/495473393/Code/src/week3/api/ConnectionException.java @@ -0,0 +1,5 @@ +package week3.api; + +public class ConnectionException extends Exception { + +} diff --git a/group12/495473393/Code/src/week3/api/ConnectionManager.java b/group12/495473393/Code/src/week3/api/ConnectionManager.java new file mode 100644 index 0000000000..9b20c0177b --- /dev/null +++ b/group12/495473393/Code/src/week3/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package week3.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group12/495473393/Code/src/week3/api/DownloadListener.java b/group12/495473393/Code/src/week3/api/DownloadListener.java new file mode 100644 index 0000000000..da4eb7abc3 --- /dev/null +++ b/group12/495473393/Code/src/week3/api/DownloadListener.java @@ -0,0 +1,5 @@ +package week3.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group12/495473393/Code/src/week3/impl/ConnectionImpl.java b/group12/495473393/Code/src/week3/impl/ConnectionImpl.java new file mode 100644 index 0000000000..e354f10029 --- /dev/null +++ b/group12/495473393/Code/src/week3/impl/ConnectionImpl.java @@ -0,0 +1,26 @@ +package week3.impl; + +import java.io.IOException; +import week3.api.Connection; + +public class ConnectionImpl implements Connection{ + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + return null; + } + + @Override + public int getContentLength() { + + return 0; + } + + @Override + public void close() { + + + } + +} diff --git a/group12/495473393/Code/src/week3/impl/ConnectionManagerImpl.java b/group12/495473393/Code/src/week3/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..d58a2b600d --- /dev/null +++ b/group12/495473393/Code/src/week3/impl/ConnectionManagerImpl.java @@ -0,0 +1,18 @@ +package week3.impl; + +import java.net.HttpURLConnection; +import java.net.URL; + +import week3.api.Connection; +import week3.api.ConnectionException; +import week3.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + + return null; + } + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExpr.java b/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExpr.java new file mode 100644 index 0000000000..f0f597e6cb --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExpr.java @@ -0,0 +1,121 @@ +package io.github.vxzh.datastructure.less6.expr; + +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + check(); + + Stack operateStack = new Stack(); + Stack numStack = new Stack(); + + char[] ch = expr.toCharArray(); + + for (int i = 0; i < ch.length; i++) { + + if (Character.isDigit(ch[i])) { + int tmp = Integer.parseInt("" + ch[i]); + while (i < ch.length - 1 && Character.isDigit(ch[++i])) { + tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + } + numStack.push(tmp); + + } + if (ch[i] == '+' || ch[i] == '-' || ch[i] == '*' || ch[i] == '/') { + operateStack.push(ch[i]); + } + + if (!(operateStack.isEmpty()) && (char) operateStack.peek() == '*') { + int tmp = Integer.parseInt("" + ch[++i]); + while (i < ch.length - 1 && Character.isDigit(ch[++i])) { + tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + } + if (i != ch.length - 1) { + i--; + } + numStack.push(tmp); + + int tmp1 = Integer.parseInt("" + numStack.pop()); + int tmp2 = Integer.parseInt("" + numStack.pop()); + numStack.push(tmp1 * tmp2); + operateStack.pop(); + + } + if (!(operateStack.isEmpty()) && (char) operateStack.peek() == '/') { + int tmp = Integer.parseInt("" + ch[++i]); + while (i < ch.length - 1 && Character.isDigit(ch[++i])) { + tmp = tmp * 10 + Integer.parseInt("" + ch[i]); + } + if (i != ch.length - 1) { + i--; + } + numStack.push(tmp); + + int tmp1 = Integer.parseInt("" + numStack.pop()); + int tmp2 = Integer.parseInt("" + numStack.pop()); + numStack.push(tmp2 / tmp1); + operateStack.pop(); + } + } + // 将栈中的数字和运算法逆置,便于计算 + reverse(numStack); + reverse(operateStack); + + while (!(operateStack.isEmpty())) { + if ((char) operateStack.peek() == '+') { + int tmp1 = Integer.parseInt("" + numStack.pop()); + int tmp2 = Integer.parseInt("" + numStack.pop()); + numStack.push(tmp1 + tmp2); + } + + if ((char) operateStack.peek() == '-') { + int tmp1 = Integer.parseInt("" + numStack.pop()); + int tmp2 = Integer.parseInt("" + numStack.pop()); + numStack.push(tmp1 - tmp2); + } + operateStack.pop(); + } + + return Float.parseFloat("" + numStack.pop()); + } + + private void reverse(Stack s) { + + if (s.isEmpty()) { + return; + } + // 如果s里面只有一个元素,就返回。具体实现是先pop出来一个,判断剩下的是不是空栈。 + Object tmp1 = s.pop(); + reverse(s); + if (s.isEmpty()) { + s.push(tmp1); + return; + } + Object temp2 = s.pop(); + reverse(s); + s.push(tmp1); + reverse(s); + s.push(temp2); + + } + + private boolean check() { + if (expr.length() <= 0) { + return false; + } else if ('+' == expr.charAt(0) || '-' == expr.charAt(0) || '*' == expr.charAt(0) || '/' == expr.charAt(0)) { + return false; + } else if ('+' == expr.charAt(expr.length() - 1) || '-' == expr.charAt(expr.length() - 1) || '*' == expr.charAt(expr.length() - 1) || '/' == expr.charAt(expr.length() - 1)) { + return false; + } + + return true; + } + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExprTest.java b/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExprTest.java new file mode 100644 index 0000000000..dbf63cea14 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/datastructure/less6/expr/InfixExprTest.java @@ -0,0 +1,47 @@ +package io.github.vxzh.datastructure.less6.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/AttributeInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..cec3cd75f7 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/AttributeInfo.java @@ -0,0 +1,20 @@ +package io.github.vxzh.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/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/CodeAttr.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..de04b35cad --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/CodeAttr.java @@ -0,0 +1,116 @@ +package io.github.vxzh.jvm.attr; + + +import io.github.vxzh.jvm.clz.ClassFile; +import io.github.vxzh.jvm.clz.ConstantPool; +import io.github.vxzh.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 attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + //ByteCodeCommand[] cmds = ByteCodeCommand.parse(clzFile,code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.nextU2ToInt(); + //TODO 处理exception + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.nextU2ToInt(); + + for (int x = 1; x <= subAttrCount; x++) { + int subAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(2); + //line item table + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + 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 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 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 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(); + + } + + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableItem.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..a0e0f4286a --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableItem.java @@ -0,0 +1,49 @@ +package io.github.vxzh.jvm.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/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableTable.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..4993f6ce77 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package io.github.vxzh.jvm.attr; + + +import io.github.vxzh.jvm.clz.ConstantPool; +import io.github.vxzh.jvm.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 index = iter.nextU2ToInt(); + int len = iter.nextU4ToInt(); + + LocalVariableTable table = new LocalVariableTable(index, len); + + int itemLen = iter.nextU2ToInt(); + + for (int i = 1; i <= itemLen; i++) { + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLength(iter.nextU2ToInt()); + item.setNameIndex(iter.nextU2ToInt()); + item.setDescIndex(iter.nextU2ToInt()); + item.setIndex(iter.nextU2ToInt()); + 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(); + } +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/StackMapTable.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..4538a51d42 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package io.github.vxzh.jvm.attr; + + +import io.github.vxzh.jvm.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/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/AccessFlag.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/AccessFlag.java new file mode 100755 index 0000000000..4c3a3c8900 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/AccessFlag.java @@ -0,0 +1,26 @@ +package io.github.vxzh.jvm.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/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassFile.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassFile.java new file mode 100755 index 0000000000..93adf1976a --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassFile.java @@ -0,0 +1,106 @@ +package io.github.vxzh.jvm.clz; + +import io.github.vxzh.jvm.constant.ClassInfo; +import io.github.vxzh.jvm.field.Field; +import io.github.vxzh.jvm.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()); + + + } + + private String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassIndex.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassIndex.java new file mode 100755 index 0000000000..4500959430 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package io.github.vxzh.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ConstantPool.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ConstantPool.java new file mode 100755 index 0000000000..b96e330020 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/clz/ConstantPool.java @@ -0,0 +1,35 @@ +package io.github.vxzh.jvm.clz; + +import io.github.vxzh.jvm.constant.ConstantInfo; +import io.github.vxzh.jvm.constant.UTF8Info; + +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 Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ClassInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ClassInfo.java new file mode 100755 index 0000000000..c9586ee16c --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ClassInfo.java @@ -0,0 +1,30 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class ClassInfo extends ConstantInfo { + private int tag = ConstantInfo.CONSTANT_CLASS_INFO; + private int nameIndex; + + public ClassInfo(ConstantPool pool) { + super(pool); + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getTag() { + return tag; + } + + public String getClassName() { + int index = getNameIndex(); + UTF8Info utf8Info = (UTF8Info) constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ConstantInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ConstantInfo.java new file mode 100755 index 0000000000..0f3d63685c --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/ConstantInfo.java @@ -0,0 +1,42 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public abstract class ConstantInfo { + + public static final int CONSTANT_UTF8_INFO = 1;// + public static final int CONSTANT_INTEGER_INFO = 3; + public static final int CONSTANT_FLOAT_INFO = 4;// + public static final int CONSTANT_LONG_INFO = 5; + public static final int CONSTANT_DOUBLE_INFO = 6; + public static final int CONSTANT_CLASS_INFO = 7;// + public static final int CONSTANT_STRING_INFO = 8;// + public static final int CONSTANT_FIELDREF_INFO = 9;// + public static final int CONSTANT_METHODREF_INFO = 10;// + public static final int CONSTANT_INTERFACEMETHODREF_INFO = 11; + public static final int CONSTANT_NAMEANDTYPE_INFO = 12;// + public static final int CONSTANT_METHODHANDLE_INFO = 15; + public static final int CONSTANT_METHODTYPE_INFO = 16; + public static final int CONSTANT_INVOKEDYNAMIC_INFO = 18; + + protected ConstantPool constantPool; + + public ConstantInfo() { + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + + public abstract int getTag(); + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/FieldRefInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/FieldRefInfo.java new file mode 100755 index 0000000000..f39bc87b72 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/FieldRefInfo.java @@ -0,0 +1,60 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class FieldRefInfo extends ConstantInfo { + private int tag = ConstantInfo.CONSTANT_FIELDREF_INFO; + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + + public int getTag() { + return tag; + } + + 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.getNameIndex()); + + 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(); + } +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/MethodRefInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/MethodRefInfo.java new file mode 100755 index 0000000000..46535b7769 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class MethodRefInfo extends ConstantInfo { + + private int tag = ConstantInfo.CONSTANT_METHODREF_INFO; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getTag() { + return tag; + } + + 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(); + } + + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NameAndTypeInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NameAndTypeInfo.java new file mode 100755 index 0000000000..a081902eac --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class NameAndTypeInfo extends ConstantInfo { + public int tag = ConstantInfo.CONSTANT_NAMEANDTYPE_INFO; + + private int nameIndex; + private int descriptorIndex; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + public int getTag() { + return tag; + } + + + public String getName() { + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info) pool.getConstantInfo(nameIndex); + return utf8Info1.getValue(); + } + + public String getTypeInfo() { + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info) pool.getConstantInfo(descriptorIndex); + return utf8Info2.getValue(); + } + + public String toString() { + return "(" + getName() + "," + getTypeInfo() + ")"; + } +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NullConstantInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NullConstantInfo.java new file mode 100755 index 0000000000..1d1d8394f9 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package io.github.vxzh.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getTag() { + return -1; + } + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/StringInfo.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/StringInfo.java new file mode 100755 index 0000000000..e5175eed4a --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/StringInfo.java @@ -0,0 +1,30 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class StringInfo extends ConstantInfo { + private int tag = ConstantInfo.CONSTANT_STRING_INFO; + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + + public int getTag() { + return tag; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/UTF8Info.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/UTF8Info.java new file mode 100755 index 0000000000..e1fb81006b --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +package io.github.vxzh.jvm.constant; + +import io.github.vxzh.jvm.clz.ConstantPool; + +public class UTF8Info extends ConstantInfo { + private int tag = ConstantInfo.CONSTANT_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 getTag() { + return tag; + } + + @Override + public String toString() { + return "UTF8Info [tag=" + tag + ", length=" + length + ", value=" + value + ")]"; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/field/Field.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/field/Field.java new file mode 100644 index 0000000000..7bb54a6b0c --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/field/Field.java @@ -0,0 +1,48 @@ +package io.github.vxzh.jvm.field; + + +import io.github.vxzh.jvm.clz.ClassFile; +import io.github.vxzh.jvm.constant.UTF8Info; +import io.github.vxzh.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private ClassFile clzFile; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ClassFile clzFile) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.clzFile = clzFile; + } + + public String toString() { + String name = ((UTF8Info) clzFile.getConstantPool().getConstantInfo(this.nameIndex)).getValue(); + String desc = ((UTF8Info) clzFile.getConstantPool().getConstantInfo(this.descriptorIndex)).getValue(); + return name + ":" + desc; + } + + + public static Field parse(ClassFile clzFile, 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, clzFile); + + if (attribCount > 0) { + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} + + diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ByteCodeIterator.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..f3744d85b5 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,58 @@ +package io.github.vxzh.jvm.loader; + +import io.github.vxzh.jvm.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; + } + + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileLoader.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileLoader.java new file mode 100755 index 0000000000..275e9da3ac --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileLoader.java @@ -0,0 +1,58 @@ +package io.github.vxzh.jvm.loader; + +import io.github.vxzh.jvm.clz.ClassFile; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +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; + } + + public void addClassPath(String path) { + if (this.clzPaths.contains(path)) { + return; + } + clzPaths.add(path); + } + + public String getClassPath() { + return StringUtils.join(this.clzPaths, ";"); + } + + 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 ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileParser.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..4f5bafddbe --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/loader/ClassFileParser.java @@ -0,0 +1,188 @@ +package io.github.vxzh.jvm.loader; + +import io.github.vxzh.jvm.clz.AccessFlag; +import io.github.vxzh.jvm.clz.ClassFile; +import io.github.vxzh.jvm.clz.ClassIndex; +import io.github.vxzh.jvm.clz.ConstantPool; +import io.github.vxzh.jvm.constant.ClassInfo; +import io.github.vxzh.jvm.constant.FieldRefInfo; +import io.github.vxzh.jvm.constant.MethodRefInfo; +import io.github.vxzh.jvm.constant.NameAndTypeInfo; +import io.github.vxzh.jvm.constant.NullConstantInfo; +import io.github.vxzh.jvm.constant.StringInfo; +import io.github.vxzh.jvm.constant.UTF8Info; +import io.github.vxzh.jvm.field.Field; +import io.github.vxzh.jvm.method.Method; + +import java.io.UnsupportedEncodingException; + +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_CLASS_INFO; +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_FIELDREF_INFO; +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_METHODREF_INFO; +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_NAMEANDTYPE_INFO; +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_STRING_INFO; +import static io.github.vxzh.jvm.constant.ConstantInfo.CONSTANT_UTF8_INFO; + +public class ClassFileParser { + + + public ClassFile parse(byte[] codes) { + + ClassFile clzFile = new ClassFile(); + + ByteCodeIterator iter = new ByteCodeIterator(codes); + + //验证魔数 + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + + //解析次版本号和主版本号 + clzFile.setMinorVersion(iter.nextU2ToInt()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + + //解析常量池 + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstPool(pool); + + //解析访问标志 + AccessFlag flag = parseAccessFlag(iter); + clzFile.setAccessFlag(flag); + + //解析类索引和父类索引 + ClassIndex clzIndex = parseClassInfex(iter); + clzFile.setClassIndex(clzIndex); + + //解析接口 + parseInterfaces(iter); + + //解析字段表集合 + parseFileds(clzFile, iter); + + //解析方法表集合 + parseMethods(clzFile, iter); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + AccessFlag flag = new AccessFlag(iter.nextU2ToInt()); + // System.out.println("Is public class: " + flag.isPublicClass()); + // System.out.println("Is final class : " + flag.isFinalClass()); + + return flag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + ClassIndex clzIndex = new ClassIndex(); + + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + + return clzIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int constPoolCount = iter.nextU2ToInt(); + + System.out.println("Constant Pool Count :" + constPoolCount); + + ConstantPool pool = new ConstantPool(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= constPoolCount - 1; i++) { + + int tag = iter.nextU1toInt(); + + if (tag == CONSTANT_CLASS_INFO) {//7 + // Class Info + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setNameIndex(utf8Index); + pool.addConstantInfo(clzInfo); + } else if (tag == CONSTANT_UTF8_INFO) {//1 + // UTF-8 String + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info utf8Str = new UTF8Info(pool); + utf8Str.setLength(len); + utf8Str.setValue(value); + pool.addConstantInfo(utf8Str); + } else if (tag == CONSTANT_STRING_INFO) {//8 + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + } else if (tag == CONSTANT_FIELDREF_INFO) {//9 + FieldRefInfo field = new FieldRefInfo(pool); + field.setClassInfoIndex(iter.nextU2ToInt()); + field.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(field); + } else if (tag == CONSTANT_METHODREF_INFO) {//10 + // MethodRef + MethodRefInfo method = new MethodRefInfo(pool); + method.setClassInfoIndex(iter.nextU2ToInt()); + method.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(method); + } else if (tag == CONSTANT_NAMEANDTYPE_INFO) {//12 + // Name and Type Info + NameAndTypeInfo nameType = new NameAndTypeInfo(pool); + nameType.setNameIndex(iter.nextU2ToInt()); + nameType.setDescriptorIndex(iter.nextU2ToInt()); + pool.addConstantInfo(nameType); + } else { + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); + } + } + + System.out.println("Finished reading Constant pool "); + + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { + int fieldCount = iter.nextU2ToInt(); + + for (int i = 1; i <= fieldCount; i++) { + Field f = Field.parse(clzFile, iter); + clzFile.addField(f); + } + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + + int methodCount = iter.nextU2ToInt(); + + for (int i = 1; i <= methodCount; i++) { + Method m = Method.parse(clzFile, iter); + clzFile.addMethod(m); + } + + } + + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/method/Method.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/method/Method.java new file mode 100644 index 0000000000..40d88910e3 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/method/Method.java @@ -0,0 +1,92 @@ +package io.github.vxzh.jvm.method; + + +import io.github.vxzh.jvm.attr.AttributeInfo; +import io.github.vxzh.jvm.attr.CodeAttr; +import io.github.vxzh.jvm.clz.ClassFile; +import io.github.vxzh.jvm.clz.ConstantPool; +import io.github.vxzh.jvm.constant.UTF8Info; +import io.github.vxzh.jvm.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private CodeAttr codeAttr; + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for (int i = 0; i < attribCount; i++) { + + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if (AttributeInfo.CODE.equalsIgnoreCase(attrName)) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("only CODE attribute is implemented , please implement the " + attrName); + } + + } + + return m; + + } + + +} diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/test/ClassFileloaderTest.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/test/ClassFileloaderTest.java new file mode 100755 index 0000000000..b8defc4b12 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,254 @@ +package io.github.vxzh.jvm.test; + +import io.github.vxzh.jvm.clz.ClassFile; +import io.github.vxzh.jvm.clz.ClassIndex; +import io.github.vxzh.jvm.clz.ConstantPool; +import io.github.vxzh.jvm.constant.ClassInfo; +import io.github.vxzh.jvm.constant.MethodRefInfo; +import io.github.vxzh.jvm.constant.NameAndTypeInfo; +import io.github.vxzh.jvm.constant.UTF8Info; +import io.github.vxzh.jvm.field.Field; +import io.github.vxzh.jvm.loader.ClassFileLoader; +import io.github.vxzh.jvm.method.Method; + +import io.github.vxzh.jvm.util.Util; +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 = "com/coderising/jvm/test/EmployeeV1"; + static String path1 = "/Users/xuxiaoqing/Workspace/test"; + static String path2 = "/Users/xuxiaoqing/Documents/demo"; + + static ClassFile clzFile = null; + + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "io.github.vxzh.jvm.test.EmployeeV1"; + + clzFile = loader.loadClass(className); + clzFile.print(); + } + + + @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 = "io.github.vxzh.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "io.github.vxzh.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + + String acctualValue = Util.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + @Test + public void testVersion() { + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool() { + + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getNameIndex()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getNameIndex()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", 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.getNameIndex()); + Assert.assertEquals(14, nameAndType.getDescriptorIndex()); + } + //抽查几个吧 + { + 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); + } + + +} \ No newline at end of file diff --git a/group13/2729382520/L6/src/io/github/vxzh/jvm/test/EmployeeV1.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/test/EmployeeV1.java new file mode 100755 index 0000000000..87e05ff033 --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +package io.github.vxzh.jvm.test; + +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/group13/2729382520/L6/src/io/github/vxzh/jvm/util/Util.java b/group13/2729382520/L6/src/io/github/vxzh/jvm/util/Util.java new file mode 100644 index 0000000000..9a659ef3eb --- /dev/null +++ b/group13/2729382520/L6/src/io/github/vxzh/jvm/util/Util.java @@ -0,0 +1,23 @@ +package io.github.vxzh.jvm.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 < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task8/jvm/attr/AttributeInfo.java b/group15/1507_977996067/src/task8/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..ec71b64d22 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package task8.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/group15/1507_977996067/src/task8/jvm/attr/CodeAttr.java b/group15/1507_977996067/src/task8/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..bd9658c0bc --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/CodeAttr.java @@ -0,0 +1,120 @@ +package task8.jvm.attr; + + +import task8.jvm.clz.ClassFile; +import task8.jvm.cmd.ByteCodeCommand; +import task8.jvm.cmd.CommandParser; +import task8.jvm.constant.ConstantPool; +import task8.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 attrNameIndex = iter.next2Bytes(); + int attrLen = iter.next4Bytes(); + int maxStack = iter.next2Bytes(); + int maxLocals = iter.next2Bytes(); + int codeLen = iter.next4Bytes(); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println(code); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.next2Bytes(); + //TODO 处理exception + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + + int subAttrCount = iter.next2Bytes(); + + for (int x = 1; x <= subAttrCount; x++) { + int subAttrIndex = iter.next2Bytes(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + + //已经向前移动了U2, 现在退回去。 + iter.back(2); + //line item table + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need code to process " + subAttrName); + } + + + } + + return codeAttr; + } + + + public String toString(ConstantPool pool) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Code:").append(code).append("\n"); + for (int i = 0; i < cmds.length; i++) { + buffer.append(cmds[i].toString(pool)).append("\n"); + } + buffer.append("\n"); + buffer.append(this.lineNumTable.toString()); + buffer.append(this.localVarTable.toString(pool)); + return buffer.toString(); + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/attr/LineNumberTable.java b/group15/1507_977996067/src/task8/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..b191bb8f29 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/LineNumberTable.java @@ -0,0 +1,72 @@ +package task8.jvm.attr; + +import task8.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTable extends AttributeInfo { + List 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(ByteCodeIterator iter) { + + int index = iter.next2Bytes(); + int len = iter.next4Bytes(); + + LineNumberTable table = new LineNumberTable(index, len); + + int itemLen = iter.next2Bytes(); + + for (int i = 1; i <= itemLen; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.next2Bytes()); + item.setLineNum(iter.next2Bytes()); + 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/group15/1507_977996067/src/task8/jvm/attr/LocalVariableItem.java b/group15/1507_977996067/src/task8/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..484e395f4b --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package task8.jvm.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/group15/1507_977996067/src/task8/jvm/attr/LocalVariableTable.java b/group15/1507_977996067/src/task8/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..5d4481fff5 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package task8.jvm.attr; + + +import task8.jvm.constant.ConstantPool; +import task8.jvm.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 index = iter.next2Bytes(); + int len = iter.next4Bytes(); + + LocalVariableTable table = new LocalVariableTable(index,len); + + int itemLen = iter.next2Bytes(); + + for(int i=1; i<=itemLen; i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.next2Bytes()); + item.setLength(iter.next2Bytes()); + item.setNameIndex(iter.next2Bytes()); + item.setDescIndex(iter.next2Bytes()); + item.setIndex(iter.next2Bytes()); + 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/group15/1507_977996067/src/task8/jvm/attr/StackMapTable.java b/group15/1507_977996067/src/task8/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..2286391bbe --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package task8.jvm.attr; + + +import task8.jvm.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.next2Bytes(); + int len = iter.next4Bytes(); + 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/group15/1507_977996067/src/task8/jvm/clz/AccessFlag.java b/group15/1507_977996067/src/task8/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..6b877b438b --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package task8.jvm.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/group15/1507_977996067/src/task8/jvm/clz/ClassFile.java b/group15/1507_977996067/src/task8/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..089224ffc7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/clz/ClassFile.java @@ -0,0 +1,134 @@ +package task8.jvm.clz; + +import task8.jvm.constant.ClassInfo; +import task8.jvm.constant.ConstantPool; +import task8.jvm.field.Field; +import task8.jvm.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 void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + public List getMethods() { + return methods; + } + + public void setMethods(List methods) { + this.methods = methods; + } + + 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 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 method : methods) { + int nameIndex = method.getNameIndex(); + int descriptorIndex = method.getDescriptorIndex(); + String name = getConstantPool().getUTF8String(nameIndex); + String descriptor = getConstantPool().getUTF8String(descriptorIndex); + if (methodName.equalsIgnoreCase(name) && paramAndReturnType.equalsIgnoreCase(descriptor)) { + return method; + } + } + return null; + } + + public Method getMainMethod() { + + return getMethod("main", "([Ljava/lang/String;)"); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/clz/ClassIndex.java b/group15/1507_977996067/src/task8/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..b4e6157fbb --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package task8.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group15/1507_977996067/src/task8/jvm/cmd/BiPushCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..1b3d16fab7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/BiPushCmd.java @@ -0,0 +1,29 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantPool; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.Heap; +import task8.jvm.engine.StackFrame; + + +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(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + frame.getOprandStack().push(Heap.getInstance().newInt(getOperand())); + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/ByteCodeCommand.java b/group15/1507_977996067/src/task8/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..d62ed01385 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,126 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantInfo; +import task8.jvm.constant.ConstantPool; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.StackFrame; + +import java.util.HashMap; +import java.util.Map; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static { + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + protected ByteCodeCommand(ClassFile clzFile, String opCode) { + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + protected ConstantInfo getConstantInfo(int index) { + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool() { + return this.getClassFile().getConstantPool(); + } + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + public String toString() { + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText() { + String txt = codeMap.get(opCode); + if (txt == null) { + return opCode; + } + return txt; + } + + public abstract void execute(StackFrame frame, ExecutionResult result); +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/CommandParser.java b/group15/1507_977996067/src/task8/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..6e36ac1a2f --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/CommandParser.java @@ -0,0 +1,124 @@ +package task8.jvm.cmd; + +import task8.jvm.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) { + codes = codes.toUpperCase(); + System.out.println("=========> codes: " + codes); + CommandIterator iterator = new CommandIterator(codes); + List commands = new ArrayList<>(); + while (iterator.hasNext()) { + String opCode = iterator.next2CharAsString(); + switch (opCode) { + case new_object: + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, codes); + newObjectCmd.setOprand1(iterator.next2CharAsInt()); + newObjectCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(newObjectCmd); + break; + case ldc: + LdcCmd ldcCmd = new LdcCmd(clzFile, codes); + ldcCmd.setOperand(iterator.next2CharAsInt()); + commands.add(ldcCmd); + break; + case bipush: + BiPushCmd biPushCmd = new BiPushCmd(clzFile, codes); + biPushCmd.setOperand(iterator.next2CharAsInt()); + commands.add(biPushCmd); + break; + case invokespecial: + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, codes); + invokeSpecialCmd.setOprand1(iterator.next2CharAsInt()); + invokeSpecialCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(invokeSpecialCmd); + break; + case invokevirtual: + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, codes); + invokeVirtualCmd.setOprand1(iterator.next2CharAsInt()); + invokeVirtualCmd.setOprand2(iterator.next2CharAsInt()); + commands.add(invokeVirtualCmd); + break; + default: + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, codes); + commands.add(noOperandCmd); + } + } + calcuateOffset(commands); + return commands.toArray(new ByteCodeCommand[commands.size()]); + } + + 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); + } + + } +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/GetFieldCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..ab19950a37 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,27 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantPool; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.StackFrame; + + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/GetStaticFieldCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..6c2df9be63 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,27 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantPool; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.StackFrame; + + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/InvokeSpecialCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..b7e70e50be --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,39 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantInfo; +import task8.jvm.constant.ConstantPool; +import task8.jvm.constant.MethodRefInfo; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.MethodArea; +import task8.jvm.engine.StackFrame; +import task8.jvm.method.Method; + + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo info = (MethodRefInfo) this.getConstantInfo(getIndex()); + + if ("java/lang/Object".equalsIgnoreCase(info.getClassName()) && "".equalsIgnoreCase(info.getMethodName())) { + return; + } + Method method = MethodArea.getInstance().getMethod(info); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(method); + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/InvokeVirtualCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..1541ec2524 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.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/group15/1507_977996067/src/task8/jvm/cmd/LdcCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..c080efc812 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/LdcCmd.java @@ -0,0 +1,44 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ConstantInfo; +import task8.jvm.constant.ConstantPool; +import task8.jvm.constant.StringInfo; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.Heap; +import task8.jvm.engine.JavaObject; +import task8.jvm.engine.StackFrame; + +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; + + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantInfo info = this.getConstantPool().getConstantInfo(this.getOperand()); + if (info instanceof StringInfo) { + JavaObject object = Heap.getInstance().newString(info.toString()); + frame.getOprandStack().push(object); + } else { + // ... + } + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/NewObjectCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..c79e60d451 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,32 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.ClassInfo; +import task8.jvm.constant.ConstantPool; +import task8.jvm.engine.ExecutionResult; +import task8.jvm.engine.Heap; +import task8.jvm.engine.JavaObject; +import task8.jvm.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd { + + public NewObjectCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getIndex()); + String className = classInfo.getClassName(); + JavaObject object = Heap.getInstance().newObject(className); + frame.getOprandStack().push(object); + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/cmd/NoOperandCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..a7f861f5b8 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.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/group15/1507_977996067/src/task8/jvm/cmd/OneOperandCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..5579b19d8f --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package task8.jvm.cmd; + +import task8.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/group15/1507_977996067/src/task8/jvm/cmd/PutFieldCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..3938d110b7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.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/group15/1507_977996067/src/task8/jvm/cmd/TwoOperandCmd.java b/group15/1507_977996067/src/task8/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..f05e5dd9e4 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,63 @@ +package task8.jvm.cmd; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.*; + +public abstract class TwoOperandCmd extends ByteCodeCommand { + + int oprand1 = -1; + int oprand2 = -1; + + public int getOprand1() { + return oprand1; + } + + public void setOprand1(int oprand1) { + this.oprand1 = oprand1; + } + + public void setOprand2(int oprand2) { + this.oprand2 = oprand2; + } + + public int getOprand2() { + return oprand2; + } + + public TwoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + public int getIndex(){ + int oprand1 = this.getOprand1(); + int oprand2 = this.getOprand2(); + int index = oprand1 << 8 | oprand2; + return index; + } + + protected String getOperandAsClassInfo(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); + } + + protected String getOperandAsMethod(ConstantPool pool){ + int index = getIndex(); + String codeTxt = getReadableCodeText(); + ConstantInfo constInfo = this.getConstantInfo(index); + MethodRefInfo info = (MethodRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + + protected String getOperandAsField(ConstantPool pool){ + int index = getIndex(); + + String codeTxt = getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(index); + return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); + } + public int getLength(){ + return 3; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/ClassInfo.java b/group15/1507_977996067/src/task8/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..21e6655f29 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/ClassInfo.java @@ -0,0 +1,31 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitClassInfo(this); + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/ConstantInfo.java b/group15/1507_977996067/src/task8/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a6fe00f23d --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/ConstantInfo.java @@ -0,0 +1,35 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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 abstract void accept(ConstantInfoVisitor visitor); + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/ConstantPool.java b/group15/1507_977996067/src/task8/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..4f467f53e7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/ConstantPool.java @@ -0,0 +1,37 @@ +package task8.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos; + + public ConstantPool() { + this.constantInfos = new ArrayList<>(); + } + + public ConstantPool(int size) { + this.constantInfos = new ArrayList<>(size); + + addConstantInfo(new NullConstantInfo()); + } + + 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 Object getSize() { + return this.constantInfos.size() - 1; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/FieldRefInfo.java b/group15/1507_977996067/src/task8/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..8f1b247214 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/FieldRefInfo.java @@ -0,0 +1,65 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitFieldRefInfo(this); + } + + 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(); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/MethodRefInfo.java b/group15/1507_977996067/src/task8/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..6e567ab507 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/MethodRefInfo.java @@ -0,0 +1,65 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitMethodRefInfo(this); + } + + 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(); + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/NameAndTypeInfo.java b/group15/1507_977996067/src/task8/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..1ff765a7f6 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,56 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitNameAndTypeInfo(this); + } + + + 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() + ")"; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/NullConstantInfo.java b/group15/1507_977996067/src/task8/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..b69f30c334 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/NullConstantInfo.java @@ -0,0 +1,21 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + // non impl + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/StringInfo.java b/group15/1507_977996067/src/task8/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..0fb1d53b58 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/StringInfo.java @@ -0,0 +1,35 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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; + } + + @Override + public void accept(ConstantInfoVisitor visitor) { + visitor.visitStringInfo(this); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + + public String toString() { + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/constant/UTF8Info.java b/group15/1507_977996067/src/task8/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..1587a05525 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/constant/UTF8Info.java @@ -0,0 +1,45 @@ +package task8.jvm.constant; + +import task8.jvm.print.ConstantInfoVisitor; + +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 void accept(ConstantInfoVisitor visitor) { + visitor.visitUtf8Info(this); + } + + @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; + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/ExecutionResult.java b/group15/1507_977996067/src/task8/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..01f910c52c --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/ExecutionResult.java @@ -0,0 +1,53 @@ +package task8.jvm.engine; + +import task8.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + public void setNextAction(int action) { + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame() { + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame() { + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd() { + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump() { + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/ExecutorEngine.java b/group15/1507_977996067/src/task8/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..ffcda2e803 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/ExecutorEngine.java @@ -0,0 +1,49 @@ +package task8.jvm.engine; + +import task8.jvm.method.Method; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +public class ExecutorEngine { + private Stack stack = new Stack<>(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod) { + + StackFrame frame = StackFrame.create(mainMethod); + stack.push(frame); + + while (!stack.empty()) { + StackFrame sf = stack.peek(); + ExecutionResult result = sf.execute(); + if (result.isPauseAndRunNewFrame()) { + Method nextMethod = result.getNextMethod(); + StackFrame nextMethodStackFrame = StackFrame.create(nextMethod); + nextMethodStackFrame.setCallerFrame(sf); + setupFunctionCallParams(sf, nextMethodStackFrame); + stack.push(nextMethodStackFrame); + } else stack.pop(); + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) { + Method nextMethod = nextFrame.getMethod(); + List paramList = nextMethod.getParameterList(); + List values = new ArrayList<>(); + int paramNumber = paramList.size() + 1; + while (paramNumber > 0) { + values.add(currentFrame.getOprandStack().pop()); + paramNumber--; + } + Collections.reverse(values); + nextFrame.setLocalVariableTable(values); + + } +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/Heap.java b/group15/1507_977996067/src/task8/jvm/engine/Heap.java new file mode 100644 index 0000000000..c3a551e88c --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package task8.jvm.engine; + +public class Heap { + + private Heap() { + + } + + public static Heap INSTANCE = new Heap(); + + public static Heap getInstance() { + return INSTANCE; + } + + public JavaObject newObject(String className) { + JavaObject object = new JavaObject(JavaObject.OBJECT); + object.setClassName(className); + return object; + } + + public JavaObject newString(String value) { + JavaObject object = new JavaObject(JavaObject.STRING); + object.setStringValue(value); + return object; + } + + public JavaObject newInt(int value) { + JavaObject object = new JavaObject(JavaObject.INT); + object.setIntValue(value); + return object; + } + + public JavaObject newFloat(int value) { + JavaObject object = new JavaObject(JavaObject.FLOAT); + object.setFloatValue(value); + return object; + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/JavaObject.java b/group15/1507_977996067/src/task8/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..596f3c058e --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/JavaObject.java @@ -0,0 +1,81 @@ +package task8.jvm.engine; + +import java.util.Map; +import java.util.HashMap; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue) { + fieldValues.put(fieldName, fieldValue); + } + + public JavaObject(int type) { + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setStringValue(String value) { + stringValue = value; + } + + public String getStringValue() { + return this.stringValue; + } + + public void setIntValue(int value) { + this.intValue = value; + } + + public int getIntValue() { + return this.intValue; + } + + public int getType() { + return type; + } + + public JavaObject getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public String toString() { + switch (this.getType()) { + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className + ":" + this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default: + return null; + } + } + + public String getClassName() { + return this.className; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/MethodArea.java b/group15/1507_977996067/src/task8/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..d6757f12e2 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/MethodArea.java @@ -0,0 +1,41 @@ +package task8.jvm.engine; + +import task8.jvm.clz.ClassFile; +import task8.jvm.constant.MethodRefInfo; +import task8.jvm.loader.ClassFileLoader; +import task8.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + +public class MethodArea { + + private MethodArea() { + } + + private static MethodArea INSTANCE = new MethodArea(); + + private ClassFileLoader classFileLoader; + + Map map = new HashMap<>(); + + public static MethodArea getInstance() { + return INSTANCE; + } + + public Method getMainMethod(String className) { + return classFileLoader.loadClass(className).getMainMethod(); + } + + public Method getMethod(MethodRefInfo info) { + return classFileLoader.loadClass(info.getClassName()).getMethod(info.getMethodName(), info.getParamAndReturnType()); + } + + public ClassFileLoader getClassFileLoader() { + return classFileLoader; + } + + public void setClassFileLoader(ClassFileLoader classFileLoader) { + this.classFileLoader = classFileLoader; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/MiniJVM.java b/group15/1507_977996067/src/task8/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..63250e5815 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/MiniJVM.java @@ -0,0 +1,18 @@ +package task8.jvm.engine; + +import task8.jvm.loader.ClassFileLoader; + +import java.util.Arrays; + +public class MiniJVM { + + public void run(String[] classpath, String className) throws Exception { + ClassFileLoader loader = new ClassFileLoader(); + Arrays.stream(classpath).forEach(loader::addClassPath); + MethodArea methodArea = MethodArea.getInstance(); + methodArea.setClassFileLoader(loader); + + ExecutorEngine executorEngine = new ExecutorEngine(); + executorEngine.execute(methodArea.getMainMethod(className.replaceAll("\\.", "/"))); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/engine/StackFrame.java b/group15/1507_977996067/src/task8/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..7763e0b78b --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/engine/StackFrame.java @@ -0,0 +1,106 @@ +package task8.jvm.engine; + +import task8.jvm.cmd.ByteCodeCommand; +import task8.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class StackFrame { + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + public static StackFrame create(Method m) { + + StackFrame frame = new StackFrame(m); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + public JavaObject getLocalVariableValue(int index) { + return this.localVariableTable.get(index); + } + + public Stack getOprandStack() { + return this.oprandStack; + } + + public int getNextCommandIndex(int offset) { + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for (int i = 0; i < cmds.length; i++) { + if (cmds[i].getOffset() == offset) { + return i; + } + } + throw new RuntimeException("Can't find next command"); + } + + public ExecutionResult execute() { + ByteCodeCommand[] cmds = m.getCmds(); + int length = cmds.length; + + while (index < length) { + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.RUN_NEXT_CMD); + cmds[index].execute(this, result); + + if (result.isRunNextCmd()) { + index++; + } else if (result.isExitCurrentFrame()) { + return result; + } else if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } else if (result.isJump()) { + index = getNextCommandIndex(result.getNextCmdOffset()); + } else index++; + } + return null; + + } + + + public void setLocalVariableTable(List values) { + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo) { + //问题: 为什么要这么做?? + if (this.localVariableTable.size() - 1 < index) { + for (int i = this.localVariableTable.size(); i <= index; i++) { + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod() { + return m; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/field/Field.java b/group15/1507_977996067/src/task8/jvm/field/Field.java new file mode 100644 index 0000000000..34a79aebca --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/field/Field.java @@ -0,0 +1,48 @@ +package task8.jvm.field; + + +import task8.jvm.constant.ConstantPool; +import task8.jvm.constant.UTF8Info; +import task8.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private ConstantPool pool; + + public Field(int accessFlag, int nameIndex, int descriptorIndex, ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name + ":" + desc; + } + + + public static Field parse(ConstantPool pool, ByteCodeIterator iter) { + + int accessFlag = iter.next2Bytes(); + int nameIndex = iter.next2Bytes(); + int descIndex = iter.next2Bytes(); + int attribCount = iter.next2Bytes(); + //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; + } + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task8/jvm/loader/ByteCodeIterator.java b/group15/1507_977996067/src/task8/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..cdd96f4953 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,56 @@ +package task8.jvm.loader; + +import task8.jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + + private int position; + + private byte[] bytes; + + public ByteCodeIterator(byte[] bytes) { + this.bytes = bytes; + } + + public String getMagicNumber() { + position = 0; + byte[] bytes = Arrays.copyOf(this.bytes, 4); + position += 4; + return Util.byteToHexString(bytes); + } + + public int next2Bytes() { + return nextBytes(2); + } + + public int next4Bytes() { + return nextBytes(4); + } + + public int nextFlag() { + return nextBytes(1); + } + + public void back(int length) { + position -= length; + } + + public byte[] getBytes(int length) { + byte[] bytes = Arrays.copyOfRange(this.bytes, position, position + length); + position += length; + return bytes; + } + + public String nextUxToHexString(int length) { + return new String(getBytes(length)); + } + + private int nextBytes(int size) { + byte[] bytes = Arrays.copyOfRange(this.bytes, position, position + size); + position += size; + return Util.byteToInt(bytes); + } + +} diff --git a/group15/1507_977996067/src/task8/jvm/loader/ClassFileLoader.java b/group15/1507_977996067/src/task8/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..fad8a033a7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/loader/ClassFileLoader.java @@ -0,0 +1,122 @@ +package task8.jvm.loader; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import task8.jvm.clz.ClassFile; + +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 < this.clzPaths.size(); i++) { + buffer.append(this.clzPaths.get(i)); + if (i < this.clzPaths.size() - 1) { + buffer.append(";"); + } + } + return buffer.toString(); + } + + private byte[] loadClassFile_V1(String clzFileName) { + + BufferedInputStream bis = null; + + try { + + File f = new File(clzFileName); + + + bis = new BufferedInputStream(new FileInputStream(f)); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + + byte[] buffer = new byte[1024]; + int length = -1; + + while ((length = bis.read(buffer)) != -1) { + bos.write(buffer, 0, length); + } + + byte[] codes = bos.toByteArray(); + + return codes; + + } catch (IOException e) { + e.printStackTrace(); + + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + + } + + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task8/jvm/loader/ClassFileParser.java b/group15/1507_977996067/src/task8/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..08e8ca3bfb --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/loader/ClassFileParser.java @@ -0,0 +1,112 @@ +package task8.jvm.loader; + +import task8.jvm.clz.AccessFlag; +import task8.jvm.clz.ClassFile; +import task8.jvm.clz.ClassIndex; +import task8.jvm.constant.*; +import task8.jvm.field.Field; +import task8.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +public class ClassFileParser { + + private ConstantPool constantPool; + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(codes); + System.out.println(iterator.getMagicNumber()); + + classFile.setMinorVersion(iterator.next2Bytes()); + classFile.setMajorVersion(iterator.next2Bytes()); + + parseConstantPool(iterator); + classFile.setConstPool(constantPool); + classFile.setAccessFlag(parseAccessFlag(iterator)); + classFile.setClassIndex(parseClassIndex(iterator));//task5 over + + iterator.next2Bytes(); // interface + + classFile.setFields(parseFileds(iterator)); + classFile.setMethods(parseMethods(classFile, iterator));//task6 over + return classFile; + } + + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.next2Bytes()); + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex clazIndex = new ClassIndex(); + clazIndex.setThisClassIndex(iter.next2Bytes()); + clazIndex.setSuperClassIndex(iter.next2Bytes()); + return clazIndex; + } + + private void parseConstantPool(ByteCodeIterator iter) { + int poolCount = iter.next2Bytes(); + ConstantPool pool = new ConstantPool(poolCount); + for (int i = 0; i < poolCount; i++) { + int tag = iter.nextFlag(); + if (tag == ConstantInfo.UTF8_INFO) { //utf-8 + int length = iter.next2Bytes(); + byte[] bytes = iter.getBytes(length); + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setValue(new String(bytes)); + utf8Info.setLength(length); + pool.addConstantInfo(utf8Info); + } else if (tag == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.next2Bytes()); + pool.addConstantInfo(stringInfo); + } else if (tag == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.next2Bytes()); + pool.addConstantInfo(classInfo); + } else if (tag == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.next2Bytes()); + fieldRefInfo.setNameAndTypeIndex(iter.next2Bytes()); + pool.addConstantInfo(fieldRefInfo); + } else if (tag == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.next2Bytes()); + methodRefInfo.setNameAndTypeIndex(iter.next2Bytes()); + pool.addConstantInfo(methodRefInfo); + } else if (tag == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.next2Bytes()); + nameAndTypeInfo.setIndex2(iter.next2Bytes()); + pool.addConstantInfo(nameAndTypeInfo); + } + } + this.constantPool = pool; + } + + private List parseFileds(ByteCodeIterator iter) { + int fieldCount = iter.next2Bytes(); + + List fieldList = new ArrayList<>(fieldCount); + + for (int i = 0; i < fieldCount; i++) { + Field f = Field.parse(constantPool, iter); + fieldList.add(f); + } + return fieldList; + } + + private List parseMethods(ClassFile classFile, ByteCodeIterator iter) { + int methodCount = iter.next2Bytes(); + + List methodList = new ArrayList<>(methodCount); + + for (int i = 0; i < methodCount; i++) { + Method m = Method.parse(classFile, iter); + methodList.add(m); + } + return methodList; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/method/Method.java b/group15/1507_977996067/src/task8/jvm/method/Method.java new file mode 100644 index 0000000000..049c6d6d3e --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/method/Method.java @@ -0,0 +1,107 @@ +package task8.jvm.method; + +import task8.jvm.attr.AttributeInfo; +import task8.jvm.attr.CodeAttr; +import task8.jvm.clz.ClassFile; +import task8.jvm.cmd.ByteCodeCommand; +import task8.jvm.constant.ConstantPool; +import task8.jvm.constant.UTF8Info; +import task8.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class Method { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + public Method(ClassFile clzFile, int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info) pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info) pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + int accessFlag = iter.next2Bytes(); + int nameIndex = iter.next2Bytes(); + int descIndex = iter.next2Bytes(); + int attribCount = iter.next2Bytes(); + + + Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); + + for (int j = 1; j <= attribCount; j++) { + + int attrNameIndex = iter.next2Bytes(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); + + if (AttributeInfo.CODE.equalsIgnoreCase(attrName)) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("only CODE attribute is implemented , please implement the " + attrName); + } + } + return m; + } + + public List getParameterList() { + String paramType = ((UTF8Info) getClzFile().getConstantPool().getConstantInfo(getDescriptorIndex())).getValue(); + String param = paramType.substring(paramType.indexOf("("), paramType.lastIndexOf(")")); + List paramList = new ArrayList<>(); + while (!"".equalsIgnoreCase(param)) { + String params = param.substring(0, param.indexOf("L")); + paramList.add(params); + } + return paramList; + } + + public ByteCodeCommand[] getCmds() { + return new ByteCodeCommand[0]; + } +} diff --git a/group15/1507_977996067/src/task8/jvm/print/ClassFilePrinter.java b/group15/1507_977996067/src/task8/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..3e564b3be7 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/print/ClassFilePrinter.java @@ -0,0 +1,44 @@ +package task8.jvm.print; + +import task8.jvm.clz.ClassFile; +import task8.jvm.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 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "com.coderising.jvm.test.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitor.java b/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitor.java new file mode 100644 index 0000000000..00995c04d3 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitor.java @@ -0,0 +1,18 @@ +package task8.jvm.print; + +import task8.jvm.constant.*; + +public interface ConstantInfoVisitor { + + void visitClassInfo(ClassInfo classInfo); + + void visitFieldRefInfo(FieldRefInfo fieldRefInfo); + + void visitMethodRefInfo(MethodRefInfo methodRefInfo); + + void visitNameAndTypeInfo(NameAndTypeInfo nameAndTypeInfo); + + void visitStringInfo(StringInfo stringInfo); + + void visitUtf8Info(UTF8Info utf8Info); +} diff --git a/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitorImpl.java b/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitorImpl.java new file mode 100644 index 0000000000..57938f9cff --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/print/ConstantInfoVisitorImpl.java @@ -0,0 +1,51 @@ +package task8.jvm.print; + +import task8.jvm.constant.*; + +public class ConstantInfoVisitorImpl implements ConstantInfoVisitor { + @Override + public void visitClassInfo(ClassInfo classInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("Class\t#").append(classInfo.getUtf8Index()).append("\t").append(classInfo.getClassName()); + System.out.println(sb); + } + + @Override + public void visitFieldRefInfo(FieldRefInfo fieldRefInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("FieldRef\t#").append(fieldRefInfo.getClassInfoIndex()).append("\t").append(fieldRefInfo.getFieldName()); + System.out.println(sb); + + } + + @Override + public void visitMethodRefInfo(MethodRefInfo methodRefInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("MethodRef\t#").append(methodRefInfo.getMethodName()); + System.out.println(sb); + } + + @Override + public void visitNameAndTypeInfo(NameAndTypeInfo nameAndTypeInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("NameAndType\t#").append(nameAndTypeInfo.getName()).append("\t") + .append(nameAndTypeInfo.getIndex1()).append("\t") + .append(nameAndTypeInfo.getIndex2()).append("\t") + .append(nameAndTypeInfo.getTypeInfo()); + System.out.println(sb); + } + + @Override + public void visitStringInfo(StringInfo stringInfo) { + StringBuilder sb = new StringBuilder(); + sb.append("String\t#").append(stringInfo.getIndex()); + System.out.println(sb); + } + + @Override + public void visitUtf8Info(UTF8Info utf8Info) { + StringBuilder sb = new StringBuilder(); + sb.append("UTF8\t#").append(utf8Info.getValue()); + System.out.println(sb); + } +} diff --git a/group15/1507_977996067/src/task8/jvm/print/ConstantPoolPrinter.java b/group15/1507_977996067/src/task8/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..9d3437d40b --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,26 @@ +package task8.jvm.print; + +import task8.jvm.constant.ConstantInfo; +import task8.jvm.constant.ConstantPool; + +public class ConstantPoolPrinter { + + private ConstantPool pool; + + ConstantPoolPrinter(ConstantPool pool) { + this.pool = pool; + } + + public void print() { + + System.out.println("Constant Pool:"); + + ConstantInfoVisitor visitor = new ConstantInfoVisitorImpl(); + int size = (int) pool.getSize(); + for (int i = 0; i < size; i++) { + System.out.print("#" + i + "= "); + ConstantInfo constantInfo = pool.getConstantInfo(i); + constantInfo.accept(visitor); + } + } +} diff --git a/group15/1507_977996067/src/task8/jvm/test/ClassFileloaderTest.java b/group15/1507_977996067/src/task8/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..dc7a01b23f --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,191 @@ +package task8.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import task8.jvm.clz.ClassFile; +import task8.jvm.clz.ClassIndex; +import task8.jvm.constant.*; +import task8.jvm.loader.ClassFileLoader; + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "EmployeeV1"; + + static String path1 = "E:\\Idea\\coding2017\\group15\\1507_977996067\\out\\task5\\jvm\\test"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "EmployeeV1"; + + clzFile = loader.loadClass(className); +// clzFile.print(); + } + + + @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 = "EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1038, byteCodes.length); + + } + + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + String actualValue = this.byteToHexString(codes); + + Assert.assertEquals("cafebabe", actualValue); + } + + + private String byteToHexString(byte[] codes) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < codes.length; i++) { + byte b = codes[i]; + int value = b & 0xFF; + String strHex = Integer.toHexString(value); + if (strHex.length() < 2) { + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } + + /** + * ---------------------------------------------------------------------- + */ + + + @Test + public void testVersion() { + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool() { + + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getSize()); + + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(1); + Assert.assertEquals(2, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(2); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(3); + Assert.assertEquals(4, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(4); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(5); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(6); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(7); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(8); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(9); + Assert.assertEquals("", 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()); + } + + +} diff --git a/group15/1507_977996067/src/task8/jvm/test/EmployeeV1.java b/group15/1507_977996067/src/task8/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..f3a0755de5 --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +package task8.jvm.test; + +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/group15/1507_977996067/src/task8/jvm/util/Util.java b/group15/1507_977996067/src/task8/jvm/util/Util.java new file mode 100644 index 0000000000..6b13997e4b --- /dev/null +++ b/group15/1507_977996067/src/task8/jvm/util/Util.java @@ -0,0 +1,23 @@ +package task8.jvm.util; + +public class Util { + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.valueOf(s1, 16); + } + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData; + + private int size; + //队头 读开始的位置 + private int front = 0; + //队尾 写开始的位置 + private int rear = 0; + + public CircleQueue() { + elementData = new Object[DEFAULT_SIZE]; + size = DEFAULT_SIZE; + } + + public CircleQueue(int size) { + this.size = size; + elementData = new Object[size]; + } + + public boolean isEmpty() { + return front == rear; + } + + public int size() { + if (isEmpty()) { + return 0; + } + return rear > front ? rear - front : size - (front - rear); + } + + + public void enQueue(E data) { + int rearPosition = rear; + elementData[rearPosition++] = data; + rear = rearPosition % size; + } + + public E deQueue() { + if (isEmpty()) { + return null; + } + int frontPosition = front; + E dataToDeQueue = (E) elementData[frontPosition--]; + front = frontPosition < 0 ? frontPosition + size : frontPosition; + return dataToDeQueue; + } +} diff --git a/group15/1507_977996067/src/task8/queue/Josephus.java b/group15/1507_977996067/src/task8/queue/Josephus.java new file mode 100644 index 0000000000..1a01cb0018 --- /dev/null +++ b/group15/1507_977996067/src/task8/queue/Josephus.java @@ -0,0 +1,28 @@ +package task8.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 约瑟夫环 + */ +public class Josephus { + + public static List execute(int n, int m) { + + CircleQueue queue = new CircleQueue<>(n); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + + List resultList = new ArrayList<>(n); + int flag = 0; + while (!queue.isEmpty()) { + flag++; + if (flag % m == 0) { + resultList.add(queue.deQueue()); + } + } + return resultList; + } +} diff --git a/group15/1507_977996067/src/task8/queue/QueueWithTwoStacks.java b/group15/1507_977996067/src/task8/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..6a67fef0e8 --- /dev/null +++ b/group15/1507_977996067/src/task8/queue/QueueWithTwoStacks.java @@ -0,0 +1,41 @@ +package task8.queue; + +import java.util.Stack; + +public class QueueWithTwoStacks { + + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack<>(); + stack2 = new Stack<>(); + } + + + public boolean isEmpty() { + return stack1.isEmpty(); + } + + + public int size() { + return stack1.size(); + } + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + E itemToPop = stack2.pop(); + while (!stack2.isEmpty()) { + stack1.push(stack2.pop()); + } + return itemToPop; + } +} diff --git a/group15/1507_977996067/src/task9/stack/QuickMinStack.java b/group15/1507_977996067/src/task9/stack/QuickMinStack.java new file mode 100644 index 0000000000..22dc3640a4 --- /dev/null +++ b/group15/1507_977996067/src/task9/stack/QuickMinStack.java @@ -0,0 +1,28 @@ +package task9.stack; + +import java.util.*; + +public class QuickMinStack> { + + private List magicList = new ArrayList<>(); + + private Stack dataStack = new Stack<>(); + + public void push(T data) { + dataStack.push(data); + magicList.add(data); + magicList.sort(Comparator.naturalOrder()); + } + + public T pop() { + T result = dataStack.pop(); + magicList.remove(result); + return result; + } + + public T findMin() { + T minResult = magicList.get(0); + dataStack.remove(minResult); // sad + return minResult; + } +} diff --git a/group15/1507_977996067/src/task9/stack/StackWithTwoQueue.java b/group15/1507_977996067/src/task9/stack/StackWithTwoQueue.java new file mode 100644 index 0000000000..51532056a0 --- /dev/null +++ b/group15/1507_977996067/src/task9/stack/StackWithTwoQueue.java @@ -0,0 +1,25 @@ +package task9.stack; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class StackWithTwoQueue { + + private Queue queue1 = new ArrayDeque<>(); + private Queue queue2 = new ArrayDeque<>(); + + public void push(T data) { + queue1.add(data); + } + + public T pop() { + while (!queue1.isEmpty()) { + queue2.add(queue1.poll()); + } + T result = queue2.poll(); + while (!queue2.isEmpty()) { + queue1.add(queue2.poll()); + } + return result; + } +} diff --git a/group15/1507_977996067/src/task9/stack/TwoStackInOneArray.java b/group15/1507_977996067/src/task9/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..578c696bb1 --- /dev/null +++ b/group15/1507_977996067/src/task9/stack/TwoStackInOneArray.java @@ -0,0 +1,106 @@ +package task9.stack; + +import java.util.Objects; + +public class TwoStackInOneArray { + + private static final String INDEX_EXCEPTION_MSG = "数组越界了"; + private static final int DEFAULT_SIZE = 10; + + private Object[] data; + + private int length = DEFAULT_SIZE; + + public TwoStackInOneArray() { + data = new Object[length]; + } + + public TwoStackInOneArray(int size) { + this.length = size; + data = new Object[length]; + } + + private int leftSize = 0; + private int rightSize = 0; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + checkIndexRange(); + data[leftSize++] = o; + } + + private void checkIndexRange() { + if (leftSize + rightSize > length) { + throw new RuntimeException(INDEX_EXCEPTION_MSG); + } + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if (leftSize <= 0) { + throw new RuntimeException(INDEX_EXCEPTION_MSG); + } + Object result = data[0]; + Object[] temp = new Object[length]; + System.arraycopy(data, 1, temp, 0, leftSize - 1); + System.arraycopy(data, length - rightSize, temp, length - rightSize, rightSize); + data = temp; + leftSize--; + return result; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return data[0]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + checkIndexRange(); + data[length - rightSize - 1] = o; + rightSize++; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (rightSize <= 0) { + throw new RuntimeException(INDEX_EXCEPTION_MSG); + } + Object result = data[length - 1]; + Object[] temp = new Object[length]; + System.arraycopy(data, 0, temp, 0, leftSize); + System.arraycopy(data, length - rightSize, temp, length - rightSize + 1, rightSize - 1); + data = temp; + leftSize--; + return result; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + return data[length - 1]; + } +} diff --git a/group19/1294642551/src/LRU/LRUPageFrame.java b/group19/1294642551/src/LRU/LRUPageFrame.java new file mode 100644 index 0000000000..f2419e0278 --- /dev/null +++ b/group19/1294642551/src/LRU/LRUPageFrame.java @@ -0,0 +1,142 @@ +package LRU; + +/** + * 使用双向链表实现LRU算法 + * @author 12946 + * + */ + +public class LRUPageFrame { + + private static class Node { + + Node prev = null; + Node next = null; + int pageNum; + + Node(Object data) { + if(data != null){ + this.pageNum = (Integer)data; + } + } + } + + private int capacity;//链表总元素个数 + private int currentSize;//链表当前元素个数 + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + first = new Node(null);//栈底,元素最先放入的地方 + last = new Node(null);//栈顶 + + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + Node newNode = new Node(pageNum); + + if(currentSize == capacity){ + Node tempNode = null; + if(getIndex(pageNum) == -1){//不包含 + tempNode = first.next; + }else{//包含 + tempNode = getNode(pageNum); + } + (tempNode.prev).next = tempNode.next; + (tempNode.next).prev = tempNode.prev; + + + newNode.next = last; + newNode.prev = last.prev; + last.prev = newNode; + newNode.prev.next = newNode; + } + + if(currentSize < capacity){ + Node point = first; + for(int i = 0; i < currentSize; i++){ + point = point.next; + } + point.next = newNode; + newNode.prev = point; + + newNode.next = last; + last.prev = newNode; + + currentSize += 1; + } + + + } + + public Node getNode(int data){ + + Node point = first.next; + for(int i = 0; i < capacity; i++){ + if(point.pageNum == data){ + return point; + } + point = point.next; + } + + return null; + + } + + + public int getIndex(int data){ + Node point = first.next; + for(int i = 0; i < capacity; i++){ + if(point.pageNum == data){ + return i; + } + point = point.next; + } + + return -1; + } + +// 原toString +// 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(); +// } + + public String toString(){ + StringBuilder sb = new StringBuilder(); + Node point = last.prev; + while(point != first){ + sb.append(point.pageNum); + if(point.prev != first){ + sb.append(","); + } + point = point.prev; + } + + return sb.toString(); + + } + + + +} diff --git a/group19/1294642551/src/data_Structure_Utils/ArrayUtil.java b/group19/1294642551/src/data_Structure_Utils/ArrayUtil.java new file mode 100644 index 0000000000..5138f7e402 --- /dev/null +++ b/group19/1294642551/src/data_Structure_Utils/ArrayUtil.java @@ -0,0 +1,271 @@ +package data_Structure_Utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.TreeSet; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin){ + + if(origin == null || origin.length == 0){ + return; + } + int len = origin.length; + for(int i = 0; i < len/2; i++){ + int temp = origin[i]; + origin[i] = origin[len-1-i]; + origin[len-1-i] = temp; + } + + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray){ + if(oldArray == null){ + return null; + } + + ArrayList al = new ArrayList(); + int len = oldArray.length; + for(int i = 0; i < len; i++) + { + if(oldArray[i] != 0) + { + al.add(oldArray[i]); + } + } + + int arrLen = al.size(); + int[] arr = new int[arrLen]; + for(int i = 0; i < arrLen; i++) + { + arr[i] = al.get(i); + } + + return arr; + + + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + if(array1 == null){ + return array2; + } + if(array2 == null){ + return array1; + } + + TreeSet tr = new TreeSet(); + for(int i = 0; i < array1.length; i++) + { + tr.add(array1[i]); + } + for(int j = 0; j < array2.length; j++) + { + tr.add(array2[j]); + } + + int arrLen = tr.size(); + int[] arr = new int[arrLen]; + int index = 0; + + Iterator it = tr.iterator(); + while(it.hasNext()) + { + arr[index] = (Integer) it.next(); + index++; + } + + return arr; + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + if(oldArray == null){ + return null; + } + if(size<0){ + throw new IndexOutOfBoundsException("size < 0"); + } + int[] newArray = new int[oldArray.length + size]; + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); + return newArray; + + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + if(max == 1){ + return new int[0]; + } + if(max == 2){ + return new int[]{1, 1}; + } + + int[] arr = new int[max];//分配了多的空间,后面需要做数组拷贝 + arr[0] = 1; + arr[1] = 2; + int count = 2;//已经有两个元素了 + for(int i = 2; i < max; i++){ + arr[i] = arr[i-2] + arr[i-1]; + if(arr[i] >= max){ + break; + } + count++; + } + + return Arrays.copyOf(arr, count); + + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + + if(max < 3){ + return new int[0]; + } + + int[] arr = new int[max]; + int count = 0; + for(int n = 2; n < max; n++){ + if(isPrime(n)){ + arr[count++] = n; + } + } + + + return Arrays.copyOf(arr, count); + + } + + // 判断某个数是否是素数 + private boolean isPrime(int n){ + int i = 2; + while(i < n){ + if(n % i != 0){ + i++; + }else{ + break; + } + } + return i == n; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + if (max <= 0) { + return null; + } + int[] array = new int[max]; + int count = 0; + + for(int n = 2; n < max; n++){ + int sum = 0;//记录所有真因子之和 + for(int i = 1; i < n; i++){ + if(n%i == 0){ + sum += i; + } + } + if(sum == n){ + array[count++] = n; + } + } + + return Arrays.copyOf(array, count); + } + +// public boolean isPerfectNumber(int number) +// { +// ArrayList al = new ArrayList(); +// +// for(int i = 1; i < number; i++) +// { +// if(number % i == 0) +// al.add(i); +// } +// +// int value = 0; +// for(int j = 0; j < al.size(); j++) +// { +// value = value + al.get(j); +// } +// +// return value == number; +// } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator){ + + if(array == null){ + return null; + } + if(array.length == 0){ + return ""; + } + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < array.length; i++){ + sb.append(array[i]); + if(i < array.length -1){ + sb.append(seperator); + } + } + return sb.toString(); + } + + + +} diff --git a/group19/1294642551/src/download/DownloadThread.java b/group19/1294642551/src/download/DownloadThread.java new file mode 100644 index 0000000000..aebd8932f0 --- /dev/null +++ b/group19/1294642551/src/download/DownloadThread.java @@ -0,0 +1,43 @@ +package download; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + CyclicBarrier barrier; + String localFile; + + public DownloadThread( Connection conn, int startPos, int endPos,String localFile, CyclicBarrier barrier){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.localFile = localFile; + this.barrier = barrier; + } + + + public void run(){ + try { + System.out.println("Begin to read [" + startPos +"-"+endPos+"]"); + // 每个线程都有一个RandomAccessFile,这样多线程下载的时候不会出现冲突 + RandomAccessFile raf = new RandomAccessFile(localFile, "rw"); + byte[] data = conn.read(startPos, endPos); + raf.seek(startPos); + raf.write(data); + raf.close(); + conn.close(); + barrier.await();//等待别的线程完成 + + } catch (Exception e) { + e.printStackTrace(); + } + + } +} diff --git a/group19/1294642551/src/download/FileDownloader.java b/group19/1294642551/src/download/FileDownloader.java new file mode 100644 index 0000000000..6d7096c644 --- /dev/null +++ b/group19/1294642551/src/download/FileDownloader.java @@ -0,0 +1,120 @@ +package download; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; +import download.api.DownloadListener; + + +public class FileDownloader { + + private String url; + private String localFile; + private static final int DOWNLOAD_THREAD_NUM = 3;//下载线程的个数 + + DownloadListener listener; + ConnectionManager cm;//管理Connection + + public FileDownloader(String _url, String localFile) { + this.url = _url; + this.localFile = localFile; + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + + // 栅栏类:第一个参数表示线程的个数; + // 第二个参数表示等所有的线程执行完成之后,再调用的线程 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_THREAD_NUM, new Runnable(){ + + @Override + public void run() { + listener.notifyFinished(); + }}); + + Connection conn = null; + try { + + conn = cm.open(this.url); + int length = conn.getContentLength(); + createPlaceHolderFile(localFile, length); + int[][] ranges = allocateDownloadRange(DOWNLOAD_THREAD_NUM, length); + for(int i = 0; i < DOWNLOAD_THREAD_NUM; i++){ + int startPos = ranges[i][0]; + int endPos = ranges[i][1]; + DownloadThread thread = new DownloadThread(cm.open(url), startPos, endPos, localFile, barrier); + thread.start(); + } + + } catch (ConnectionException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + } + + // 在下载之前,根据文件的额大小,先在硬盘中占据一个地方,以免空间不够用 + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException{ + // 随机读写文件的类 + RandomAccessFile raf = new RandomAccessFile(fileName, "rw"); + for(int i = 0; i < contentLen; i++){ + raf.write(i); + } + raf.close(); + + } + + private int[][] allocateDownloadRange(int threadNum, int contentLen){ + int[][] ranges = new int[threadNum][2]; + int eachThreadSize = contentLen / threadNum; + int left = contentLen % threadNum; + for(int i = 0; i < threadNum; i++){ + int startPos = i * eachThreadSize; + int endPos = (i+1) * eachThreadSize - 1; + + if(i == (threadNum - 1)){ + endPos += left; + } + + ranges[i][0] = startPos; + ranges[i][1] = endPos; + } + return ranges; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group19/1294642551/src/download/api/Connection.java b/group19/1294642551/src/download/api/Connection.java new file mode 100644 index 0000000000..1a467a8086 --- /dev/null +++ b/group19/1294642551/src/download/api/Connection.java @@ -0,0 +1,23 @@ +package download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group19/1294642551/src/download/api/ConnectionException.java b/group19/1294642551/src/download/api/ConnectionException.java new file mode 100644 index 0000000000..8af122abf4 --- /dev/null +++ b/group19/1294642551/src/download/api/ConnectionException.java @@ -0,0 +1,10 @@ +package download.api; + + +public class ConnectionException extends Exception { + + public ConnectionException(Exception e) { + super(e); + } + +} diff --git a/group19/1294642551/src/download/api/ConnectionManager.java b/group19/1294642551/src/download/api/ConnectionManager.java new file mode 100644 index 0000000000..1519ebb787 --- /dev/null +++ b/group19/1294642551/src/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group19/1294642551/src/download/api/DownloadListener.java b/group19/1294642551/src/download/api/DownloadListener.java new file mode 100644 index 0000000000..4119e46144 --- /dev/null +++ b/group19/1294642551/src/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group19/1294642551/src/download/impl/ConnectionImpl.java b/group19/1294642551/src/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..c12669d1e2 --- /dev/null +++ b/group19/1294642551/src/download/impl/ConnectionImpl.java @@ -0,0 +1,79 @@ +package download.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; + +import download.api.Connection; +import download.api.ConnectionException; + +/** + * ConnectionImpl这个类不是public,是省略的,只在impl这个包中可见 + * @author 12946 + * + */ +class ConnectionImpl implements Connection{ + + URL url; + static final int BUFFER_SIZE = 1024; + + public ConnectionImpl(String url) throws ConnectionException { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + throw new ConnectionException(e); + } + + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + httpConn.setRequestProperty("Range", "bytes="+startPos+"-"+endPos); + InputStream input = httpConn.getInputStream(); +// input.skip(startPos); + byte[] buff = new byte[BUFFER_SIZE]; + int totalLen = endPos - startPos + 1; + //内存中的输出流,我们可以往这个内存中的输出流写东西 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while(baos.size() < totalLen){ + int len = input.read(buff);//input输入流read的数据放到buff中 + if(len < 0){ + break; + } + baos.write(buff, 0, len); + } + + if(baos.size() > totalLen){//最后一次写入baos时,可能会写入多的数据 + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + + return baos.toByteArray(); + + } + + @Override + public int getContentLength() { + try { + URLConnection httpConn = url.openConnection(); + return httpConn.getContentLength(); + } catch (IOException e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + + } + +} diff --git a/group19/1294642551/src/download/impl/ConnectionManagerImpl.java b/group19/1294642551/src/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..774ae688a4 --- /dev/null +++ b/group19/1294642551/src/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,18 @@ +package download.impl; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + /** + * 返回的是Connection接口 + */ + @Override + public Connection open(String url) throws ConnectionException { + + return new ConnectionImpl(url); + } + +} diff --git a/group19/1294642551/src/expr/InfixExpr.java b/group19/1294642551/src/expr/InfixExpr.java new file mode 100644 index 0000000000..11970962bc --- /dev/null +++ b/group19/1294642551/src/expr/InfixExpr.java @@ -0,0 +1,69 @@ +package expr; + +import java.util.List; +import java.util.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + + } + + public float evaluate() { + List tokenList = TokenParser.parse(expr); + Stack operatorStack = new Stack(); + Stack valueStack = new Stack(); + + for(int i = 0; i < tokenList.size(); i++){ + Token token = tokenList.get(i); + if(token.isOperator()){//新元素是操作符 + if(operatorStack.isEmpty()){ + operatorStack.push(token); + }else{ + while(!operatorStack.isEmpty() && !token.hasHigherPriority(operatorStack.peek())){ + popCompute(operatorStack, valueStack); + } + operatorStack.push(token); + } + }else{//新元素是数值 + valueStack.push(token); + } + + + } + + while(!operatorStack.isEmpty()){ + popCompute(operatorStack, valueStack); + } + + + return valueStack.peek().getFloatValue(); + } + + // 计算加减乘除的结果 + public float compute(float num1, float num2, String operator){ + if(operator.equals("+")){ + return num1 + num2; + }else if(operator.equals("-")){ + return num1 - num2; + }else if(operator.equals("*")){ + return num1 * num2; + }else{ + return num1 / num2; + } + } + + // 弹栈计算,取一个操作符和两个操作数进行计算,并将得到的操作数压入数值栈 + public void popCompute(Stack operatorStack, Stack valueStack){ + float num2 = valueStack.pop().getFloatValue(); + float num1 = valueStack.pop().getFloatValue(); + String operator = operatorStack.pop().getOperator(); + float value = compute(num1, num2, operator); + valueStack.push(new Token(1, String.valueOf(value))); + + } + + +} diff --git a/group19/1294642551/src/expr/InfixToPostfix.java b/group19/1294642551/src/expr/InfixToPostfix.java new file mode 100644 index 0000000000..24be56412c --- /dev/null +++ b/group19/1294642551/src/expr/InfixToPostfix.java @@ -0,0 +1,47 @@ +package expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + List inList = TokenParser.parse(expr); + List postList = new ArrayList(); + Stack operatorStack = new Stack(); + for(int i = 0; i < inList.size(); i++){ + Token token = inList.get(i); + if(token.isOperator()){ + while(!operatorStack.isEmpty() && !token.hasHigherPriority(operatorStack.peek())){ + postList.add(operatorStack.pop()); + } + operatorStack.add(token); + + }else{ + postList.add(token); + } + } + + while(!operatorStack.isEmpty()){ + postList.add(operatorStack.pop()); + } + + + return postList; + } + + public static String toString(List tokenList){ + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < tokenList.size(); i++){ + sb.append(tokenList.get(i).getValue()); + if(i < tokenList.size()-1){ + sb.append(" "); + } + } + return sb.toString(); + } + + + +} diff --git a/group19/1294642551/src/expr/PostfixExpr.java b/group19/1294642551/src/expr/PostfixExpr.java new file mode 100644 index 0000000000..1fb335fc9f --- /dev/null +++ b/group19/1294642551/src/expr/PostfixExpr.java @@ -0,0 +1,55 @@ +package expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List tokenList = TokenParser.parse(expr); + Stack operatorStack = new Stack(); + Stack valueStack = new Stack(); + for(int i = 0; i < tokenList.size(); i++){ + Token token = tokenList.get(i); + if(token.isOperator()){ + operatorStack.push(token); + popCompute(operatorStack, valueStack); + }else{ + valueStack.push(token); + } + + } + + return valueStack.peek().getFloatValue(); + } + + // 计算加减乘除的结果 + public float compute(float num1, float num2, String operator){ + if(operator.equals("+")){ + return num1 + num2; + }else if(operator.equals("-")){ + return num1 - num2; + }else if(operator.equals("*")){ + return num1 * num2; + }else{ + return num1 / num2; + } + } + + // 弹栈计算,取一个操作符和两个操作数进行计算,并将得到的操作数压入数值栈 + public void popCompute(Stack operatorStack, Stack valueStack){ + float num2 = valueStack.pop().getFloatValue(); + float num1 = valueStack.pop().getFloatValue(); + String operator = operatorStack.pop().getOperator(); + float value = compute(num1, num2, operator); + valueStack.push(new Token(1, String.valueOf(value))); + + } + + +} diff --git a/group19/1294642551/src/expr/PrefixExpr.java b/group19/1294642551/src/expr/PrefixExpr.java new file mode 100644 index 0000000000..4afda30732 --- /dev/null +++ b/group19/1294642551/src/expr/PrefixExpr.java @@ -0,0 +1,69 @@ +package expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + List tokenList = TokenParser.parse(expr); + tokenList = reverse(tokenList); + Stack operatorStack = new Stack(); + Stack valueStack = new Stack(); + for(int i = 0; i < tokenList.size(); i++){ + Token token = tokenList.get(i); + if(token.isOperator()){ + operatorStack.push(token); + popCompute(operatorStack, valueStack); + }else{ + valueStack.push(token); + } + + } + + return valueStack.peek().getFloatValue(); + } + + public List reverse(List tokenList){ + List newList = new ArrayList(); + int size = tokenList.size(); + for(int i = 0; i < size; i++){ + newList.add(tokenList.get(size - 1 - i)); + } + return newList; + } + + // 计算加减乘除的结果 + public float compute(float num1, float num2, String operator){ + if(operator.equals("+")){ + return num1 + num2; + }else if(operator.equals("-")){ + return num1 - num2; + }else if(operator.equals("*")){ + return num1 * num2; + }else{ + return num1 / num2; + } + } + + // 弹栈计算,取一个操作符和两个操作数进行计算,并将得到的操作数压入数值栈 + // 注:在前缀表达式的计算中交换了第一个操作数和第二个操作数的位置,因为前缀表示式是从后向前遍历的 + public void popCompute(Stack operatorStack, Stack valueStack){ + float num2 = valueStack.pop().getFloatValue(); + float num1 = valueStack.pop().getFloatValue(); + String operator = operatorStack.pop().getOperator(); + float value = compute(num2, num1, operator);//交换了操作数的位置 + valueStack.push(new Token(1, String.valueOf(value))); + + } + + + +} diff --git a/group19/1294642551/src/expr/Token.java b/group19/1294642551/src/expr/Token.java new file mode 100644 index 0000000000..130aea44a3 --- /dev/null +++ b/group19/1294642551/src/expr/Token.java @@ -0,0 +1,62 @@ +package 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + public float getFloatValue(){ + return Float.valueOf(value); + } + + public String getValue(){ + return value; + } + + public String getOperator(){ + return 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/group19/1294642551/src/expr/TokenParser.java b/group19/1294642551/src/expr/TokenParser.java new file mode 100644 index 0000000000..110bdb1702 --- /dev/null +++ b/group19/1294642551/src/expr/TokenParser.java @@ -0,0 +1,57 @@ +package 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{ +// 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); + } +} diff --git a/group19/1294642551/src/jvm/attr/CodeAttr.java b/group19/1294642551/src/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e3dde08c77 --- /dev/null +++ b/group19/1294642551/src/jvm/attr/CodeAttr.java @@ -0,0 +1,111 @@ +package jvm.attr; + +import java.util.Arrays; + +import jvm.clz.ClassFile; +import jvm.cmd.ByteCodeCommand; +import jvm.cmd.CommandParser; +import jvm.constant.ConstantPool; +import jvm.loader.ByteCodeIterator; + + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + private ByteCodeCommand[] cmds ; + + public String getCode() { + return code; + } + + public ByteCodeCommand[] getCmds() { + return cmds; + } + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code, ByteCodeCommand[] cmds) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + iter.back(2); + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + String code = iter.nextUxToHexString(codeLen); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); +// System.out.println(Arrays.toString(cmds)); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, cmds); + + int exceptionLen = iter.nextU2ToInt(); + if(exceptionLen>0){ + String exTable = iter.nextUxToHexString(exceptionLen); + System.out.println("Encountered exception table , just ignore it :" + exTable); + + } + + int childAttrLen = iter.nextU2ToInt(); + + + for(int i = 0; i < childAttrLen; i++){ + int childAttrNameIndex = iter.nextU2ToInt(); + String childAttrName = clzFile.getConstantPool().getUTF8String(childAttrNameIndex); + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(childAttrName)){ + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + }else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(childAttrName)){ + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + }else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(childAttrName)){ + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + }else{ + throw new RuntimeException("code 的子属性 "+ childAttrName+"没有解析"); + } + } + return codeAttr; + } + + + public String toString(ConstantPool pool){ + StringBuilder buffer = new StringBuilder(); + 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(ByteCodeIterator iter){ + iter.back(2); + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLen); + + int itemLen = iter.nextU2ToInt(); + for(int i = 0; i < itemLen; i++){ + LineNumberItem item = new LineNumberItem(); + int startPC = iter.nextU2ToInt(); + int lineNumber = iter.nextU2ToInt(); + item.setStartPC(startPC); + item.setLineNum(lineNumber); + + lineNumberTable.addLineNumberItem(item); + + } + + return lineNumberTable; + } + + 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/group19/1294642551/src/jvm/attr/LocalVariableItem.java b/group19/1294642551/src/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..96dde8a0d2 --- /dev/null +++ b/group19/1294642551/src/jvm/attr/LocalVariableItem.java @@ -0,0 +1,52 @@ +package jvm.attr; + +public class LocalVariableItem { + private int startPC; + private int length; + private int nameIndex; + private int descIndex; + private int index; + + + + public LocalVariableItem(int startPC, int length, int nameIndex, + int descIndex, int index) { + super(); + this.startPC = startPC; + this.length = length; + this.nameIndex = nameIndex; + this.descIndex = descIndex; + this.index = 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/group19/1294642551/src/jvm/attr/LocalVariableTable.java b/group19/1294642551/src/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..28d41fcd26 --- /dev/null +++ b/group19/1294642551/src/jvm/attr/LocalVariableTable.java @@ -0,0 +1,58 @@ +package jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import jvm.constant.ConstantPool; + +import jvm.loader.ByteCodeIterator; + +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){ + iter.back(2); + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int itemLen = iter.nextU2ToInt(); + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIndex, attrLen); + + for(int i = 0; i < itemLen; i++){ + int startPC = iter.nextU2ToInt(); + int length = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int slotIndex = iter.nextU2ToInt(); + LocalVariableItem item = new LocalVariableItem(startPC, length, nameIndex, descIndex, slotIndex); + localVariableTable.addLocalVariableItem(item); + + } + + return localVariableTable; + } + + + 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/group19/1294642551/src/jvm/clz/ClassFile.java b/group19/1294642551/src/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2abe746659 --- /dev/null +++ b/group19/1294642551/src/jvm/clz/ClassFile.java @@ -0,0 +1,112 @@ +package jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import jvm.constant.ClassInfo; +import jvm.constant.ConstantPool; +import jvm.field.Field; +import jvm.method.Method; + +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 m :methods){ + + int nameIndex = m.getNameIndex(); + int descriptionIndex = m.getDescriptorIndex(); + + String name = this.getConstantPool().getUTF8String(nameIndex); + String desc = this.getConstantPool().getUTF8String(descriptionIndex); + if(name.equals(methodName) && desc.equals(paramAndReturnType)){ + return m; + } + } + return null; + } + public Method getMainMethod(){ + + return getMethod("main","([Ljava/lang/String;)V"); + } +} diff --git a/group19/1294642551/src/jvm/cmd/CommandParser.java b/group19/1294642551/src/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..8529a49ed5 --- /dev/null +++ b/group19/1294642551/src/jvm/cmd/CommandParser.java @@ -0,0 +1,175 @@ +package jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import jvm.clz.ClassFile; + +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) { + if(codes == null || codes.length()== 0){ + throw new RuntimeException("code 代码不正确"); + } + + codes = codes.toUpperCase(); + CommandIterator iter = new CommandIterator(codes); + ArrayList cmds = new ArrayList(); + + while(iter.hasNext()){ + String opCode = iter.next2CharAsString(); + int cmdsLen = cmds.size(); + addNoOperandCmd(clzFile, cmds, opCode); + addOneOperandCmd(clzFile, iter, cmds, opCode); + addTwoOperandCmd(clzFile, iter, cmds, opCode); + + if(cmds.size() == cmdsLen){//说明opCode没有加入进cmds + throw new RuntimeException("oprate code: "+opCode+"未实现"); + } + + } + + calcuateOffset(cmds);//计算偏移 + ByteCodeCommand[] result = new ByteCodeCommand[cmds.size()]; + cmds.toArray(result); + + + return result; + } + + public static void addNoOperandCmd(ClassFile clzFile, + ArrayList cmds, String opCode ) { + NoOperandCmd noOperandCmd = null; + if(opCode.equals(aload_0) || opCode.equals(aload_1) || opCode.equals(aload_2) + || opCode.equals(iload_1) || opCode.equals(iload_2) ||opCode.equals(iload_3) + || opCode.equals(fload_3) || opCode.equals(voidreturn) || opCode.equals(dup) + || opCode.equals(astore_1)){ + noOperandCmd = new NoOperandCmd(clzFile, opCode); + cmds.add(noOperandCmd); + } + } + + public static void addOneOperandCmd(ClassFile clzFile, + CommandIterator iter, ArrayList cmds, String opCode ) { + OneOperandCmd oneOperandCmd = null; + boolean flag = false; + if(bipush.equals(opCode)){ + oneOperandCmd = new BiPushCmd(clzFile, opCode); + flag = true; + }else if(ldc.equals(opCode)){ + oneOperandCmd = new LdcCmd(clzFile, opCode); + flag = true; + } + if(flag){ + oneOperandCmd.setOperand(iter.next2CharAsInt()); + cmds.add(oneOperandCmd); + } + } + + public static void addTwoOperandCmd(ClassFile clzFile, + CommandIterator iter, ArrayList cmds, String opCode) { + TwoOperandCmd twoOperandCmd = null; + boolean flag = false; + if(new_object.equals(opCode)){ + twoOperandCmd = new NewObjectCmd(clzFile, opCode); + flag = true; + + }else if(invokespecial.equals(opCode)){ + twoOperandCmd = new InvokeSpecialCmd(clzFile, opCode); + flag = true; + + }else if(invokevirtual.equals(opCode)){ + twoOperandCmd = new InvokeVirtualCmd(clzFile, opCode); + flag = true; + + }else if(getfield.equals(opCode)){ + twoOperandCmd = new GetFieldCmd(clzFile, opCode); + flag = true; + + }else if(getstatic.equals(opCode)){ + twoOperandCmd = new GetStaticFieldCmd(clzFile, opCode); + flag = true; + + }else if(putfield.equals(opCode)){ + twoOperandCmd = new PutFieldCmd(clzFile, opCode); + flag = true; + + } + + if(flag){ + twoOperandCmd.setOprand1(iter.next2CharAsInt()); + twoOperandCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(twoOperandCmd); + } + } + + 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/group19/1294642551/src/jvm/constant/ClassInfo.java b/group19/1294642551/src/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..4a3fb0474a --- /dev/null +++ b/group19/1294642551/src/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package jvm.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/group19/1294642551/src/jvm/field/Field.java b/group19/1294642551/src/jvm/field/Field.java new file mode 100644 index 0000000000..edb9051797 --- /dev/null +++ b/group19/1294642551/src/jvm/field/Field.java @@ -0,0 +1,49 @@ +package jvm.field; + +import jvm.constant.ConstantPool; +import jvm.constant.UTF8Info; +import jvm.loader.ByteCodeIterator; + + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + + + private ConstantPool pool; + + public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { + + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.pool = pool; + } + + public String toString() { + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + + 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/group19/1294642551/src/jvm/loader/ClassFileLoader.java b/group19/1294642551/src/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..7517ddc4fc --- /dev/null +++ b/group19/1294642551/src/jvm/loader/ClassFileLoader.java @@ -0,0 +1,83 @@ +package jvm.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + + +import jvm.clz.ClassFile; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + className = className.replace('.', File.separatorChar) + ".class"; + + for(String path : clzPaths){ + String clzFileName = path + File.separatorChar + className; + byte[] codes = loadClassFile(clzFileName); + if(codes != null){ + return codes; + } + } + + return null; + + } + + private byte[] loadClassFile(String clzFileName) { + + try { + InputStream input = new FileInputStream(new File(clzFileName)); + return IOUtils.toByteArray(input); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } 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); + + } + + + + + + + +} \ No newline at end of file diff --git a/group19/1294642551/src/jvm/loader/ClassFileParser.java b/group19/1294642551/src/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..3529f727bc --- /dev/null +++ b/group19/1294642551/src/jvm/loader/ClassFileParser.java @@ -0,0 +1,168 @@ +package jvm.loader; + + + +import java.io.UnsupportedEncodingException; + +import jvm.clz.AccessFlag; +import jvm.clz.ClassFile; +import jvm.clz.ClassIndex; +import jvm.constant.ClassInfo; +import jvm.constant.ConstantInfo; +import jvm.constant.ConstantPool; +import jvm.constant.FieldRefInfo; +import jvm.constant.MethodRefInfo; +import jvm.constant.NameAndTypeInfo; +import jvm.constant.NullConstantInfo; +import jvm.constant.StringInfo; +import jvm.constant.UTF8Info; +import jvm.field.Field; +import jvm.method.Method; + +public class ClassFileParser { + + private ConstantPool constantPool; + + public ClassFile parse(byte[] codes) { + + + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + iter.nextUxToHexString(4); + + clzFile.setMinorVersion(iter.nextU2ToInt()); + clzFile.setMajorVersion(iter.nextU2ToInt()); + + this.constantPool = parseConstantPool(iter); + clzFile.setConstPool(constantPool); + + AccessFlag accessFlag = parseAccessFlag(iter); + clzFile.setAccessFlag(accessFlag); + + ClassIndex clzIndex = parseClassInfex(iter); + clzFile.setClassIndex(clzIndex); + + parseInterfaces(iter);//接口 + + parseFileds(clzFile, iter); + + parseMethods(clzFile, iter); + + + + return clzFile; + } + + + + // 访问标志 + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + int flagValue = iter.nextU2ToInt(); + AccessFlag accessFlag = new AccessFlag(flagValue); + return accessFlag; + } + + // 本类和父类 + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + int thisClassIndex = iter.nextU2ToInt(); + int superClassIndex = iter.nextU2ToInt(); + + classIndex.setThisClassIndex(thisClassIndex); + classIndex.setSuperClassIndex(superClassIndex); + + return classIndex; + + } + + // 常量池 + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + ConstantPool constantPool = new ConstantPool(); + int poolSize = iter.nextU2ToInt(); + constantPool.addConstantInfo(new NullConstantInfo()); + for(int i = 1; i < poolSize; i++){ + ConstantInfo constantInfo = null; + + int type = iter.nextU1toInt(); + if(type == 1){ + UTF8Info utf8Info = new UTF8Info(constantPool); + int length = iter.nextU2ToInt(); + byte[] data = iter.getBytes(length); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + utf8Info.setLength(length); + utf8Info.setValue(value); + constantInfo = utf8Info; + + }else if(type == 7){ + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(iter.nextU2ToInt()); + constantInfo = classInfo; + + }else if(type == 8){ + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(iter.nextU2ToInt()); + constantInfo = stringInfo; + + }else if(type == 9){ + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + constantInfo = fieldRefInfo; + + }else if(type == 10){ + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + constantInfo = methodRefInfo; + + }else if(type == 12){ + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); + constantInfo = nameAndTypeInfo; + + }else{ + throw new RuntimeException("type: "+type+" 不在范围之内"); + } + + constantPool.addConstantInfo(constantInfo); + } + + return constantPool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + +// System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private void parseFileds(ClassFile clzFile, ByteCodeIterator iter) { + int fieldCount = iter.nextU2ToInt(); + for(int i = 0; i < fieldCount; i++){ + Field field = Field.parse(clzFile.getConstantPool(), iter); + clzFile.addField(field); + } + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + int methodCount = iter.nextU2ToInt(); + for(int i = 0; i < methodCount; i++){ + Method method = Method.parse(clzFile, iter); + clzFile.addMethod(method); + } + + + } + + +} diff --git a/group19/1294642551/src/jvm/method/Method.java b/group19/1294642551/src/jvm/method/Method.java new file mode 100644 index 0000000000..5749091ffe --- /dev/null +++ b/group19/1294642551/src/jvm/method/Method.java @@ -0,0 +1,99 @@ +package jvm.method; + +import jvm.clz.ClassFile; +import jvm.cmd.ByteCodeCommand; +import jvm.attr.AttributeInfo; +import jvm.attr.CodeAttr; +import jvm.constant.ConstantPool; +import jvm.constant.UTF8Info; +import jvm.loader.ByteCodeIterator; + + + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + + public ClassFile getClzFile() { + return clzFile; + } + + public int getNameIndex() { + return nameIndex; + } + public int getDescriptorIndex() { + return descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr code) { + this.codeAttr = code; + } + + + + public Method(ClassFile clzFile,int accessFlag, int nameIndex, int descriptorIndex) { + this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + + + + public String toString() { + + ConstantPool pool = this.clzFile.getConstantPool(); + StringBuilder buffer = new StringBuilder(); + + String name = ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + + String desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + + buffer.append(name).append(":").append(desc).append("\n"); + + buffer.append(this.codeAttr.toString(pool)); + + return buffer.toString(); + } + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attributeCount = iter.nextU2ToInt(); + + Method method = new Method(clzFile, accessFlag, nameIndex, descIndex); + for(int i = 0; i < attributeCount; i++){ + int attrNameIndex = iter.nextU2ToInt(); + String attributeName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + if(AttributeInfo.CODE.equalsIgnoreCase(attributeName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + }else{ + throw new RuntimeException("Method 中的属性"+attributeName+"未定义"); + } + } + + + return method; + + } + + public ByteCodeCommand[] getCmds() { + return this.getCodeAttr().getCmds(); + } + +} diff --git a/group19/1294642551/src/jvm/print/ClassFilePrinter.java b/group19/1294642551/src/jvm/print/ClassFilePrinter.java new file mode 100644 index 0000000000..abff3602fe --- /dev/null +++ b/group19/1294642551/src/jvm/print/ClassFilePrinter.java @@ -0,0 +1,54 @@ +package jvm.print; + +import jvm.clz.ClassFile; +import jvm.constant.ClassInfo; +import jvm.constant.ConstantInfo; +import jvm.constant.ConstantPool; +import jvm.constant.FieldRefInfo; +import jvm.constant.MethodRefInfo; +import jvm.constant.NameAndTypeInfo; + +import jvm.constant.StringInfo; +import jvm.constant.UTF8Info; +import jvm.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.getMajorVersion()); + + ConstantPoolPrinter cnstPoolPrinter = new ConstantPoolPrinter(clzFile.getConstantPool()); + cnstPoolPrinter.print(); + + + + + } + + public static void main(String[] args){ + String path = "D:\\Git Files\\coding2017\\group19\\1294642551\\bin"; + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path); + String className = "jvm.EmployeeV1"; + + ClassFile clzFile = loader.loadClass(className); + + ClassFilePrinter printer = new ClassFilePrinter(clzFile); + + printer.print(); + } +} diff --git a/group19/1294642551/src/jvm/print/ConstantPoolPrinter.java b/group19/1294642551/src/jvm/print/ConstantPoolPrinter.java new file mode 100644 index 0000000000..de85de2eaf --- /dev/null +++ b/group19/1294642551/src/jvm/print/ConstantPoolPrinter.java @@ -0,0 +1,87 @@ +package jvm.print; + +import jvm.constant.ClassInfo; +import jvm.constant.ConstantInfo; +import jvm.constant.ConstantPool; +import jvm.constant.FieldRefInfo; +import jvm.constant.MethodRefInfo; +import jvm.constant.NameAndTypeInfo; +import jvm.constant.StringInfo; +import jvm.constant.UTF8Info; + +public class ConstantPoolPrinter { + ConstantPool pool; + ConstantPoolPrinter(ConstantPool pool){ + this.pool = pool; + } + public void print(){ + + System.out.println("Constant Pool:"); + + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } + } + + + + +} diff --git a/group19/1294642551/src/linkList/LinkedList.java b/group19/1294642551/src/linkList/LinkedList.java new file mode 100644 index 0000000000..ebbe0beb31 --- /dev/null +++ b/group19/1294642551/src/linkList/LinkedList.java @@ -0,0 +1,320 @@ +package linkList; + +/** + * 单向链表:其中头结点(head)中没有数据,第一个数据是head结点的下一个结点存贮 + * @author 12946 + * + */ +public class LinkedList implements List { + + private Node head;//头结点 + private int size;//链表中元素的个数 + + public LinkedList(){ + this.head = new Node(null); + this.size = 0; + } + + + public void add(Object o){ + Node newNode = new Node(o); + Node tempNode = head; + while(tempNode.next != null){ + tempNode = tempNode.next; + } + tempNode.next = newNode; + size++; + } + + public void add(int index , Object o){ + if(index < 0 || index > size-1){ + throw new IndexOutOfBoundsException("索引越界"); + } + Node newNode = new Node(o); + Node tempNode = null; + if(index == 0){ + tempNode = head; + }else{ + tempNode = getNode(index - 1); + } + newNode.next = tempNode.next; + tempNode.next = newNode; + + size++; + } + + public Object get(int index){ + + return getNode(index).data; + } + + public Node getNode(int index){ + if(index < 0 || index > size-1){ + throw new IndexOutOfBoundsException("索引越界"); + } + Node tempNode = head; + for(int i = -1; i < index; i++){ + tempNode = tempNode.next; + } + return tempNode; + } + + public Object remove(int index){ + if(index < 0 || index > size-1){ + throw new IndexOutOfBoundsException("索引越界"); + } + Node tempNode = null; + if(index == 0){ + tempNode = head; + }else{ + tempNode = getNode(index - 1); + } + tempNode.next = tempNode.next.next; + size--; + return tempNode.next.data; + } + + public int size(){ + return size; + } + + public void addFirst(Object o){ + Node newNode = new Node(o); + newNode.next = getNode(0); + head.next = newNode; + size++; + } + public void addLast(Object o){ + getNode(size-1).next = new Node(o); + size++; + } + public Object removeFirst(){ + if(size < 1){ + throw new IndexOutOfBoundsException("链表为null,不能删除元素"); + } + head.next = head.next.next; + size--; + + return head.next.data; + } + public Object removeLast(){ + if(size < 1){ + throw new IndexOutOfBoundsException("链表为null,不能删除元素"); + } + + Object data = null; + if(size == 1){ + data = head.next.data; + head.next = null; + }else{ + Node tempNode = getNode(size-2); + data = tempNode.next.data; + tempNode.next = null; + } + size--; + return data; + } + + /** + * 根据元素的值查找元素在链表中的位置,找不到则返回-1 + * @param o + * @return + */ + public int findIndex(Object o){ + for(int i = 0; i < size; i++){ + if(get(i).equals(o)){ + return i; + } + } + + return -1; + } + + public String toString(){ + StringBuilder sb = new StringBuilder("["); + for(int i = 0; i < size; i++){ + sb.append(get(i)); + if(i != size-1){ + sb.append(","); + } + } + sb.append("]"); + + return sb.toString(); + } + + private static class Node{ + Object data; + Node next = null; + + public Node(Object data){ + this.data = data; + } + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + int[] arr = new int[size]; + for(int i = 0; i < size; i++){ + arr[i] = (Integer) get(size - i - 1); + } + LinkedList newLinkedList = new LinkedList(); + for(int i = 0; i < size; i++){ + newLinkedList.add(arr[i]); + } + + head = newLinkedList.head; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int index = size/2; + head.next = getNode(index); + size = size - index; + } + + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + if(i < 0 ){ + throw new IndexOutOfBoundsException("索引越界"); + } + + Node startNode = null; + Node endNode = null; + + if(i == 0){ + startNode = head; + }else{ + startNode = getNode(i - 1); + } + + if(i + length >= size){ + endNode = null; + size = i; + }else{ + endNode = getNode(i + length); + size = size - length; + } + startNode.next = endNode; + + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + if((Integer)list.get(list.size-1) > this.size - 1){ + throw new IndexOutOfBoundsException("list指定的元素角标超过当前链表的范围"); + } + int[] arr = new int[list.size]; + for(int i = 0; i < arr.length; i++){ + int index = (Integer) list.get(i); + arr[i] = (Integer) this.get(index); + } + + return arr; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + for(int i = 0; i < list.size; i++){ + Object value = list.get(i); + int index = this.findIndex(value); + if(index != -1){ + this.remove(index); + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + LinkedList newLinkedList = new LinkedList(); + for(int i = 0; i < size; i++){ + Object value = this.get(i); + if(newLinkedList.findIndex(value) == -1){ + newLinkedList.add(value); + } + } + this.head = newLinkedList.head; + this.size = newLinkedList.size; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + int start = 0; + int end = size - 1; + for(int i = 0; i < size; i++){ + int value = (Integer) get(i); + if(value <= min){ + start++; + } + } + + for(int j = size-1; j > -1; j--){ + int value = (Integer) get(j); + if(value >= max){ + end--; + } + } + + Node tempNode = null; + if(start == 0){ + tempNode = head; + }else{ + tempNode = getNode(start - 1); + } + tempNode.next = getNode(end).next; + size = size - (end - start + 1); + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + LinkedList newLinkedList = new LinkedList(); + for(int i = 0; i < list.size; i++){ + int value = (Integer) list.get(i); + int index = findIndex(value); + if(index != -1){ + newLinkedList.add(value); + } + } + + return newLinkedList; + } +} diff --git a/group19/1294642551/src/linkList/LinkedListTest.java b/group19/1294642551/src/linkList/LinkedListTest.java new file mode 100644 index 0000000000..53570d25d2 --- /dev/null +++ b/group19/1294642551/src/linkList/LinkedListTest.java @@ -0,0 +1,202 @@ +package linkList; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReverse() { + LinkedList l = new LinkedList(); + + Assert.assertEquals("[]", l.toString()); + + l.add(1); + l.reverse(); + Assert.assertEquals("[1]", l.toString()); + + l.add(2); + l.add(3); + l.add(4); + + l.reverse(); + Assert.assertEquals("[4,3,2,1]", l.toString()); + } + + @Test + public void testRemoveFirstHalf() { + { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(4); + linkedList.removeFirstHalf(); + Assert.assertEquals("[3,4]", linkedList.toString()); + } + { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(4); + linkedList.add(5); + linkedList.removeFirstHalf(); + Assert.assertEquals("[3,4,5]", linkedList.toString()); + } + } + + + + @Test + public void testRemoveIntInt() { + + { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(4); + linkedList.remove(0, 2); + Assert.assertEquals("[3,4]", linkedList.toString()); + } + { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(4); + linkedList.remove(3, 2); + Assert.assertEquals("[1,2,3]", linkedList.toString()); + } + { + LinkedList linkedList = new LinkedList(); + linkedList.add(1); + linkedList.add(2); + linkedList.add(3); + linkedList.add(4); + linkedList.remove(2, 2); + Assert.assertEquals("[1,2]", linkedList.toString()); + } + + } + @Test + public void testGetElements() { + LinkedList linkedList = new LinkedList(); + linkedList.add(11); + linkedList.add(101); + linkedList.add(201); + linkedList.add(301); + linkedList.add(401); + linkedList.add(501); + linkedList.add(601); + linkedList.add(701); + LinkedList list = new LinkedList(); + list.add(1); + list.add(3); + list.add(4); + list.add(6); + Assert.assertArrayEquals(new int[]{101,301,401,601}, linkedList.getElements(list)); + } + + @Test + public void testSubtract() { + LinkedList list1 = new LinkedList(); + list1.add(101); + list1.add(201); + list1.add(301); + list1.add(401); + list1.add(501); + list1.add(601); + list1.add(701); + + LinkedList list2 = new LinkedList(); + + list2.add(101); + list2.add(201); + list2.add(301); + list2.add(401); + list2.add(501); + + list1.subtract(list2); + + Assert.assertEquals("[601,701]", list1.toString()); + } + + + @Test + public void testRemoveDuplicateValues() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(1); + list.add(2); + list.add(2); + list.add(3); + list.add(5); + list.add(5); + list.add(6); + list.removeDuplicateValues(); + Assert.assertEquals("[1,2,3,5,6]", list.toString()); + } + + + @Test + public void testRemoveRange() { + + { + LinkedList linkedList = new LinkedList(); + + linkedList.add(11); + linkedList.add(12); + linkedList.add(13); + linkedList.add(14); + linkedList.add(16); + linkedList.add(16); + linkedList.add(19); + + linkedList.removeRange(10, 19); + Assert.assertEquals("[19]", linkedList.toString()); + } + + { + LinkedList linkedList = new LinkedList(); + + linkedList.add(11); + linkedList.add(12); + linkedList.add(13); + linkedList.add(14); + linkedList.add(16); + linkedList.add(16); + linkedList.add(19); + + linkedList.removeRange(10, 14); + Assert.assertEquals("[14,16,16,19]", linkedList.toString()); + } + } + @Test + public void testIntersection() { + LinkedList list1 = new LinkedList(); + list1.add(1); + list1.add(6); + list1.add(7); + + LinkedList list2 = new LinkedList(); + list2.add(2); + list2.add(5); + list2.add(6); + + LinkedList newList = list1.intersection(list2); + Assert.assertEquals("[6]", newList.toString()); + } + +} diff --git a/group19/1294642551/src/linkList/List.java b/group19/1294642551/src/linkList/List.java new file mode 100644 index 0000000000..715da9ab77 --- /dev/null +++ b/group19/1294642551/src/linkList/List.java @@ -0,0 +1,9 @@ +package linkList; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group19/1294642551/src/litestruts/Configuration.java b/group19/1294642551/src/litestruts/Configuration.java new file mode 100644 index 0000000000..5dcde2d1c6 --- /dev/null +++ b/group19/1294642551/src/litestruts/Configuration.java @@ -0,0 +1,137 @@ +package litestruts; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + + +/** + * 配置类 + * 提取xml文件中的元素和属性,封装成Java对象,这样方便使用 + * @author 12946 + * + */ + +public class Configuration { + + //键为actionName,值为ActionConfig对象 + private Map actions = new HashMap(); + + public Configuration(String filename) { + //得到输入流 + String packageName = this.getClass().getPackage().getName(); + packageName = packageName.replace(".", "/"); + InputStream input = this.getClass().getResourceAsStream("/"+packageName+"/"+filename); + parseXML(input); + try { + input.close(); + } catch (IOException e) { + throw new ConfigurationException(e); + } + //解析XML + + } + + /** + * 解析XML,将XML的元素封装到ActionConfig对象中 + * @param input + */ + @SuppressWarnings("unchecked") + private void parseXML(InputStream input) { + + try { + SAXReader reader = new SAXReader(); + Document document = reader.read(input); + Element root = document.getRootElement(); + + List actionList = root.elements("action");//得到所有action元素 + for(Element action : actionList){ + String actionName = action.attributeValue("name"); + String className = action.attributeValue("class"); + // 创建ActionConfig对象 + ActionConfig ac = new ActionConfig(actionName, className); + // 给ActionConfig对象增加ViewResult + List results = action.elements("result"); + for(Element result : results){ + String resultName = result.attributeValue("name"); + String resultText = result.getText(); + ac.addViewResult(resultName, resultText); + } + // 将ActionConfig对象加入到actions中 + this.actions.put(actionName, ac); + } + } catch (DocumentException e) { + throw new ConfigurationException(e); + } + + + } + + /** + * 获取指定action中的class名称 + * @param actionName + * @return + */ + public String getClassName(String actionName) { + ActionConfig ac = this.actions.get(actionName); + if(ac == null){ + return null; + } + return ac.getClassName(); + } + + /** + * 根据resultName获取resultView + * @param string + * @return + */ + public String getResultView(String actionName, String resultName) { + ActionConfig ac = this.actions.get(actionName); + if(ac == null){ + return null; + } + return ac.getViewName(resultName); + } + + /** + * 内部类,封装struts.xml的元素 + * @author 12946 + * + */ + @SuppressWarnings("unused") + private class ActionConfig{ + private String actionName; + private String className; + Map viewResult = new HashMap(); + + public ActionConfig(String actionName, String className) { + super(); + this.actionName = actionName; + this.className = className; + } + + public String getClassName(){ + return className; + } + + public void addViewResult(String name, String viewName){ + viewResult.put(name, viewName); + } + + public String getViewName(String resultName){ + return viewResult.get(resultName); + } + + } + + + + +} diff --git a/group19/1294642551/src/litestruts/ConfigurationException.java b/group19/1294642551/src/litestruts/ConfigurationException.java new file mode 100644 index 0000000000..a74e434a38 --- /dev/null +++ b/group19/1294642551/src/litestruts/ConfigurationException.java @@ -0,0 +1,26 @@ +package litestruts; + +import java.io.IOException; + +import org.dom4j.DocumentException; + + +public class ConfigurationException extends RuntimeException { + + + public ConfigurationException(String msg) { + super(msg); + } + + + public ConfigurationException(IOException e) { + super(e); + } + + + public ConfigurationException(DocumentException e) { + super(e); + } + + +} diff --git a/group19/1294642551/src/litestruts/LoginAction.java b/group19/1294642551/src/litestruts/LoginAction.java new file mode 100644 index 0000000000..bba4c11c9f --- /dev/null +++ b/group19/1294642551/src/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group19/1294642551/src/litestruts/ReflectionUtil.java b/group19/1294642551/src/litestruts/ReflectionUtil.java new file mode 100644 index 0000000000..fc015885d6 --- /dev/null +++ b/group19/1294642551/src/litestruts/ReflectionUtil.java @@ -0,0 +1,79 @@ +package litestruts; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class ReflectionUtil { + + public static List getSetterMethod(Class clazz) { + return getMethods(clazz, "set"); + } + + + public static void setParameters(Object o, + Map parameters) { + List methods = getSetterMethod(o.getClass()); + + for(String name : parameters.keySet()){ + String methodName = "set"+name; + for(Method m : methods){ + if(m.getName().equalsIgnoreCase(methodName)){ + try { + m.invoke(o, parameters.get(name)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + } + } + + + public static List getGetterMethod(Class clazz) { + return getMethods(clazz,"get"); + } + + + public static List getMethods(Class clazz, String startWithName) { + List methods = new ArrayList(); + for(Method method : clazz.getDeclaredMethods()){ + if(method.getName().startsWith(startWithName)){ + methods.add(method); + } + } + return methods; + } + + + public static Map getParameters(Object o) { + List methods = getGetterMethod(o.getClass()); + Map parameters = new HashMap(); + for(Method m : methods){ + try { + String name = m.getName().replaceFirst("get", "").toLowerCase(); + Object value = m.invoke(o); + parameters.put(name, value); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + return parameters; + + } + + +} diff --git a/group19/1294642551/src/litestruts/Struts.java b/group19/1294642551/src/litestruts/Struts.java new file mode 100644 index 0000000000..1034ccf2d5 --- /dev/null +++ b/group19/1294642551/src/litestruts/Struts.java @@ -0,0 +1,98 @@ +package litestruts; + +import java.lang.reflect.Method; +import java.util.Map; + + + +public class Struts { + + private static final Configuration cfg = new Configuration("struts.xml"); + + public static View runAction(String actionName, Map parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ +// try { +// String className = cfg.getClassName(actionName); +// if(className == null){ +// return null; +// } +// Class clazz = Class.forName(className); +// LoginAction action = (LoginAction) clazz.newInstance(); +// +// ReflectionUtil.setParameters(action, parameters); +// Method excuteMethod = clazz.getMethod("excute"); +// String resultName = (String) excuteMethod.invoke(action); +// String jsp = cfg.getResultView(actionName, resultName); +// +// Map parameterMap = ReflectionUtil.getParameters(action); +// +// View view = new View(); +// view.setParameters(parameterMap); +// view.setJsp(jsp); +// return view; +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// return null; +// } +// + + + + + + + + String clzName = cfg.getClassName(actionName); + + if(clzName == null){ + return null; + } + + try { + + Class clz = Class.forName(clzName); + Object action = clz.newInstance(); + + ReflectionUtil.setParameters(action, parameters); + + Method m = clz.getDeclaredMethod("execute"); + String resultName = (String)m.invoke(action); + + Map params = ReflectionUtil.getParameters(action); + String resultView = cfg.getResultView(actionName, resultName); + View view = new View(); + view.setParameters(params); + view.setJsp(resultView); + return view; + + + + } catch (Exception e) { + + e.printStackTrace(); + } + return null; + } +} diff --git a/group19/1294642551/src/litestruts/View.java b/group19/1294642551/src/litestruts/View.java new file mode 100644 index 0000000000..77e7435117 --- /dev/null +++ b/group19/1294642551/src/litestruts/View.java @@ -0,0 +1,23 @@ +package litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group19/1294642551/src/stackUtil/Stack.java b/group19/1294642551/src/stackUtil/Stack.java new file mode 100644 index 0000000000..a01d2b6e87 --- /dev/null +++ b/group19/1294642551/src/stackUtil/Stack.java @@ -0,0 +1,51 @@ +package stackUtil; + +import java.util.ArrayList; + + +public class Stack { + private ArrayList elementData; + private int size; + + public Stack(){ + elementData = new ArrayList(); + this.size = 0; + } + + + + public void push(E e){ + elementData.add(e); + size++; + } + + public E pop(){ + E o = elementData.remove(size - 1); + size--; + return o; + } + + public E peek(){ + return elementData.get(size - 1); + } + + public boolean isEmpty(){ + return size == 0; + } + + public int size(){ + return size; + } + + public String toString(){ + StringBuilder sb = new StringBuilder("["); + for(int i = 0; i < size; i++){ + sb.append(elementData.get(i)); + if(i < size - 1){ + sb.append(", "); + } + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/group19/1294642551/src/stackUtil/StackUtil.java b/group19/1294642551/src/stackUtil/StackUtil.java new file mode 100644 index 0000000000..de1ec4231d --- /dev/null +++ b/group19/1294642551/src/stackUtil/StackUtil.java @@ -0,0 +1,121 @@ +package stackUtil; + + + +public class StackUtil { + + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + /* + * 注意值传递的问题 + */ + if(s == null || s.isEmpty()) { + return; + } + + int size = s.size(); + Stack temp1 = new Stack(); + Stack temp2 = new Stack(); + for(int i = 0; i < size; i++){ + temp1.push(s.pop()); + } + for(int i = 0; i < size; i++){ + temp2.push(temp1.pop()); + } + for(int i = 0; i < size; i++){ + s.push(temp2.pop()); + } + + + + } + + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, int o) { + if(s == null || s.isEmpty()) { + return; + } + + Stack newStack = new Stack(); + int value = s.pop(); + while(value != o){ + newStack.push(value); + value = s.pop(); + } + while(!newStack.isEmpty()){ + s.push(newStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + Object[] data = new Object[len]; + for(int i = 0; i < len; i++){ + data[i] = s.pop(); + } + for(int i = len-1; i >= 0; i--){ + s.push((Integer)data[i]); + } + return data; + } + /** + * 字符串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 stack = new Stack(); + for(int i = 0; i < s.length(); i++){ + String c = s.charAt(i)+""; + if(c.equals("{") || c.equals("[") || c.equals("(")){ + stack.push(c); + } + + if(c.equals("}")){ + if(stack.peek().equals("{")){ + stack.pop(); + }else{ + return false; + } + } + + if(c.equals("]")){ + if(stack.peek().equals("[")){ + stack.pop(); + }else{ + return false; + } + } + + if(c.equals(")")){ + if(stack.peek().equals("(")){ + stack.pop(); + }else{ + return false; + } + } + + } + return stack.size() == 0; + } + + +} diff --git a/group19/1294642551/src/struts_Reflect/Struts.java b/group19/1294642551/src/struts_Reflect/Struts.java deleted file mode 100644 index 1694cf369c..0000000000 --- a/group19/1294642551/src/struts_Reflect/Struts.java +++ /dev/null @@ -1,142 +0,0 @@ -package struts_Reflect; - -import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; - - - - -public class Struts { - - public static View runAction(String actionName, Map parameters) throws Exception { - - /* - - 0. ȡļstruts.xml - - 1. actionNameҵӦclass LoginAction, ͨʵ - parametersеݣösetter parametersе - ("name"="test" , "password"="1234") , - ǾӦõ setNamesetPassword - - 2. ͨöexectue ÷ֵ"success" - - 3. ͨҵgetter getMessage, - ͨã ֵγһHashMap , {"message": "¼ɹ"} , - ŵViewparameters - - 4. struts.xmlе ,Լexecuteķֵ ȷһjsp - ŵViewjspֶС - - * - */ - - //classNameַ - String className = null; - - //---------XMLļ--------------------------------------------------------------------------- - - // saxReader - SAXReader reader = new SAXReader(); - // ͨreadȡһļ תDocument - Document document = reader.read(new File("src/struts_Reflect/Struts.xml")); - //ȡڵԪض - Element root = document.getRootElement(); - //System.out.println("Root: " + root.getName()); - - // ȡԪnameֵΪloginclassԵֵ浽classNameС - for (Iterator iter = root.elementIterator(); iter.hasNext();) - { - Element e = (Element) iter.next(); - String name = e.attributeValue("name"); - - if(name.equals("login")) - { - className = e.attributeValue("class"); - } - - } - - //-----------ȡLoginActionʵ䷽--------------------------------------------------------- - - //ȡʵ - Class clazz = Class.forName("struts_Reflect.LoginAction"); - Object obj = clazz.newInstance(); - - //setName setPassword - Method mSetName = clazz.getMethod("setName", String.class); - Method mSetPassWord = clazz.getMethod("setPassword", String.class); - mSetName.invoke(obj, parameters.get("name")); - mSetPassWord.invoke(obj, parameters.get("password")); - - //excute - Method mExecute = clazz.getMethod("execute", null); - String result = (String) mExecute.invoke(obj, null); - System.out.println(result); - - //ҵgetterԺֵŵparameterMapС - Method[] methods = clazz.getDeclaredMethods(); -// HashMap paraMap = new HashMap(); - - ArrayList al = new ArrayList(); - al.add("name"); - al.add("password"); - al.add("message"); - String key = null; - String value = null; - Field field = null; - - for(int i = 0; i < al.size(); i++) - { - key = al.get(i); - field = clazz.getDeclaredField(key); - field.setAccessible(true); - value = (String) field.get(obj); - parameters.put(key, value); - System.out.println(key+"---"+value); - } - - - - View view = new View(); - view.setParameters(parameters); - - //----------JSPֶηŵView------------------------------------- - - //ȡΪactionԪؽڵ - Element actionE = root.element("action"); - - // ȡԪresultе - String rValue = null; - - for (Iterator iter = actionE.elementIterator(); iter.hasNext();) - { - Element e = (Element) iter.next(); - String name = e.attributeValue("name"); - - if(name.equals(result)) - { - rValue = e.getText(); - view.setJsp(rValue); - System.out.println(rValue); - } - - } - - return view; - - } - -} \ No newline at end of file diff --git a/group19/1294642551/test/LRU/LRUPageFrameTest.java b/group19/1294642551/test/LRU/LRUPageFrameTest.java new file mode 100644 index 0000000000..dd51b5504f --- /dev/null +++ b/group19/1294642551/test/LRU/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package LRU; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group19/1294642551/test/data_Structure_Utils/ArrayUtilTest.java b/group19/1294642551/test/data_Structure_Utils/ArrayUtilTest.java new file mode 100644 index 0000000000..3a2ff9491a --- /dev/null +++ b/group19/1294642551/test/data_Structure_Utils/ArrayUtilTest.java @@ -0,0 +1,107 @@ +package data_Structure_Utils; + + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ArrayUtilTest { + + private ArrayUtil au; + @Before + public void setUp(){ + au = new ArrayUtil(); + } + + @Test + public void testReverseArray() { + + int[] origin = {7, 9, 30, 3, 4}; + int[] expecteds ={4, 3, 30, 9, 7}; + au.reverseArray(origin); + int[] actuals = origin; + + Assert.assertArrayEquals(expecteds, actuals); + } + + @Test + public void testRemoveZero() { + int[] oldArray = {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; + int[] expecteds = {1,3,4,5,6,6,5,4,7,6,7,5}; + int[] actuals = au.removeZero(oldArray); + + Assert.assertArrayEquals(expecteds, actuals); + } + + @Test + public void testMerge() { + + int[] a1 = {3, 5, 7,8}; + int[] a2 = {4, 5, 6,7}; + int[] expecteds = {3,4,5,6,7,8}; + int[] actuals = au.merge(a1, a2); + + Assert.assertArrayEquals(expecteds, actuals); + } + + @Test + public void testGrow() { + + int[] oldArray = {2,3,6}; + int size = 3; + int[] expecteds = {2,3,6,0,0,0}; + int[] actuals = au.grow(oldArray, size); + + Assert.assertArrayEquals(expecteds, actuals); + } + + @Test + public void testFibonacci() { + + int max = 1; + int[] expecteds = new int[0]; + int[] actuals = au.fibonacci(max); + + Assert.assertArrayEquals(expecteds, actuals); + } + + + + @Test + public void testGetPrimes() { + int max = 23; + int[] expecteds = {2,3,5,7,11,13,17,19}; + int[] actuals = au.getPrimes(max); + + Assert.assertArrayEquals(expecteds, actuals); + + } + + @Test + public void testGetPerfectNumbers() { + + int max = 30; + int[] expecteds = {6, 28}; + int[] actuals = au.getPerfectNumbers(max); + + Assert.assertArrayEquals(expecteds, actuals); + + max = 2; + expecteds = new int[0]; + actuals = au.getPerfectNumbers(max); + + Assert.assertArrayEquals(expecteds, actuals); + } + + @Test + public void testJoin() { + + int[] array = {3, 8, 9}; + String seperator = "-"; + String expecteds = "3-8-9"; + String actuals = au.join(array, seperator); + + Assert.assertEquals(expecteds, actuals); + } + +} diff --git a/group19/1294642551/test/download/ConnectionTest.java b/group19/1294642551/test/download/ConnectionTest.java new file mode 100644 index 0000000000..e71acc8728 --- /dev/null +++ b/group19/1294642551/test/download/ConnectionTest.java @@ -0,0 +1,36 @@ +package download; + +import java.io.IOException; + +import junit.framework.Assert; + +import org.junit.Test; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; +import download.impl.ConnectionManagerImpl; + +public class ConnectionTest { + + @Test + public void testGetContentLength() throws ConnectionException{ + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open("http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"); + Assert.assertEquals(35470, conn.getContentLength()); + } + + @Test + public void testRead() throws ConnectionException, IOException{ + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open("http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"); + byte[] data = conn.read(0, 35470); + Assert.assertEquals(35470, data.length); + + data = conn.read(0, 1023); + Assert.assertEquals(1024, data.length); + + data = conn.read(1024, 2023); + Assert.assertEquals(1000, data.length); + } +} diff --git a/group19/1294642551/test/download/FileDownloaderTest.java b/group19/1294642551/test/download/FileDownloaderTest.java new file mode 100644 index 0000000000..e3a708390a --- /dev/null +++ b/group19/1294642551/test/download/FileDownloaderTest.java @@ -0,0 +1,59 @@ +package download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import download.api.ConnectionManager; +import download.api.DownloadListener; +import download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url = "http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"; + + FileDownloader downloader = new FileDownloader(url, "d:/a.jpg"); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group19/1294642551/test/expr/InfixExprTest.java b/group19/1294642551/test/expr/InfixExprTest.java new file mode 100644 index 0000000000..5adcfc70ee --- /dev/null +++ b/group19/1294642551/test/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group19/1294642551/test/expr/InfixToPostfixTest.java b/group19/1294642551/test/expr/InfixToPostfixTest.java new file mode 100644 index 0000000000..3f3bd31a93 --- /dev/null +++ b/group19/1294642551/test/expr/InfixToPostfixTest.java @@ -0,0 +1,28 @@ +package expr; + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixToPostfixTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testConvert() { + { +// InfixExpr expr = new InfixExpr("2+3*4+5"); + String expr = "2+9/3-5"; + Assert.assertEquals("2 9 3 / + 5 -", InfixToPostfix.toString(InfixToPostfix.convert(expr))); + } + } + +} diff --git a/group19/1294642551/test/expr/PostfixExprTest.java b/group19/1294642551/test/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c3bb438ac4 --- /dev/null +++ b/group19/1294642551/test/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package 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/group19/1294642551/test/expr/PrefixExprTest.java b/group19/1294642551/test/expr/PrefixExprTest.java new file mode 100644 index 0000000000..9a4e8dae7d --- /dev/null +++ b/group19/1294642551/test/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package 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/group19/1294642551/test/expr/TokenParserTest.java b/group19/1294642551/test/expr/TokenParserTest.java new file mode 100644 index 0000000000..b435de08f7 --- /dev/null +++ b/group19/1294642551/test/expr/TokenParserTest.java @@ -0,0 +1,40 @@ +package 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 = TokenParser.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/group19/1294642551/test/jvm/ClassFileloaderTest.java b/group19/1294642551/test/jvm/ClassFileloaderTest.java new file mode 100644 index 0000000000..d0f4ca4186 --- /dev/null +++ b/group19/1294642551/test/jvm/ClassFileloaderTest.java @@ -0,0 +1,348 @@ +package jvm; + + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import jvm.clz.ClassFile; +import jvm.clz.ClassIndex; +import jvm.cmd.BiPushCmd; +import jvm.cmd.ByteCodeCommand; +import jvm.cmd.OneOperandCmd; +import jvm.cmd.TwoOperandCmd; +import jvm.constant.ClassInfo; +import jvm.constant.ConstantPool; +import jvm.constant.MethodRefInfo; +import jvm.constant.NameAndTypeInfo; +import jvm.constant.UTF8Info; +import jvm.field.Field; +import jvm.loader.ClassFileLoader; +import jvm.method.Method; + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "jvm/EmployeeV1"; + + static String path1 = "D:\\Git Files\\coding2017\\group19\\1294642551\\bin"; + static String path2 = "D:\\TempFiles"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "jvm.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 = "jvm.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1016, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "jvm.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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()); + } + + @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/group19/1294642551/test/litestruts/ConfigurationTest.java b/group19/1294642551/test/litestruts/ConfigurationTest.java new file mode 100644 index 0000000000..a5e260633e --- /dev/null +++ b/group19/1294642551/test/litestruts/ConfigurationTest.java @@ -0,0 +1,39 @@ +package litestruts; + +import org.junit.Assert; +import org.junit.Test; + +/** + * 配置类Configuration的测试类 + * @author 12946 + * + */ + +public class ConfigurationTest { + + private Configuration cfg = new Configuration("struts.xml"); + + @Test + public void testGetClassName(){ + String clzName = cfg.getClassName("login"); + Assert.assertEquals("litestruts.LoginAction", clzName); + + clzName = cfg.getClassName("logout"); + Assert.assertEquals("litestruts.LogoutAction", clzName); + } + + @Test + public void testGetResultView(){ + String jpg = cfg.getResultView("login","success"); + Assert.assertEquals("/jsp/homepage.jsp", jpg); + + jpg = cfg.getResultView("login","fail"); + Assert.assertEquals("/jsp/showLogin.jsp", jpg); + + jpg = cfg.getResultView("logout","success"); + Assert.assertEquals("/jsp/welcome.jsp", jpg); + + jpg = cfg.getResultView("logout","error"); + Assert.assertEquals("/jsp/error.jsp", jpg); + } +} diff --git a/group19/1294642551/test/litestruts/ReflectionUtilTest.java b/group19/1294642551/test/litestruts/ReflectionUtilTest.java new file mode 100644 index 0000000000..c04b3cda7d --- /dev/null +++ b/group19/1294642551/test/litestruts/ReflectionUtilTest.java @@ -0,0 +1,110 @@ +package litestruts; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class ReflectionUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testGetSetterMethod() throws ClassNotFoundException{ + String className = "litestruts.LoginAction"; + Class clazz = Class.forName(className); + List methods = ReflectionUtil.getSetterMethod(clazz); + + Assert.assertEquals(2, methods.size()); + //---------- + List expectedNames = new ArrayList(); + expectedNames.add("setName"); + expectedNames.add("setPassword"); + + Set actualNames = new HashSet(); + for(Method method : methods){ + actualNames.add(method.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectedNames)); + + } + + @Test + public void testSetParameters() throws Exception{ + String className = "litestruts.LoginAction"; + Class clazz = Class.forName(className); + LoginAction action = (LoginAction) clazz.newInstance(); + + Map parameters = new HashMap(); + parameters.put("name", "test"); + parameters.put("password", "1234"); + + ReflectionUtil.setParameters(action, parameters); + + Field f = clazz.getDeclaredField("name"); + f.setAccessible(true); + Assert.assertEquals("test", f.get(action)); + + f = clazz.getDeclaredField("password"); + f.setAccessible(true); + Assert.assertEquals("1234", f.get(action)); + } + + @Test + public void testGetGetterMethod() throws ClassNotFoundException{ + String className = "litestruts.LoginAction"; + Class clazz = Class.forName(className); + List methods = ReflectionUtil.getGetterMethod(clazz); + + Assert.assertEquals(3, methods.size()); + //---------- + List expectedNames = new ArrayList(); + expectedNames.add("getName"); + expectedNames.add("getPassword"); + expectedNames.add("getMessage"); + + Set actualNames = new HashSet(); + for(Method method : methods){ + actualNames.add(method.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectedNames)); + + } + + @Test + public void testGetParameters() throws Exception { + String className = "litestruts.LoginAction"; + Class clazz = Class.forName(className); + LoginAction action = (LoginAction) clazz.newInstance(); + action.setName("test"); + action.setPassword("123456"); + Map parameterMap = ReflectionUtil.getParameters(action); + + Assert.assertEquals(3, parameterMap.size()); + + + Assert.assertEquals(null, parameterMap.get("messaage") ); + Assert.assertEquals("test", parameterMap.get("name") ); + Assert.assertEquals("123456", parameterMap.get("password") ); + + } + + +} diff --git a/group19/1294642551/test/litestruts/StrutsTest.java b/group19/1294642551/test/litestruts/StrutsTest.java new file mode 100644 index 0000000000..986180da44 --- /dev/null +++ b/group19/1294642551/test/litestruts/StrutsTest.java @@ -0,0 +1,39 @@ +package litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group19/1294642551/test/stackUtil/StackUtilTest.java b/group19/1294642551/test/stackUtil/StackUtilTest.java new file mode 100644 index 0000000000..7f304445c7 --- /dev/null +++ b/group19/1294642551/test/stackUtil/StackUtilTest.java @@ -0,0 +1,66 @@ +package stackUtil; + + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/QuickMinStack.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/QuickMinStack.java new file mode 100644 index 0000000000..12e02ba5aa --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/QuickMinStack.java @@ -0,0 +1,61 @@ +package org.xukai.coderising.stack; + +import org.junit.Test; + +import java.util.*; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + + private TreeSet treeSet = new TreeSet(); + + private java.util.Stack stack = new java.util.Stack(); + + public void push(int data){ + stack.push(data); + treeSet.add(data); + } + public int pop(){ + if (!stack.isEmpty()) { + treeSet.remove(stack.peek()); + return stack.pop(); + } + return -1; + } + public int findMin(){ + if (treeSet.size() > 0) { + return treeSet.first(); + } + return -1; + } + + @Test + public void testQuickMinStack(){ + QuickMinStack stack = new QuickMinStack(); + stack.push(6); + stack.push(5); + stack.push(4); + stack.push(3); + stack.push(2); + stack.push(1); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println("min:" + stack.findMin()); + System.out.println(stack.pop()); + System.out.println("min:" + stack.findMin()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println("min:" + stack.findMin()); + System.out.println(stack.pop()); + System.out.println("min:" + stack.findMin()); + System.out.println(stack.pop()); + + + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackWithTwoQueues.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..e2e22a9766 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackWithTwoQueues.java @@ -0,0 +1,63 @@ +package org.xukai.coderising.stack; + + +import org.junit.Test; + +import java.util.concurrent.ArrayBlockingQueue; + +public class StackWithTwoQueues { + + private ArrayBlockingQueue queue1 = new ArrayBlockingQueue(10); + + private ArrayBlockingQueue queue2 = new ArrayBlockingQueue(10); + + + + + public void push(int data) { + + if (queue1.isEmpty()) { + queue1.offer(data); + swap(queue1,queue2); + } else { + queue2.offer(data); + swap(queue2, queue1); + } + } + + private void swap(ArrayBlockingQueue target, ArrayBlockingQueue origin) { + while (!origin.isEmpty()) { + target.offer(origin.poll()); + } + } + + public int pop() { + if (!queue1.isEmpty()) { + return queue1.poll(); + } else if(!queue2.isEmpty()) { + return queue2.poll(); + } + return -1; + } + + @Test + public void testStackWithTwoQueues(){ + StackWithTwoQueues queue = new StackWithTwoQueues(); + queue.push(6); + queue.push(5); + queue.push(4); + queue.push(3); + queue.push(2); + queue.push(1); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + System.out.println(queue.pop()); + + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TwoStackInOneArray.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..d5a91f0672 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/TwoStackInOneArray.java @@ -0,0 +1,122 @@ +package org.xukai.coderising.stack; + +import org.junit.Test; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + + Object[] data = new Object[5]; + + private int s1Pos = -1; + + private int s2Pos = data.length; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if (s1Pos == s2Pos) { + doubleCapcity(data, s1Pos, s2Pos); + } + s1Pos++; + data[s1Pos] = o; + } + + private void doubleCapcity(Object[] data, int s1Pos, int s2Pos) { + Object[] newData = new Object[2 * data.length]; + System.arraycopy(data, 0, newData, 0, s1Pos + 1); + System.arraycopy(data, s2Pos, newData, data.length + s2Pos, data.length - s2Pos); + this.s2Pos = data.length + s2Pos; + this.data = newData; + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if (s1Pos > -1) { + Object o = data[s1Pos]; + s1Pos--; + return o; + } + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + public Object peek1(){ + if (s1Pos > -1) { + return data[s1Pos]; + } + return null; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if (s1Pos == s2Pos - 1) { + doubleCapcity(data, s1Pos, s2Pos); + } + s2Pos--; + data[s2Pos] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if (s2Pos < data.length) { + Object o = data[s2Pos]; + s2Pos++; + return o; + } + return null; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if (s2Pos < data.length) { + return data[s2Pos]; + } + return null; + } + + @Test + public void testTwoStackInOneArray(){ + TwoStackInOneArray stack = new TwoStackInOneArray(); + System.out.println(stack.peek1()); + System.out.println(stack.peek2()); + System.out.println(stack.pop1()); + System.out.println(stack.pop2()); + + stack.push1(1); + stack.push1(2); + stack.push2(6); + stack.push2(5); + stack.push2(4); + stack.push2(3); + System.out.println(stack.pop1()); + System.out.println(stack.pop1()); + System.out.println(stack.pop1()); + System.out.println(stack.pop1()); + System.out.println(stack.pop2()); + System.out.println(stack.pop2()); + System.out.println(stack.pop2()); + System.out.println(stack.pop2()); + + } + +} diff --git a/group23/.DS_Store b/group23/.DS_Store deleted file mode 100644 index 7e3e6cfac4..0000000000 Binary files a/group23/.DS_Store and /dev/null differ diff --git a/group23/1028361767/Week1DataStructure/bin/com/coderising/litestruts/struts.xml b/group23/1028361767/Week1DataStructure/bin/com/coderising/litestruts/struts.xml deleted file mode 100644 index e5d9aebba8..0000000000 --- a/group23/1028361767/Week1DataStructure/bin/com/coderising/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/1028361767/Week1DataStructure/src/com/coderising/array/ArrayUtil.java b/group23/1028361767/Week1DataStructure/src/com/coderising/array/ArrayUtil.java deleted file mode 100644 index e497a8e251..0000000000 --- a/group23/1028361767/Week1DataStructure/src/com/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.coderising.array; - -import java.util.Arrays; - -public class ArrayUtil { - - /** - * 给定一个整形数组a , 对该数组的值进行置换 - 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] - 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * @param origin - * @return - */ - public int[] reverseArray(int[] origin){ - int len = origin.length; - int[] ret = new int[len]; - for(int i=0;i len1 && i2 > len2){ - break; - }else if(i1 > len1){ - ret[i++] = array2[i2++]; - }else{ - ret[i++] = array1[i1++]; - } - } - - } - if(sameNum > 0){ - ret = Arrays.copyOf(ret, ret.length - sameNum); - } - return ret; - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * @param oldArray - * @param size - * @return - */ - public int[] grow(int [] oldArray, int size){ - return Arrays.copyOf(oldArray, oldArray.length + size); - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - * @param max - * @return - */ - public int[] fibonacci(int max){ - if(max == 1){ - return new int[0]; - }else{ - int[] tmp = new int[max + 1]; - int x1 = 1, x2 = 1; - int i = 1, j = 0; - tmp[j++] = x1; - tmp[j++] = x2; - while(true){ - i = x1 + x2; - if(i > max){ - break; - } - x1 = x2; - x2 = i; - tmp[j++] = i; - } - return Arrays.copyOf(tmp, j); - } - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * @param max - * @return - */ - public int[] getPrimes(int max){ - int[] tmp = new int[max/2 + 1]; - boolean isPrime; - int k = 0; - for(int i=2;i - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/1028361767/Week1DataStructure/src/com/coding/basic/ArrayList.java b/group23/1028361767/Week1DataStructure/src/com/coding/basic/ArrayList.java deleted file mode 100644 index da0237bdf7..0000000000 --- a/group23/1028361767/Week1DataStructure/src/com/coding/basic/ArrayList.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.coding.basic; - -import java.util.Arrays; - -public class ArrayList implements List { - - private int size = 0; - - private int HALF_MAX_VALUE = Integer.MAX_VALUE; - - private Object[] elementData = new Object[100]; - - public void add(Object o) { - if (noSpace()) { - elementData = grow(); - } - elementData[size++] = o; - } - - public void add(int index, Object o) { - if (index < 0) { - throw new IllegalArgumentException("index must be positive integer"); - } - if (index > size) { - throw new IndexOutOfBoundsException("size is" + size); - } - if (noSpace()) { - elementData = grow(); - } - System.arraycopy(elementData, index, elementData, index + 1, size - index); - elementData[size++] = o; - } - - public Object get(int index) { - if (index < 0) { - throw new IllegalArgumentException("index must be positive integer"); - } - if (index > (size - 1)) { - throw new IndexOutOfBoundsException("size is" + size); - } - return elementData[index]; - } - - public Object remove(int index) { - if (index < 0) { - throw new IllegalArgumentException("index must be positive integer"); - } - if (index > (size - 1)) { - throw new IndexOutOfBoundsException("size is" + size); - } - Object obj = elementData[index]; - System.arraycopy(elementData, index + 1, elementData, index, size - index); - elementData[size-1] = null; - size--; - return obj; - } - - public int size() { - return size; - } - - public Iterator iterator() { - return null; - } - - private boolean noSpace() { - return size == elementData.length; - } - - private Object[] grow() { - int newSize; - if (size < HALF_MAX_VALUE) { - newSize = size * 2; - } else { - newSize = Integer.MAX_VALUE; - } - return Arrays.copyOf(elementData, newSize); - } - -} diff --git a/group23/1028361767/Week1DataStructure/src/com/coding/basic/LinkedList.java b/group23/1028361767/Week1DataStructure/src/com/coding/basic/LinkedList.java deleted file mode 100644 index 5e241db172..0000000000 --- a/group23/1028361767/Week1DataStructure/src/com/coding/basic/LinkedList.java +++ /dev/null @@ -1,244 +0,0 @@ -package com.coding.basic; - - -import java.util.NoSuchElementException; - -public class LinkedList implements List { - - private Node head; - private int size; - - public void add(Object o) { - Node newNode = new Node(o, null); - if (head == null) { - head = newNode; - } else { - Node tmp = head; - while (tmp.next != null) { - tmp = tmp.next; - } - tmp.next = newNode; - } - size++; - } - - public void add(int index, Object o) { - checkMinBound(index); - checkMaxBound(index, size); - Node newNode = new Node(o, null); - if (index == 0) { - newNode.next = head; - head = newNode; - } else { - int pos = 1; - Node tmp = head; - while (pos != index) { - tmp = tmp.next; - pos++; - } - newNode.next = tmp.next; - tmp.next = newNode; - } - size++; - - } - - private void checkMinBound(int index) { - if (index < 0) { - throw new IllegalArgumentException(); - } - } - - private void checkMaxBound(int index, int max) { - if (index > max) { - throw new IndexOutOfBoundsException(); - } - } - - - public Object get(int index) { - checkMinBound(index); - checkMaxBound(index, size - 1); - Node cur = head; - if (index != 0) { - int pos = 0; - do { - cur = cur.next; - pos++; - } while (pos != index); - } - return cur; - } - - public Object remove(int index) { - checkMinBound(index); - checkMaxBound(index, size - 1); - Node cur = head; - if (index == 0) { - head = cur.next; - } else { - int pos = 1; - Node prev = cur; - while (pos != index) { - prev = prev.next; - pos++; - } - cur = prev.next; - prev.next = cur.next; - } - size--; - return cur; - } - - public int size() { - return size; - } - - public void addFirst(Object o) { - Node newNode = new Node(o, null); - newNode.next = head; - head = newNode; - size++; - } - - public void addLast(Object o) { - Node newNode = new Node(o, null); - if (head == null) { - head = newNode; - } else { - Node tmp = head; - while (tmp.next != null) { - tmp = tmp.next; - } - tmp.next = newNode; - } - size++; - } - - public Object removeFirst() { - if (head == null) { - throw new NoSuchElementException(); - } - Node ret = head; - head = head.next; - size--; - return ret; - } - - public Object removeLast() { - if (head == null) { - throw new NoSuchElementException(); - } - Node ret; - if (head.next == null) { - ret = head; - head = null; - } else { - Node prev = head; - ret = head.next; - while (ret.next != null) { - prev = ret; - ret = ret.next; - } - prev.next = null; - } - size--; - return ret; - } - - public Iterator iterator() { - return null; - } - - - private static class Node { - Object data; - Node next; - - public Node(Object data, Node next) { - this.data = data; - this.next = next; - } - - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse() { - - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - */ - public void removeFirstHalf() { - - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * - * @param i - * @param length - */ - public void remove(int i, int length) { - - } - - /** - * 假定当前链表和list均包含已升序排列的整数 - * 从当前链表中取出那些list所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * - * @param list - */ - public static int[] getElements(LinkedList list) { - return null; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在list中出现的元素 - * - * @param list - */ - - public void subtract(LinkedList list) { - - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues() { - - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * - * @param min - * @param max - */ - public void removeRange(int min, int max) { - - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * - * @param list - */ - public LinkedList intersection(LinkedList list) { - return null; - } -} diff --git a/group23/1028361767/Week1DataStructure/src/com/coding/basic/Queue.java b/group23/1028361767/Week1DataStructure/src/com/coding/basic/Queue.java deleted file mode 100644 index bb24e2132e..0000000000 --- a/group23/1028361767/Week1DataStructure/src/com/coding/basic/Queue.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.coding.basic; - -public class Queue { - - private LinkedList linkedList = new LinkedList(); - - public void enQueue(Object o) { - linkedList.add(o); - } - - public Object deQueue() { - return linkedList.removeFirst(); - } - - public boolean isEmpty() { - return linkedList.size() == 0; - } - - public int size() { - return linkedList.size(); - } -} diff --git a/group23/1028361767/Week1DataStructure/src/com/coding/basic/Stack.java b/group23/1028361767/Week1DataStructure/src/com/coding/basic/Stack.java deleted file mode 100644 index 55c96985a9..0000000000 --- a/group23/1028361767/Week1DataStructure/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.coding.basic; - -import java.util.EmptyStackException; - -public class Stack { - private ArrayList elementData = new ArrayList(); - - public void push(Object o) { - elementData.add(o); - } - - public Object pop() { - checkBound(); - return elementData.get(size() - 1); - } - - public Object peek() { - checkBound(); - return elementData.remove(size() - 1); - } - - public boolean isEmpty() { - return size() == 0; - } - - public int size() { - return elementData.size(); - } - - private void checkBound() { - if (isEmpty()) { - throw new EmptyStackException(); - } - } -} diff --git a/group23/1028361767/Week1DataStructure/src/test/com/coding/basic/TestArrayList.java b/group23/1028361767/Week1DataStructure/src/test/com/coding/basic/TestArrayList.java deleted file mode 100644 index 61562d2a39..0000000000 --- a/group23/1028361767/Week1DataStructure/src/test/com/coding/basic/TestArrayList.java +++ /dev/null @@ -1,60 +0,0 @@ -package test.com.coding.basic; - -import com.coding.basic.ArrayList; -import org.junit.Assert; -import org.junit.Test; - -public class TestArrayList { - - @Test - public void testAdd() { - ArrayList list = new ArrayList(); - int i = 0; - for (; i < 1000; i++) { - list.add(new Object()); - } - Assert.assertTrue(list.size() == i); - } - - @Test - public void testGet() { - ArrayList list = new ArrayList(); - int i = 0; - for (; i < 10; i++) { - list.add(new Object()); - } - Assert.assertFalse(list.get(5) == null); - try { - list.get(10); - Assert.assertTrue(false); - } catch (IndexOutOfBoundsException e) { - Assert.assertTrue(true); - } - } - - @Test - public void testAddWithIndex() { - ArrayList list = new ArrayList(); - int i = 0; - for (; i < 10; i++) { - list.add(new Object()); - } - Object obj = list.get(5); - list.add(5, new Object()); - Assert.assertTrue(list.size() == (i + 1)); - Assert.assertTrue(obj == list.get(6)); - } - - @Test - public void testRemove() { - ArrayList list = new ArrayList(); - int i = 0; - for (; i < 10; i++) { - list.add(i); - } - Object tempObj = list.get(5); - Assert.assertTrue(tempObj == list.remove(5)); - Assert.assertTrue(list.size() == (i - 1)); - Assert.assertTrue((int) list.get(list.size() - 1) == (i - 1)); - } -} diff --git a/group23/1028361767/data-structure/src/com/coderising/download/DownloadThread.java b/group23/1028361767/data-structure/src/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..8cf0ae1e42 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coderising/download/DownloadThread.java @@ -0,0 +1,31 @@ +package com.coderising.download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.coderising.download.api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + public DownloadThread( Connection conn, int startPos, int endPos){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + public void run(){ + try { + byte[] bytes = conn.read(startPos, endPos); + RandomAccessFile file = new RandomAccessFile("/Users/jie/Desktop/test.png", "rw"); + file.seek(startPos); + file.write(bytes); + file.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/group23/1028361767/data-structure/src/com/coderising/download/FileDownloader.java b/group23/1028361767/data-structure/src/com/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..1fe4ebb159 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coderising/download/FileDownloader.java @@ -0,0 +1,104 @@ +package com.coderising.download; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + Thread[] threads = new Thread[3]; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + int size = length / 3; + int remain = length - size; + + for(int i=0;i<3;i++){ + conn = cm.open(this.url); + int startPos = i*size; + int endPos = (i+1) * size - 1; + if(i == 2){ + endPos = (i+1) * size - 1 + remain; + } + threads[i] = new DownloadThread(conn,startPos,endPos); + threads[i].start(); + } + + new Thread(new Runnable(){ + public void run(){ + boolean finish; + do{ + finish = true; + for(int i=0;i size) { + throw new IndexOutOfBoundsException("size is" + size); + } + if (noSpace()) { + elementData = grow(); + } + System.arraycopy(elementData, index, elementData, index + 1, size - index); + elementData[size++] = o; + } + + public Object get(int index) { + if (index < 0) { + throw new IllegalArgumentException("index must be positive integer"); + } + if (index > (size - 1)) { + throw new IndexOutOfBoundsException("size is" + size); + } + return elementData[index]; + } + + public Object remove(int index) { + if (index < 0) { + throw new IllegalArgumentException("index must be positive integer"); + } + if (index > (size - 1)) { + throw new IndexOutOfBoundsException("size is" + size); + } + Object obj = elementData[index]; + System.arraycopy(elementData, index + 1, elementData, index, size - index); + elementData[size-1] = null; + size--; + return obj; + } + + public int size() { + return size; + } + + public Iterator iterator() { + return null; + } + + private boolean noSpace() { + return size == elementData.length; + } + + private Object[] grow() { + int newSize; + if (size < HALF_MAX_VALUE) { + newSize = size * 2; + } else { + newSize = Integer.MAX_VALUE; + } + return Arrays.copyOf(elementData, newSize); + } + +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/array/ArrayUtil.java b/group23/1028361767/data-structure/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..8e1b170dc0 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,210 @@ +package com.coding.basic.array; + +import java.util.Arrays; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public int[] reverseArray(int[] origin){ + int len = origin.length; + int[] ret = new int[len]; + for(int i=0;i len1 && i2 > len2){ + break; + }else if(i1 > len1){ + ret[i++] = array2[i2++]; + }else{ + ret[i++] = array1[i1++]; + } + } + + } + if(sameNum > 0){ + ret = Arrays.copyOf(ret, ret.length - sameNum); + } + return ret; + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + return Arrays.copyOf(oldArray, oldArray.length + size); + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + if(max == 1){ + return new int[0]; + }else{ + int[] tmp = new int[max + 1]; + int x1 = 1, x2 = 1; + int i = 1, j = 0; + tmp[j++] = x1; + tmp[j++] = x2; + while(true){ + i = x1 + x2; + if(i > max){ + break; + } + x1 = x2; + x2 = i; + tmp[j++] = i; + } + return Arrays.copyOf(tmp, j); + } + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + int[] tmp = new int[max/2 + 1]; + boolean isPrime; + int k = 0; + for(int i=2;i max) { + throw new IndexOutOfBoundsException(); + } + } + + + public Object get(int index) { + checkMinBound(index); + checkMaxBound(index, size - 1); + Node cur = head; + if (index != 0) { + int pos = 0; + do { + cur = cur.next; + pos++; + } while (pos != index); + } + return cur.data; + } + + public Object remove(int index) { + checkMinBound(index); + checkMaxBound(index, size - 1); + Node cur = head; + if (index == 0) { + head = cur.next; + } else { + int pos = 1; + Node prev = cur; + while (pos != index) { + prev = prev.next; + pos++; + } + cur = prev.next; + prev.next = cur.next; + } + size--; + return cur.data; + } + + public int size() { + return size; + } + + public void addFirst(Object o) { + Node newNode = new Node(o, null); + newNode.next = head; + head = newNode; + size++; + } + + public void addLast(Object o) { + Node newNode = new Node(o, null); + if (head == null) { + head = newNode; + } else { + Node tmp = head; + while (tmp.next != null) { + tmp = tmp.next; + } + tmp.next = newNode; + } + size++; + } + + public Object removeFirst() { + if (head == null) { + throw new NoSuchElementException(); + } + Node ret = head; + head = head.next; + size--; + return ret.data; + } + + public Object removeLast() { + if (head == null) { + throw new NoSuchElementException(); + } + Node ret; + if (head.next == null) { + ret = head; + head = null; + } else { + Node prev = head; + ret = head.next; + while (ret.next != null) { + prev = ret; + ret = ret.next; + } + prev.next = null; + } + size--; + return ret.data; + } + + public Iterator iterator() { + return null; + } + + + private static class Node { + Object data; + Node next; + + public Node(Object data, Node next) { + this.data = data; + this.next = next; + } + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + if(size == 0 || size == 1){ + return ; + } + Node node = head; + Node nextNode = head.next; + Node tmp; + node.next = null; + do{ + tmp = nextNode.next; + nextNode.next = node; + node = nextNode; + nextNode = tmp; + }while(nextNode != null); + head = node; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + if(size == 0 || size == 1){ + return ; + } + int num = size / 2; + size -= num; + Node node = head; + while(num > 0){ + node = node.next; + num--; + } + head = node; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + checkMinBound(i); + checkMaxBound(i + length, size); + Node prev = null; + Node node = head; + int index = 0; + while(index < i){ + prev = node; + node = node.next; + index++; + } + Node nextNode = node.next; + while(index < (i + length - 1)){ + nextNode = nextNode.next; + index++; + } + size -= length; + if(i == 0){ + head = nextNode; + }else{ + prev.next = nextNode; + head = prev; + } + } + + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + */ + public int[] getElements(LinkedList list) { + int[] ret = new int[list.size()]; + if(ret.length == 0){ + return ret; + } + int index; + int j = 0; + Node node = head; + for(int i=0;i min){ + foundMin = true; + } + if(foundMin && (int)node.data > max){ + break; + } + if(foundMin == false){ + prev = node; + }else{ + size -= 1; + } + node = node.next; + }while(node != null); + if(prev == null){ + head = node; + }else{ + prev.next = node; + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList ret = new LinkedList(); + Node node = head; + int nodeValue; + int elementValue; + for(int i=0;i elementValue){ + break; + } + node = node.next; + } + } + } + return ret; + } + + public String toString(){ + Node node = head; + StringBuilder sb = new StringBuilder(); + if(node == null){ + return ""; + }else{ + sb.append(head.data); + while((node = node.next) != null){ + sb.append(",").append(node.data); + } + return sb.toString(); + } + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/queue/CircleQueue.java b/group23/1028361767/data-structure/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..eeed686419 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,57 @@ +package com.coding.basic.queue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + private int maxSize = DEFAULT_SIZE; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public CircleQueue(int maxSize){ + elementData = new Object[maxSize]; + this.maxSize = maxSize; + } + + public boolean isEmpty() { + return rear == front; + + } + + public int size() { + return rear - front; + } + + + + public void enQueue(E data) { + if((rear+1)%maxSize == front){ + throw new FullQueueException(); + } + elementData[rear] = data; + rear = (rear + 1) % maxSize; + } + + public E deQueue() { + if(rear == front){ + throw new EmptyQueueException(); + } + E data = (E)elementData[front]; + elementData[front] = null; + front = (front + 1) % maxSize; + return data; + } + +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/queue/EmptyQueueException.java b/group23/1028361767/data-structure/src/com/coding/basic/queue/EmptyQueueException.java new file mode 100644 index 0000000000..925c9de7ec --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/queue/EmptyQueueException.java @@ -0,0 +1,14 @@ +package com.coding.basic.queue; + +public class EmptyQueueException extends RuntimeException { + + private static final long serialVersionUID = 7013504079461713464L; + + public EmptyQueueException() { + super(); + } + + public EmptyQueueException(String message) { + super(message); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/queue/FullQueueException.java b/group23/1028361767/data-structure/src/com/coding/basic/queue/FullQueueException.java new file mode 100644 index 0000000000..96cc1ab4fb --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/queue/FullQueueException.java @@ -0,0 +1,14 @@ +package com.coding.basic.queue; + +public class FullQueueException extends RuntimeException { + + private static final long serialVersionUID = 5782713639805661798L; + + public FullQueueException() { + super(); + } + + public FullQueueException(String message) { + super(message); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/queue/Josephus.java b/group23/1028361767/data-structure/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..8400d503b4 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,32 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +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){ + List numbers = new ArrayList<>(); + CircleQueue queue = new CircleQueue<>(n+1); + 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/group23/1028361767/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group23/1028361767/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..d56e7b97ff --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,54 @@ +package com.coding.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.size() == 0; + } + + + + public int size() { + return stack1.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + E data = stack2.pop(); + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + return data; + } + + + + } + diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/QuickMinStack.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..a04191da19 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack; + +import java.util.Arrays; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + int[] datas = new int[10]; + int size; + int minIndex; + + public void push(int data){ + checkAndresize(); + datas[size] = data; + if(datas[minIndex] > data){ + minIndex = size; + } + size++; + } + + public int pop(){ + checkOutBound(); + return datas[size-1]; + } + public int findMin(){ + checkOutBound(); + return datas[minIndex]; + } + + private void checkAndresize() { + if(size == datas.length){ + datas = Arrays.copyOf(datas, datas.length*2); + } + } + private void checkOutBound(){ + if(size <= 0){ + throw new IndexOutOfBoundsException(); + } + } +} \ No newline at end of file diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/Stack.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..58a4846f2b --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,47 @@ +package com.coding.basic.stack; + +import java.util.EmptyStackException; + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o) { + elementData.add(o); + } + + public Object pop() { + checkBound(); + return elementData.remove(size() - 1); + } + + public Object peek() { + checkBound(); + return elementData.get(size() - 1); + } + + public boolean isEmpty() { + return size() == 0; + } + + public int size() { + return elementData.size(); + } + + private void checkBound() { + if (isEmpty()) { + throw new EmptyStackException(); + } + } + + public String toString(){ + StringBuilder sb = new StringBuilder(); + for(int i=0;i i) { + tmp.push(s.pop()); + } + s.push(top); + while(tmp.size() > 0){ + s.push(tmp.pop()); + } + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + Stack tmp = new Stack(); + boolean found = false; + while(!s.isEmpty() && !found){ + Object obj = s.pop(); + if(obj == o){ + found = true; + }else{ + tmp.push(obj); + } + } + while(!tmp.isEmpty()) + s.push(tmp.pop()); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + Object[] objs = new Object[len]; + if(s.isEmpty() || len == 0) + return objs; + int i = 0; + while(i < len && !s.isEmpty()){ + objs[i++] = s.pop(); + } + for(i=objs.length-1;i>=0;i--) + s.push(objs[i]); + return objs; + } + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * + * ( 40 ) 41 [ 91 ] 93 {123 }125 + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + if(s == null || s.length() == 0) + return true; + Stack stack = new Stack(); + char[] chars = s.toCharArray(); + for(int i=0;i queue1 = new LinkedList(); + Queue queue2 = new LinkedList(); + + public void push(int data) { + queue1.add(data); + } + + public int pop() { + while(queue1.size() > 1){ + queue2.add(queue1.poll()); + } + queue1.addAll(queue2); + return queue1.poll(); + } + + public static void main(String[] args) { + StackWithTwoQueues s = new StackWithTwoQueues(); + for (int i = 0; i < 5; i++) { + s.push(i); + } + System.out.println(s.pop()); + System.out.println(s.pop()); + System.out.println(s.pop()); + System.out.println(s.pop()); + } + +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..2173d65b5a --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,108 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + int front; + int rear; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + checkInBound(); + data[front++] = o; + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + checkOutBound(front); + Object o = data[--front]; + data[front] = null; + return o; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + checkOutBound(front); + return data[front-1]; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + checkInBound(); + data[data.length-rear-1] = o; + rear++; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + checkOutBound(rear); + int index = data.length-rear; + Object o = data[index]; + data[index] = null; + rear--; + return o; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + checkOutBound(rear); + return data[data.length-rear]; + } + + private Object[] resize(int len) { + int newLen = len * 2; + Object[] newData = new Object[newLen]; + if(front > 0){ + System.arraycopy(data, 0, newData, 0, front); + } + if(rear > 0){ + System.arraycopy(data, len-rear, newData, newLen-rear, rear); + } + return newData; + } + + private void checkOutBound(int index){ + if(index <= 0){ + throw new IndexOutOfBoundsException(); + } + } + + private void checkInBound() { + if((front+rear) >= data.length){ + data = resize(data.length); + } + } + + public static void main(String[] args) { + TwoStackInOneArray t = new TwoStackInOneArray(); + for(int i=0;i<25;i++){ + t.push1(i); + t.push2(i); + } + System.out.println(t.front+t.rear); + for(int i=0;i 1){ +// doAddOrSubOps(numStack, opStack); +// } +// return new Float((String)numStack.pop()); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + + + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + + for(Token token : tokens){ + + if (token.isOperator()){ + + if(opStack.isEmpty()){ + + opStack.push(token); + } else{ + + while(!opStack.isEmpty() + && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(), f1,f2); + numStack.push(result); + + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + + while(!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(), f1,f2)); + } + + + return numStack.pop().floatValue(); + } + + /** + * 多个加减 + * @param numStack + * @param opStack + */ + private void doAddOrSubOps(Stack numStack, Stack opStack) { + Stack calStack = new Stack(); + while(numStack.size() > 1){ + calStack.push(numStack.pop()); + calStack.push(opStack.pop()); + } + float num1 = new Float((String)numStack.pop()); + float num2; + while(calStack.size() > 0){ + String op = (String)calStack.pop(); + num2 = new Float((String)calStack.pop()); + if("+".equals(op)){ + num1 += num2; + }else{ + num1 -= num2; + } + } + numStack.push(num1 + ""); + } + + /** + * 单个乘除 + * @param numStack + * @param op + */ + private void doMulOrDivOp(Stack numStack, String op){ + float num2 = new Float((String)numStack.pop()); + float num1 = new Float((String)numStack.pop()); + String result = null; + if("*".equals(op)){ + result = (num1 * num2) + ""; + }else{ + result = (num1 / num2) + ""; + } + numStack.push(result); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } +} \ No newline at end of file diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..1d679bdb32 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} \ No newline at end of file diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..a518e43c13 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,44 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class InfixToPostfix { + + public static List convert(String expr) { + // 3*20+12*5-40/2 --> 3 20 * 12 5 * + 40 2 / - + // 10-30+50 --> 10 30 - 50 + + List ret = new ArrayList<>(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + Stack opStack = new Stack<>(); + for(Token token : tokens){ + if(token.isNumber()){ + ret.add(token); + }else{ + while(!opStack.isEmpty() && opStack.peek().hasHigherPriority(token)){ + ret.add(opStack.pop()); + } + opStack.push(token); + } + } + while(!opStack.isEmpty()){ + ret.add(opStack.pop()); + } + return ret; + } + + public static String toString(List tokens){ + StringBuilder sb = new StringBuilder(); + for(Token token : tokens){ + sb.append(token.value); + } + return sb.toString(); + } + + public static void main(String[] args) { + System.out.println(toString(convert("10-30+50"))); + System.out.println(toString(convert("3*20+12*5-40/2"))); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..d4af19f583 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,62 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + Stack numStack = new Stack<>(); + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(expr); + for(Token token : tokens) { + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + }else{ + String op = token.value; + float num2 = numStack.pop(); + float num1 = numStack.pop(); + float result = calculate(op, num1, num2); + numStack.push(result); + } + } + return numStack.pop(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + private void reverse(Stack s){ + Stack tmp = new Stack(); + int len = s.size(); + for(int i=0;i i) { + tmp.push(s.pop()); + } + s.push(top); + while(tmp.size() > 0){ + s.push(tmp.pop()); + } + } + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..ad2b6dfd69 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,42 @@ +package com.coding.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() { + { + // 6*(3+5+(2+3)*8) + 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/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..b5264d1362 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,85 @@ +package com.coding.basic.stack.expr; + +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack opStack = new Stack<>(); + Stack numStack = new Stack<>(); + int preContinueOp = 0; + int preContinueNum = 0; + for(Token token : tokens){ + if(token.isOperator()) { + opStack.push(token); + if(preContinueNum > 0){ + preContinueNum = 0; + preContinueOp = 1; + }else{ + preContinueOp++; + } + }else{ + numStack.push(new Float(token.getIntValue())); + preContinueNum++; + } + if(preContinueNum >= 2 && preContinueOp > 0){ + float num2 = numStack.pop(); + float num1 = numStack.pop(); + float result = calculate(opStack.pop().value, num1, num2); + numStack.push(result); + preContinueNum--; + preContinueOp--; + } + } + if(!opStack.isEmpty()){ + reverse(numStack); + } + while(!opStack.isEmpty()) { + String op = opStack.pop().value; + float num1 = numStack.pop(); + float num2 = numStack.pop(); + float result = calculate(op, num1, num2); + numStack.push(result); + } + return numStack.pop(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + + private void reverse(Stack s){ + Stack tmp = new Stack(); + int len = s.size(); + for(int i=0;i i) { + tmp.push(s.pop()); + } + s.push(top); + while(tmp.size() > 0){ + s.push(tmp.pop()); + } + } + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/Token.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParser.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..bf62a9df26 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,64 @@ +package com.coding.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(isBlank(c)){ + i++; + continue; + } + else 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); + } + + private boolean isBlank(char c){ + return c == 32; + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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"); + + 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/group23/1028361767/data-structure/src/com/coding/me/Palindrome.java b/group23/1028361767/data-structure/src/com/coding/me/Palindrome.java new file mode 100644 index 0000000000..2de0c4370d --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/me/Palindrome.java @@ -0,0 +1,82 @@ +package com.coding.me; + +/** + * 回文 + * + */ +public class Palindrome { + + private static String oddCase(char[] chars, int index) { + int maxLength = 1; + int i = 1; + while((index - i) >= 0 && (index + i) < chars.length - 1){ + if(chars[index - i] != chars[index + i]){ + break; + } + maxLength += 2; + i++; + } + return String.valueOf(chars, index + 1 - i, maxLength); + } + + private static String evenCase(char[] chars, int index) { + int maxLength = 0; + int i = 0; + while((index - i) >= 0 && (index + 1 + i) <= chars.length - 1){ + if(chars[index - i] != chars[index + 1 + i]){ + break; + } + i++; + maxLength += 2; + } + return String.valueOf(chars, index + 1 - i, maxLength); + } + + public static String findLongestPalindrome(String s){ + char[] chars = s.toCharArray(); + String longestPalindrome = ""; + String tmp = ""; + for(int i=0;i= 10){ + carry = 1; + sum -= 10; + }else{ + carry = 0; + } + if(ret == null){ + ret = new ListNode(sum); + first = ret; + }else{ + ret.next = new ListNode(sum); + ret = ret.next; + } + if(l1 != null){ + l1 = l1.next; + } + if(l2 != null){ + l2 = l2.next; + } + } + if(carry > 0){ + ret.next = new ListNode(carry); + } + return first; + } + + public ListNode leetcodeSolution(ListNode l1, ListNode l2) { + ListNode dummyHead = new ListNode(0); + ListNode p = l1, q = l2, curr = dummyHead; + int carry = 0; + while (p != null || q != null) { + int x = (p != null) ? p.val : 0; + int y = (q != null) ? q.val : 0; + int sum = carry + x + y; + carry = sum / 10; + curr.next = new ListNode(sum % 10); + curr = curr.next; + if (p != null) p = p.next; + if (q != null) q = q.next; + } + if (carry > 0) { + curr.next = new ListNode(carry); + } + return dummyHead.next; + } + + public static void main(String[] args) { + ListNode l11 = new ListNode(2); + ListNode l12 = new ListNode(4); + ListNode l13 = new ListNode(3); + l11.next = l12; + l12.next = l13; + + ListNode l21 = new ListNode(5); + ListNode l22 = new ListNode(6); + ListNode l23 = new ListNode(4); + l21.next = l22; + l22.next = l23; + + ListNode ret = new AddTwoNums().mySolution(l11, l21); + while(ret != null){ + System.out.println(ret.val); + ret = ret.next; + } + } +} + +class ListNode { + int val; + ListNode next; + ListNode(int x) { val = x; } +} diff --git a/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/LongestCommonPrefix.java b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/LongestCommonPrefix.java new file mode 100644 index 0000000000..910241063f --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/LongestCommonPrefix.java @@ -0,0 +1,223 @@ +package com.coding.me.leetcode.algorithms; + +/** + * Write a function to find the longest common prefix string amongst an array of strings. + * ["a", "b"] return "" + * ["a", "a"] return "a" + * ["ac", "ac", "a", "a"] return "a" + * + */ +public class LongestCommonPrefix { + + public static String mySolution(String[] strs){ + if(strs.length == 0) return ""; + char[] chars = strs[0].toCharArray(); + int count = chars.length; + if(count == 0) return ""; + char[] tmp; + for(int i = 1;i set = new HashSet<>(); + for (int i = start; i < end; i++) { + Character ch = s.charAt(i); + if (set.contains(ch)) return false; + set.add(ch); + } + return true; + } + + /** + * Sliding Window + * The naive approach is very straightforward. But it is too slow. So how + * can we optimize it? + * + * In the naive approaches, we repeatedly check a substring to see if it has + * duplicate character. But it is unnecessary. If a substring S​ij ​​ from + * index i i to j 1 j−1 is already checked to have no duplicate characters. + * We only need to check if s[j] is already in the substring S​ij ​​ . + * + * To check if a character is already in the substring, we can scan the + * substring, which leads to an O(n^2) algorithm. But we can do better. + * + * By using HashSet as a sliding window, checking if a character in the + * current can be done in O 1 O(1). + * + * A sliding window is an abstract concept commonly used in array/string + * problems. A window is a range of elements in the array/string which + * usually defined by the start and end indices, i.e. i j [i,j) + * (left-closed, right-open). A sliding window is a window "slides" its two + * boundaries to the certain direction. For example, if we slide i j [i,j) + * to the right by 1 1 element, then it becomes i 1 j 1 [i+1,j+1) + * (left-closed, right-open). + * + * Back to our problem. We use HashSet to store the characters in current + * window i j [i,j) ( j i j=i initially). Then we slide the index j j to the + * right. If it is not in the HashSet, we slide j j further. Doing so until + * s[j] is already in the HashSet. At this point, we found the maximum size + * of substrings without duplicate characters start with index i i. If we do + * this for all i i, we get our answer. + * + * Time complexity : O(2n)=O(n). In the worst case each character will be + * visited twice by i and j. + * + * Space complexity : O(min(m,n)). Same as the previous approach. We need + * O(k) space for the sliding window, where k is the size of the Set. The + * size of the Set is upper bounded by the size of the string n n and the + * size of the charset/alphabet m m. + * + * @param s + * @return + */ + public int leetcodeSolution2(String s) { + int n = s.length(); + Set set = new HashSet<>(); + int ans = 0, i = 0, j = 0; + while (i < n && j < n) { + // try to extend the range [i, j] + if (!set.contains(s.charAt(j))){ + set.add(s.charAt(j++)); + ans = Math.max(ans, j - i); + } + else { + set.remove(s.charAt(i++)); + } + } + return ans; + } + + /** + * Sliding Window Optimized + * + * The above solution requires at most 2n steps. In fact, it could be + * optimized to require only n steps. Instead of using a set to tell if a + * character exists or not, we could define a mapping of the characters to + * its index. Then we can skip the characters immediately when we found a + * repeated character. + * + * The reason is that if s[j] have a duplicate in the range [i,j) + * with index j ​′ ​​ , we don't need to increase i little by little. + * We can skip all the elements in the range [i,j ​′ ​​ ] and let i i + * to be j ​′+1 directly. + * + * @param s + * @return + */ + public int leetCodeSolution3(String s){ + int n = s.length(), ans = 0; + Map map = new HashMap<>(); // current index of character + // try to extend the range [i, j] + for (int j = 0, i = 0; j < n; j++) { + if (map.containsKey(s.charAt(j))) { + i = Math.max(map.get(s.charAt(j)), i); + } + ans = Math.max(ans, j - i + 1); + map.put(s.charAt(j), j + 1); + } + return ans; + } + + /** + * Java (Assuming ASCII 128) + * + * The previous implements all have no assumption on the charset of the + * string s. + * + * If we know that the charset is rather small, we can replace the Map with + * an integer array as direct access table. + * + * Commonly used tables are: + * + * int[26] for Letters 'a' - 'z' or 'A' - 'Z' + * int[128] for ASCII + * int[256] for Extended ASCII + * + * @param s + * @return + */ + public int leetCodeSolution4(String s) { + int n = s.length(), ans = 0; + int[] index = new int[128]; // current index of character + // try to extend the range [i, j] + for (int j = 0, i = 0; j < n; j++) { + i = Math.max(index[s.charAt(j)], i); + ans = Math.max(ans, j - i + 1); + index[s.charAt(j)] = j + 1; + } + return ans; + } + + + private LongestSubstringWithoutRepeatingCharacters lswrc; + @Before + public void setup(){ + lswrc = new LongestSubstringWithoutRepeatingCharacters(); + } + + @Test + public void testMySolution(){ + Assert.assertEquals(3, lswrc.mySolution("abcabcbb")); + Assert.assertEquals(4, lswrc.mySolution("abcdabcdbbd")); + } + + @Test + public void testLeetcodeSolution3(){ + Assert.assertEquals(3, lswrc.leetCodeSolution3("abcabcbb")); + Assert.assertEquals(4, lswrc.leetCodeSolution3("abcdabcdbbd")); + } + + @Test + public void testLeetcodeSolution4(){ + Assert.assertEquals(3, lswrc.leetCodeSolution4("abcabcbb")); +// Assert.assertEquals(4, lswrc.leetCodeSolution4("abcdabcdbbd")); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/MedianOfTwoSortedArrays.java b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/MedianOfTwoSortedArrays.java new file mode 100644 index 0000000000..b80850e24a --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/MedianOfTwoSortedArrays.java @@ -0,0 +1,102 @@ +package com.coding.me.leetcode.algorithms; + +import org.junit.Before; +import org.junit.Test; + +/** + * There are two sorted arrays nums1 and nums2 of size m and n respectively. + * + * Find the median of the two sorted arrays. The overall run time complexity + * should be O(log (m+n)). + * + * Example 1: nums1 = [1, 3] nums2 = [2] + * + * The median is 2.0 Example 2: nums1 = [1, 2] nums2 = [3, 4] + * + * The median is (2 + 3)/2 = 2.5 + * + * @author hewj + * + */ +public class MedianOfTwoSortedArrays { + + public double mySolution(int[] nums1, int[] nums2) { + int[] nums = new int[nums1.length + nums2.length]; + int mid = nums.length/2; + int remain = nums.length%2; + int i=0,j=0; + int a,b; + int k=0; + while(i n) + return findKthSmallest(b, n, begin2, a, m, begin1, k); + if (m == 0) + return b[begin2 + k - 1]; + if (k == 1) + return Integer.min(a[begin1], b[begin2]); + int partA = Integer.min(k / 2, m), partB = k - partA; + if (a[begin1 + partA - 1] == b[begin2 + partB - 1]) + return a[begin1 + partA - 1]; + else if (a[begin1 + partA - 1] > b[begin2 + partB - 1]) + return findKthSmallest(a, m, begin1, b, n - partB, begin2 + partB, k - partB); + else + return findKthSmallest(a, m - partA, begin1 + partA, b, n, begin2, k - partA); + + } + + private MedianOfTwoSortedArrays motsa; + + @Before + public void setup(){ + motsa = new MedianOfTwoSortedArrays(); + } + + @Test + public void testMySolution(){ + int[] nums1 = {2}; + int[] nums2 = {1,3}; + System.out.println(motsa.mySolution(nums1, nums2)); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/OptimalDivision.java b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/OptimalDivision.java new file mode 100644 index 0000000000..8821941630 --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/OptimalDivision.java @@ -0,0 +1,76 @@ +package com.coding.me.leetcode.algorithms; + +/** + * Given a list of positive integers, the adjacent integers will perform the + * float division. For example, [2,3,4] -> 2 / 3 / 4. + * + * However, you can add any number of parenthesis at any position to change the + * priority of operations. You should find out how to add parenthesis to get the + * maximum result, and return the corresponding expression in string format. + * Your expression should NOT contain redundant parenthesis. + * + * Example: Input: [1000,100,10,2] Output: "1000/(100/10/2)" Explanation: + * 1000/(100/10/2) = 1000/((100/10)/2) = 200 However, the bold parenthesis in + * "1000/((100/10)/2)" are redundant, since they don't influence the operation + * priority. So you should return "1000/(100/10/2)". + * + * Other cases: 1000/(100/10)/2 = 50 1000/(100/(10/2)) = 50 1000/100/10/2 = 0.5 + * 1000/100/(10/2) = 2 Note: + * + * The length of the input array is [1, 10]. Elements in the given array will be + * in range [2, 1000]. There is only one optimal division for each test case. + * + * @author hewj + * + */ +public class OptimalDivision { + + public static String mySolution(int[] nums) { + if(nums.length == 0 || nums.length > 10) { + return ""; + } + if(nums.length == 1) { + return "" + nums[0]; + } + straightInsertionSort(nums); + StringBuilder sb = new StringBuilder(); + sb.append(nums[0]).append("/"); + if(nums.length == 2){ + sb.append(nums[1]); + }else{ + sb.append("("); + for(int k=1;k lList = new ArrayList<>(); + for(int i=0;i 1 || lList.size() > 2){ + return false; + } + } + return true; + } + + public static void main(String[] args) { + System.out.println(mySolution("LPLPLPLPLPL")); + } +} diff --git a/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/TwoSum.java b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/TwoSum.java new file mode 100644 index 0000000000..d91eb869fb --- /dev/null +++ b/group23/1028361767/data-structure/src/com/coding/me/leetcode/algorithms/TwoSum.java @@ -0,0 +1,102 @@ +package com.coding.me.leetcode.algorithms; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Given an array of integers, return indices of the two numbers such that + * they add up to a specific target. + * + * You may assume that each input would have exactly one solution, and you + * may not use the same element twice. + * + * Example: Given nums = [2, 7, 11, 15], target = 9, + * + * Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1]. Subscribe to see + * which companies asked this question. + */ +public class TwoSum { + /** + * Time complexity : O(n^2) + * Space complexity : O(1) + * @param nums + * @param target + * @return + */ + public int[] mySolution(int[] nums, int target) { + int[] ret = new int[2]; + for(int i=0;i map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + map.put(nums[i], i); + } + for (int i = 0; i < nums.length; i++) { + int complement = target - nums[i]; + if (map.containsKey(complement) && map.get(complement) != i) { + return new int[] { i, map.get(complement) }; + } + } + throw new IllegalArgumentException("No two sum solution"); + } + + /** + * one pass hash table + * Time complexity : O(n) + * Space complexity : O(n) + * @param nums + * @param target + * @return + */ + public int[] leetCodeSolution2(int[] nums, int target) { + Map map = new HashMap<>(); + for (int i = 0; i < nums.length; i++) { + int complement = target - nums[i]; + if (map.containsKey(complement)) { + return new int[] { map.get(complement), i }; + } + map.put(nums[i], i); + } + throw new IllegalArgumentException("No two sum solution"); + } + + + public static void main(String[] args) throws InterruptedException { +// String s = new String("字符串在内存中"); + List s = new ArrayList(); + s.add(new Object()); + WeakReference wr = new WeakReference(s.get(0)); + +// Thread.sleep(500); + System.out.println(wr.get()); + + s.remove(0); + System.gc(); + + System.out.println(wr.get()); +// Thread.sleep(500); +// System.out.println(wr.get()); + } +} diff --git a/group23/1028361767/data-structure/src/test/com/coding/basic/TestArrayList.java b/group23/1028361767/data-structure/src/test/com/coding/basic/TestArrayList.java new file mode 100644 index 0000000000..791157d0d6 --- /dev/null +++ b/group23/1028361767/data-structure/src/test/com/coding/basic/TestArrayList.java @@ -0,0 +1,61 @@ +package test.com.coding.basic; + +import org.junit.Assert; +import org.junit.Test; + +import com.coding.basic.array.ArrayList; + +public class TestArrayList { + + @Test + public void testAdd() { + ArrayList list = new ArrayList(); + int i = 0; + for (; i < 1000; i++) { + list.add(new Object()); + } + Assert.assertTrue(list.size() == i); + } + + @Test + public void testGet() { + ArrayList list = new ArrayList(); + int i = 0; + for (; i < 10; i++) { + list.add(new Object()); + } + Assert.assertFalse(list.get(5) == null); + try { + list.get(10); + Assert.assertTrue(false); + } catch (IndexOutOfBoundsException e) { + Assert.assertTrue(true); + } + } + + @Test + public void testAddWithIndex() { + ArrayList list = new ArrayList(); + int i = 0; + for (; i < 10; i++) { + list.add(new Object()); + } + Object obj = list.get(5); + list.add(5, new Object()); + Assert.assertTrue(list.size() == (i + 1)); + Assert.assertTrue(obj == list.get(6)); + } + + @Test + public void testRemove() { + ArrayList list = new ArrayList(); + int i = 0; + for (; i < 10; i++) { + list.add(i); + } + Object tempObj = list.get(5); + Assert.assertTrue(tempObj == list.remove(5)); + Assert.assertTrue(list.size() == (i - 1)); + Assert.assertTrue((int) list.get(list.size() - 1) == (i - 1)); + } +} diff --git a/group23/1028361767/Week1DataStructure/src/test/com/coding/basic/TestBinaryTreeNode.java b/group23/1028361767/data-structure/src/test/com/coding/basic/TestBinaryTreeNode.java similarity index 100% rename from group23/1028361767/Week1DataStructure/src/test/com/coding/basic/TestBinaryTreeNode.java rename to group23/1028361767/data-structure/src/test/com/coding/basic/TestBinaryTreeNode.java diff --git a/group23/1028361767/data-structure/src/test/com/coding/basic/TestLinkedList.java b/group23/1028361767/data-structure/src/test/com/coding/basic/TestLinkedList.java new file mode 100644 index 0000000000..3a4a79ba0d --- /dev/null +++ b/group23/1028361767/data-structure/src/test/com/coding/basic/TestLinkedList.java @@ -0,0 +1,176 @@ +package test.com.coding.basic; + +import static org.junit.Assert.fail; + +import org.junit.Assert; +import org.junit.Test; + +import com.coding.basic.linklist.LinkedList; + +public class TestLinkedList { + + @Test + public void testReverse(){ + LinkedList list = new LinkedList(); + list.add(3); + list.add(7); + list.add(10); + list.reverse(); + Assert.assertEquals("10,7,3", list.toString()); + Assert.assertEquals("10", list.get(0).toString()); + } + + @Test + public void testRemoveFirstHalf(){ + LinkedList list = new LinkedList(); + list.add(3); + list.add(7); + list.add(10); + list.add(12); + list.add(15); + list.removeFirstHalf(); + Assert.assertEquals("10", list.get(0).toString()); + Assert.assertEquals("10,12,15", list.toString()); + Assert.assertEquals(3, list.size()); + } + + @Test + public void testRemoveByLength(){ + LinkedList list = new LinkedList(); + list.add(3); + list.add(7); + list.add(10); + list.add(12); + list.add(15); + list.remove(0, 2); + Assert.assertEquals("10", list.get(0).toString()); + Assert.assertEquals("10,12,15", list.toString()); + Assert.assertEquals(3, list.size()); + + list.remove(1, 1); + Assert.assertEquals("10", list.get(0).toString()); + Assert.assertEquals("10,15", list.toString()); + Assert.assertEquals(2, list.size()); + } + + @Test + public void testGetElements(){ + LinkedList list = new LinkedList(); + list.add(0); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + + LinkedList indices = new LinkedList(); + indices.add(1); + indices.add(3); + indices.add(4); + indices.add(6); + int[] elements = list.getElements(indices); + StringBuilder sb = new StringBuilder(); + for(int i=0;i System.out.println("runnable with no argument."); + Thread thread = new Thread(noArg); + thread.start(); + + ActionListener oneArg = event -> System.out.println("actionListener with one argument."); + + Runnable multiStatement = () -> { + System.out.println("Runnable with multi statement."); + System.out.println("Hello Java8!"); + }; + BinaryOperator add = (x, y) -> x + y; + BinaryOperator addExplicit = (Long x, Long y) -> x + y; + + String name = "abc"; + name = "def"; + //ActionListener oneArg1 = event -> System.out.println("actionListener with one argument." + name); + // 编译无法通过:方法块中使用的变量必须使用final声明或既成事实的final变量,即变成赋值成功后不能再赋值 + + + Predicate atLeast5 = x -> x > 5; + System.out.println(atLeast5.test(6)); + +// BinaryOperator addE = (x,y) -> x + y;//编译不通过 + BinaryOperator addLongs = (x,y) -> x + y; + + } + + interface IntPred { + boolean test(Integer value); + } + interface A { + boolean check(Predicate predicate); + boolean check(IntPred predicate); + } +} diff --git a/group23/1028361767/learn-spring/src/practise/chapter1/HelloService.java b/group23/1028361767/learn-spring/src/practise/chapter1/HelloService.java new file mode 100644 index 0000000000..c6d60e339c --- /dev/null +++ b/group23/1028361767/learn-spring/src/practise/chapter1/HelloService.java @@ -0,0 +1,35 @@ +package practise.chapter1; + +import java.util.List; + +public class HelloService { + + private String target; + + private List targets; + + public HelloService(String target){ + this.target = target; + } + + public String say(){ + return "hello " + this.target; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public List getTargets() { + return targets; + } + + public void setTargets(List targets) { + this.targets = targets; + } + +} diff --git a/group23/1028361767/learn-spring/src/practise/chapter1/HelloWorldService.java b/group23/1028361767/learn-spring/src/practise/chapter1/HelloWorldService.java new file mode 100644 index 0000000000..390a7b7e68 --- /dev/null +++ b/group23/1028361767/learn-spring/src/practise/chapter1/HelloWorldService.java @@ -0,0 +1,9 @@ +package practise.chapter1; + +public class HelloWorldService { + + public String hello(){ + System.out.println("Hello Spring!"); + return "hello"; + } +} diff --git a/group23/1028361767/learn-spring/src/test/practise/Test1.java b/group23/1028361767/learn-spring/src/test/practise/Test1.java new file mode 100644 index 0000000000..7867ac294d --- /dev/null +++ b/group23/1028361767/learn-spring/src/test/practise/Test1.java @@ -0,0 +1,39 @@ +package test.practise; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import practise.chapter1.HelloService; +import practise.chapter1.HelloWorldService; + +public class Test1 { + + ApplicationContext context = new ClassPathXmlApplicationContext("practise/chapter1.xml"); + + @Test + public void testHello(){ + HelloWorldService helloWorldService = context.getBean("helloWorldService", HelloWorldService.class); + Assert.assertEquals("hello", helloWorldService.hello()); + HelloWorldService helloWorldService1 = context.getBean("helloWorldService1", HelloWorldService.class); + Assert.assertEquals("hello", helloWorldService1.hello()); + HelloWorldService helloWorldService2 = context.getBean("helloWorldService2", HelloWorldService.class); + Assert.assertEquals("hello", helloWorldService2.hello()); + String[] alias = context.getAliases("helloWorldService"); + Assert.assertEquals(2, alias.length); + for(String alia : alias){ + System.out.println(alia); + } + } + + @Test + public void testSay(){ + HelloService helloService = context.getBean("helloService", HelloService.class); + Assert.assertEquals("hello spring3", helloService.say()); + for(String target : helloService.getTargets()){ + System.out.println(target); + } + Assert.assertEquals(3, helloService.getTargets().size()); + } +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e5d5e522ee --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,89 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.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 attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + + String code = iter.nextUxToHexString(codeLen); + ByteCodeCommand[] commands = CommandParser.parse(clzFile, code); + + CodeAttr attr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, commands); + int expTableLen = iter.nextU2ToInt(); + if(expTableLen > 0){ + String expTable = iter.nextUxToHexString(expTableLen); + System.out.println("expTable: " + expTable); + // TODO 异常表处理 + } + int subAttrCount = iter.nextU2ToInt(); + ConstantPool pool = clzFile.getConstantPool(); + for (int i = 1; i <= subAttrCount; i++) { + int subAttrNameIndex = iter.nextU2ToInt(); + String subAttrName = pool.getUTF8String(subAttrNameIndex); + iter.back(2); + if(AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + attr.setLineNumberTable(LineNumberTable.parse(iter)); + }else if(AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + attr.setLocalVariableTable(LocalVariableTable.parse(iter)); + }else if(AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + attr.setStackMapTable(StackMapTable.parse(iter)); + }else{ + //TODO + throw new RuntimeException("CodeAttr.parse not implement " + subAttrName); + } + } + return attr; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..f83202d6c3 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo { + List 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(ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + LineNumberTable table = new LineNumberTable(attrNameIndex, attrLen); + int lineNumberTableLen = iter.nextU2ToInt(); + for(int i=0;i items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + LocalVariableTable table = new LocalVariableTable(attrNameIndex, attrLen); + int localVarLen = iter.nextU2ToInt(); + for(int i=0;i fields = new ArrayList<>(); + private List methods = new ArrayList<>(); + + + public ConstantPool getPool() { + return pool; + } + public void setPool(ConstantPool pool) { + this.pool = pool; + } + public List getMethods() { + return methods; + } + public void setMethods(List methods) { + this.methods = methods; + } + public void setClzIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + 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 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 List getFields() { + return fields; + } + public void setFields(List fields) { + this.fields = fields; + } + + public Method getMethod(String methodName, String paramAndReturnType){ + for(Method m : this.methods){ + String mName = this.getConstantPool().getUTF8String(m.getNameIndex()); + String pAndRT = this.getConstantPool().getUTF8String(m.getDescriptorIndex()); + if(methodName.equals(mName) + && paramAndReturnType.equals(pAndRT)){ + return m; + } + } + + return null; + } + public Method getMainMethod(){ + + return getMethod("main", "([Ljava/lang/String;)V"); + } +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..fca703c59a --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,138 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + +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) { + List cmds = new ArrayList<>(); + CommandIterator iter = new CommandIterator(codes); + while(iter.hasNext()){ + String opCode = iter.next2CharAsString().toUpperCase(); + if(new_object.equals(opCode)){ + NewObjectCmd newObjCmd = new NewObjectCmd(clzFile, opCode); + newObjCmd.setOprand1(iter.next2CharAsInt()); + newObjCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(newObjCmd); + }else if(getfield.equals(opCode)){ + GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, opCode); + getFieldCmd.setOprand1(iter.next2CharAsInt()); + getFieldCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(getFieldCmd); + }else if(getstatic.equals(opCode)){ + GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, opCode); + getStaticFieldCmd.setOprand1(iter.next2CharAsInt()); + getStaticFieldCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(getStaticFieldCmd); + }else if(putfield.equals(opCode)){ + PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, opCode); + putFieldCmd.setOprand1(iter.next2CharAsInt()); + putFieldCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(putFieldCmd); + }else if(invokevirtual.equals(opCode)){ + InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, opCode); + invokeVirtualCmd.setOprand1(iter.next2CharAsInt()); + invokeVirtualCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(invokeVirtualCmd); + }else if(invokespecial.equals(opCode)){ + InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, opCode); + invokeSpecialCmd.setOprand1(iter.next2CharAsInt()); + invokeSpecialCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(invokeSpecialCmd); + }else if(ldc.equals(opCode)){ + LdcCmd ldcCmd = new LdcCmd(clzFile, opCode); + ldcCmd.setOperand(iter.next2CharAsInt()); + cmds.add(ldcCmd); + }else if(bipush.equals(opCode)){ + BiPushCmd biPushCmd = new BiPushCmd(clzFile, opCode); + biPushCmd.setOperand(iter.next2CharAsInt()); + cmds.add(biPushCmd); + }else if(dup.equals(opCode) || aload_0.equals(opCode) + || aload_1.equals(opCode) || aload_2.equals(opCode) + || astore_1.equals(opCode) || voidreturn.equals(opCode) + || iload.equals(opCode) || iload_1.equals(opCode) + || iload_2.equals(opCode) || iload_3.equals(opCode)){ + NoOperandCmd noOpCmd = new NoOperandCmd(clzFile, opCode); + cmds.add(noOpCmd); + }else{ + throw new RuntimeException("cmd " + opCode + " has not bean implemented yet."); + } + } + calcuateOffset(cmds); + ByteCodeCommand[] byteCodeCmds = new ByteCodeCommand[cmds.size()]; + return cmds.toArray(byteCodeCmds); + } + + 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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.UTF8Info; + + +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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; + + +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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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 = (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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..92ac5b67eb --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..8d4fc6f0de --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.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 static interface Visitor { + void visitClassInfo(ClassInfo classInfo); + void visitFieldRefInfo(FieldRefInfo fieldRefInfo); + void visitMethodRefInfo(MethodRefInfo methodRefInfo); + void visitNameAndTypeInfo(NameAndTypeInfo nameAndTypeInfo); + void visitNullConstantInfo(NullConstantInfo nullConstantInfo); + void visitStringInfo(StringInfo stringInfo); + void visitUTF8Info(UTF8Info utf8Info); + } + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..93506b1e20 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..cb31499dd3 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.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.visitFieldRefInfo(this); + } +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..466b06f9ea --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.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.visitMethodRefInfo(this); + } + + + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..c13d8c4fc6 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.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.visitNameAndTypeInfo(this); + } +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..655c273621 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + visitor.visitNullConstantInfo(this); + } + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..84ae36c4ca --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.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.visitStringInfo(this); + } + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7c4aeb1861 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,36 @@ +package com.coderising.jvm.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.visitUTF8Info(this); + } + + + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/field/Field.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..01a009331c --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + Field field = new Field(accessFlag, nameIndex, descriptorIndex, pool); + int attCount = iter.nextU2ToInt(); + if(attCount > 0){ + //TODO handle field attrs + throw new RuntimeException("Field.attr not implements"); + } + return field; + } + + public String toString() { + return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex); + } + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..c0c4598800 --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,69 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +public class ByteCodeIterator { + + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + } + + public byte[] nextU2(){ return new byte[]{codes[pos++], codes[pos++]};} + + public byte[] nextU4(){ return new byte[]{codes[pos++], codes[pos++], codes[pos++], codes[pos++]};} + + public int nextU1ToInt() { + return (codes[pos++] & 0xff); + } + + public int nextU2ToInt() { + return ((codes[pos++] & 0xff00) << 8) | (codes[pos++] & 0x00ff); + } + + public int nextU4ToInt() { + return ((codes[pos++] & 0xff000000) << 24) | ((codes[pos++] & 0x00ff0000) << 16) + | ((codes[pos++] & 0x0000ff00) << 8) | (codes[pos++] & 0x000000ff) ; + } + + public String nextUxToHexString(int len) { + StringBuffer buffer = new StringBuffer(); + for(int i=0;i 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; + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + public void addClassPath(String path) { + if(clzPaths.contains(path)) + return ; + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuilder sb = new StringBuilder(); + for(String clzPath : clzPaths){ + sb.append(clzPath).append(";"); + } + return sb.length() == 0?"":sb.substring(0, sb.length()-1); + } + + private byte[] loadClassFile(String clzFileName) { + + BufferedInputStream bis = null; + + try { + + File f = new File(clzFileName); + + + bis = new BufferedInputStream(new FileInputStream(f)); + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + + byte[] buffer = new byte[1024]; + int length = -1; + + while((length = bis.read(buffer)) != -1){ + bos.write(buffer, 0, length); + } + + byte [] codes = bos.toByteArray(); + + return codes; + + } catch(IOException e){ + e.printStackTrace(); + + } finally{ + if(bis != null){ + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + + +} diff --git a/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..3a6258e26b --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,134 @@ +package com.coderising.jvm.loader; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.AccessFlag; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.NullConstantInfo; +import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + +// String magicNumber = iter.nextUxToHexString(4); + iter.nextUxToHexString(4); + + classFile.setMinorVersion(iter.nextU2ToInt()); + classFile.setMajorVersion(iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + classFile.setConstPool(pool); + + classFile.setAccessFlag(parseAccessFlag(iter)); + + classFile.setClassIndex(parseClassInfex(iter)); + + parseInterfaces(iter); + + classFile.setFields(prarseField(iter, pool)); + classFile.setMethods(parseMethod(iter, classFile)); + return classFile; + } + + private List parseMethod(ByteCodeIterator iter, ClassFile classFile) { + List methods = new ArrayList<>(); + int mthodsCount = iter.nextU2ToInt(); + for(int i=0;i prarseField(ByteCodeIterator iter, ConstantPool pool) { + List fields = new ArrayList<>(); + int fieldsCount = iter.nextU2ToInt(); + 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/group23/1028361767/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group23/1028361767/mini-jvm/src/com/coderising/jvm/util/Util.java b/group23/1028361767/mini-jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group23/1028361767/mini-jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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;i0){ + if((index+1024)<=startPos){ + index+=1024; + continue; + } + + if(index<=startPos&&startPos<(index+1024)){ + + if(endPos<(index+1024)){ + for(int i=0,j=startPos-index;i0){ + count+=len; + } + Assert.assertEquals(count, conn.getContentLength()); + + } + + + @Test + public void testClose() { + conn.close(); + } + +} diff --git a/group23/1072760797-skomefen/day3-26/src/junit/test/ConnectionManagerImplTest.java b/group23/1072760797-skomefen/day3-26/src/junit/test/ConnectionManagerImplTest.java new file mode 100644 index 0000000000..589c1bf1d2 --- /dev/null +++ b/group23/1072760797-skomefen/day3-26/src/junit/test/ConnectionManagerImplTest.java @@ -0,0 +1,31 @@ +package junit.test; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.impl.ConnectionImpl; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class ConnectionManagerImplTest { + + @Before + public void setUp() throws Exception { + } + + + @Test + public void testOpen() throws ConnectionException { + ConnectionManager cm = new ConnectionManagerImpl(); + String url = "http://localhost:8080/TimeCapsule/readme.txt"; + Connection conn = cm.open(url); + } + +} diff --git a/group23/1072760797-skomefen/day3-26/src/junit/test/DownloadThreadTest.java b/group23/1072760797-skomefen/day3-26/src/junit/test/DownloadThreadTest.java new file mode 100644 index 0000000000..5ae230e97b --- /dev/null +++ b/group23/1072760797-skomefen/day3-26/src/junit/test/DownloadThreadTest.java @@ -0,0 +1,77 @@ +package junit.test; + +import static org.junit.Assert.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; + + + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.DownloadThread; +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.impl.ConnectionManagerImpl; + +public class DownloadThreadTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testRun() throws ConnectionException, IOException { + ConnectionManager cm = new ConnectionManagerImpl(); + String url = "http://localhost:8080/TimeCapsule/readme.txt"; + Connection conn = cm.open(url); + DownloadThread dt = new DownloadThread(conn, 0, conn.getContentLength()); + dt.start(); + + File file = new File("e://readme.txt"); + FileInputStream in = new FileInputStream(file); + byte[] b = new byte[10]; + int len = 0; + ArrayList a = new ArrayList(); + while((len=in.read(b))>0){ + a.add(b); + } + + int length = conn.getContentLength(); + if(length%3==0){ + for(int i=1;i<=3;i++){ + int startPos = length/3*i-1; + int endPos = length/3*(i-1); + new DownloadThread(conn, endPos, startPos).start(); + } + }else{ + for(int i=1;i<=2;i++){ + + int startPos = length/3*(i-1); + int endPos = length/3*i-1; + new DownloadThread(conn, startPos, endPos).start(); + } + int startPos = length/3*2; + new DownloadThread(conn, startPos, length).start(); + } + + file = new File("e://readme.txt"); + in = new FileInputStream(file); + b = new byte[10]; + len = 0; + ArrayList a1 = new ArrayList(); + while((len=in.read(b))>0){ + a1.add(b); + } + for(int i = 0;i - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/ArrayList.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/ArrayList.java new file mode 100644 index 0000000000..fd6f80a806 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/ArrayList.java @@ -0,0 +1,82 @@ +package main; + +import java.util.Arrays; + +import utils.ListUtils; + +public class ArrayList implements List { + private Object[] elementData = new Object[10]; + private int size; + + @Override + public void add(Object o) { + add(size, o); + + } + + @Override + public void add(int index, Object o) { + // 检查是否越界 + ListUtils.CheckIndexInRange(0, size, index); + if (size == elementData.length) { + elementData = Arrays.copyOf(elementData, elementData.length + 10); + } + if (index < size) { + for (int i = size; i > index; i--) { + elementData[i] = elementData[i - 1]; + } + } + elementData[index] = o; + size++; + } + + @Override + public Object remove(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + Object tag = elementData[index]; + for (int i = index; i < size - 1; i++) { + elementData[i] = elementData[i + 1]; + } + elementData[size - 1] = null; + size--; + return tag; + + } + + @Override + public Object get(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + return elementData[index]; + + } + + @Override + public int size() { + return size; + } + + public Iterator iterator() { + return new Iterator() { + private int cursor; + + @Override + public boolean hasNext() { + if (size > 0) { + return cursor < size; + } else { + return false; + } + + } + + @Override + public Object next() { + Object tag = get(cursor); + cursor++; + return tag; + } + }; + + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/BinaryTreeNode.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/BinaryTreeNode.java new file mode 100644 index 0000000000..b67a56b5a7 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/BinaryTreeNode.java @@ -0,0 +1,65 @@ +package main; + +public class BinaryTreeNode { + @SuppressWarnings("rawtypes") + private Comparable data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + @SuppressWarnings("rawtypes") + public BinaryTreeNode(Comparable data, BinaryTreeNode left, BinaryTreeNode right) { + this.data = data; + this.left = left; + this.right = right; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public BinaryTreeNode insert(Comparable o) { + int result = o.compareTo(data); + if (0 == result) { + return this; + } else if (0 < result) { + if (null == this.right) { + BinaryTreeNode node = new BinaryTreeNode(o, null, null); + this.right = node; + return node; + } + return this.right.insert(o); + } else { + if (null == this.left) { + BinaryTreeNode node = new BinaryTreeNode(o, null, null); + this.left = node; + return node; + } + return this.left.insert(o); + } + + } + + @SuppressWarnings("rawtypes") + public Comparable getData() { + return data; + } + + @SuppressWarnings("rawtypes") + public void setData(Comparable data) { + this.data = data; + } + + public BinaryTreeNode getLeft() { + return left; + } + + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + + public BinaryTreeNode getRight() { + return right; + } + + public void setRight(BinaryTreeNode right) { + this.right = right; + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Iterator.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Iterator.java new file mode 100644 index 0000000000..166a6181e3 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Iterator.java @@ -0,0 +1,6 @@ +package main; + +public interface Iterator { + public boolean hasNext(); + public Object next(); +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/LinkedList.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/LinkedList.java new file mode 100644 index 0000000000..a6d82a0545 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/LinkedList.java @@ -0,0 +1,114 @@ +package main; + +import utils.ListUtils; + +public class LinkedList implements List { + private Node head; + private int size; + + private static class Node { + private Object data; + private Node next; + } + + @Override + public void add(Object o) { + add(size, o); + } + + @Override + public void add(int index, Object o) { + ListUtils.CheckIndexInRange(0, size, index); + if (0==size) { + head = new Node(); + head.data = o; + size++; + return; + } + if (0 == index) { + Node node = new Node(); + node.data = o; + node.next = head; + head = node; + size++; + return; + } + if (index == size) { + Node node = head; + while (null != node.next) { + node = node.next; + } + Node addNode = new Node(); + addNode.data = o; + node.next = addNode; + size++; + return; + } + Node node = head; + for (int i = 0; i < index - 1; i++) { + node = node.next; + } + Node addNode = new Node(); + addNode.data = o; + addNode.next = node.next; + node.next = addNode; + size++; + } + + @Override + public Object remove(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + Node node = head; + if (0 == index) { + head = head.next; + size--; + return node.data; + } + for (int i = 0; i < index - 1; i++) { + node = node.next; + } + Node removeNode = node.next; + node.next = removeNode.next; + size--; + return removeNode.data; + } + + @Override + public Object get(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.data; + } + + @Override + public int size() { + return size; + } + + public Iterator iterator() { + return new Iterator() { + private int cursor; + + @Override + public boolean hasNext() { + if (size > 0) { + return cursor < size; + } else { + return false; + } + + } + + @Override + public Object next() { + Object tag = get(cursor); + cursor++; + return tag; + } + }; + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/List.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/List.java new file mode 100644 index 0000000000..73e3865ed7 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/List.java @@ -0,0 +1,9 @@ +package main; + +public interface List { + public void add(Object o); + public void add(int index,Object o); + public Object remove(int index); + public Object get(int index); + public int size(); +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Queue.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Queue.java new file mode 100644 index 0000000000..feebe25b99 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Queue.java @@ -0,0 +1,22 @@ +package main; + +public class Queue { + private LinkedList list = new LinkedList(); + + public void enQueue(Object o) { + list.add(o); + } + + public Object deQueue() { + return list.remove(0); + } + + public boolean isEmpty() { + return list.size() == 0; + } + + public int size() { + return list.size(); + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Stack.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Stack.java new file mode 100644 index 0000000000..a584680425 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/main/Stack.java @@ -0,0 +1,25 @@ +package main; + +public class Stack { + private ArrayList list = new ArrayList(); + + public void push(Object o) { + list.add(o); + } + + public Object pop() { + return list.remove(list.size() - 1); + } + + public Object peek() { + return list.get(list.size() - 1); + } + + public boolean isEmpty() { + return list.size() == 0; + } + + public int size() { + return list.size(); + } +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/ArrayListTest.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/ArrayListTest.java new file mode 100644 index 0000000000..f9f67e86f0 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/ArrayListTest.java @@ -0,0 +1,144 @@ +package test; + + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + + +import main.ArrayList; +import main.Iterator; + +public class ArrayListTest { + ArrayList list; + + @Before + public void init() { + list = new ArrayList(); + } + + @Test + public void testAddObject() { + list.add(0); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + list.add(7); + list.add(8); + list.add(9); + list.add(10); + assertEquals(0, list.get(0)); + assertEquals(1, list.get(1)); + assertEquals(2, list.get(2)); + + } + + @Test + public void testAddIntObject() { + list.add("b"); + list.add("d"); + list.add("e"); + list.add(0, "a"); + list.add(2, "c"); + list.add(5, "f"); + assertEquals("a", list.get(0)); + assertEquals("c", list.get(2)); + assertEquals("f", list.get(5)); + try { + list.add(-1, "hh"); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.add(7, "xx"); + fail("index should <=size"); + } catch (Exception e) { + } + + } + + @Test + public void testRemove() { + list.add("a"); + list.add("b"); + list.add("c"); + list.add("d"); + assertEquals("d", list.remove(3)); + assertEquals("a", list.remove(0)); + assertEquals("c", list.remove(1)); + try { + list.remove(-1); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.remove(1); + fail("index should <=size"); + } catch (Exception e) { + } + + } + + @Test + public void testGet() { + + list.add("a"); + assertEquals("a", list.get(0)); + + try { + list.get(-1); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.get(1); + fail("index should <=size"); + } catch (Exception e) { + } + + } + + @Test + public void testSize() { + list.add("a"); + assertEquals(1, list.size()); + list.remove(0); + assertEquals(0, list.size()); + } + + @Test + public void testIterator() { + Iterator i = list.iterator(); + assertEquals(0, list.size()); + assertFalse(i.hasNext()); + list.add("a"); + list.add("b"); + list.add("c"); + list.add("d"); + i = list.iterator(); + assertTrue(i.hasNext()); + assertEquals("a", i.next()); + assertTrue(i.hasNext()); + assertEquals("b", i.next()); + assertTrue(i.hasNext()); + assertEquals("c", i.next()); + assertTrue(i.hasNext()); + assertEquals("d", i.next()); + assertFalse(i.hasNext()); + + try { + i.next(); + fail("index should <=size"); + } catch (Exception e) { + } + + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/BinaryTreeNodeTest.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..9487991ba0 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/BinaryTreeNodeTest.java @@ -0,0 +1,25 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import main.BinaryTreeNode; + +public class BinaryTreeNodeTest { + + @Test + public void testInsert() { + BinaryTreeNode node = new BinaryTreeNode(5, null,null); + node.insert(2); + node.insert(7); + node.insert(7); + node.insert(1); + node.insert(6); + node.insert(4); + node.insert(8); + assertEquals(8, node.getRight().getRight().getData()); + assertEquals(4, node.getLeft().getRight().getData()); + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/LinkedListTest.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/LinkedListTest.java new file mode 100644 index 0000000000..a4db15567d --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/LinkedListTest.java @@ -0,0 +1,126 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import main.Iterator; +import main.LinkedList; + +public class LinkedListTest { + private LinkedList list; + + @Before + public void init(){ + list = new LinkedList(); + } + + @Test + public void testAddObject() { + list.add(0); + list.add(1); + list.add(2); + assertEquals(0, list.get(0)); + assertEquals(1, list.get(1)); + assertEquals(2, list.get(2)); + } + + @Test + public void testAddIntObject() { + list.add("b"); + list.add("d"); + list.add("e"); + list.add(0, "a"); + list.add(2, "c"); + list.add(5, "f"); + assertEquals("a", list.get(0)); + assertEquals("c", list.get(2)); + assertEquals("f", list.get(5)); + try { + list.add(-1, "hh"); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.add(7, "xx"); + fail("index should <=size"); + } catch (Exception e) {} + } + + @Test + public void testRemove() { + list.add("a"); + list.add("b"); + list.add("c"); + list.add("d"); + assertEquals("d", list.remove(3)); + assertEquals("a", list.remove(0)); + assertEquals("c", list.remove(1)); + try { + list.remove(-1); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.remove(1); + fail("index should <=size"); + } catch (Exception e) { + } + + } + + @Test + public void testGet() { + + list.add("a"); + assertEquals("a", list.get(0)); + + try { + list.get(-1); + fail("-1 cann't be index"); + } catch (Exception e) { + } + + try { + list.get(1); + fail("index should <=size"); + } catch (Exception e) { + } + } + + @Test + public void testSize() { + list.add("a"); + assertEquals(1, list.size()); + list.remove(0); + assertEquals(0, list.size()); + } + + @Test + public void testIterator() { + list.add("a"); + list.add("b"); + list.add("c"); + list.add("d"); + Iterator i = list.iterator(); + assertTrue(i.hasNext()); + assertEquals("a", i.next()); + assertTrue(i.hasNext()); + assertEquals("b", i.next()); + assertTrue(i.hasNext()); + assertEquals("c", i.next()); + assertTrue(i.hasNext()); + assertEquals("d", i.next()); + assertFalse(i.hasNext()); + + try { + i.next(); + fail("index should <=size"); + } catch (Exception e) { + } + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/QueueTest.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/QueueTest.java new file mode 100644 index 0000000000..be1feeb465 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/QueueTest.java @@ -0,0 +1,50 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import main.Queue; + +public class QueueTest { + private Queue queue; + + @Before + public void init(){ + queue = new Queue(); + } + + @Test + public void testEnQueue() { + } + + @Test + public void testDeQueue() { + try{ + queue.deQueue(); + fail("empty queue hasn't element"); + }catch (Exception e) { + } + queue.enQueue("a"); + queue.enQueue("b"); + assertEquals("a", queue.deQueue()); + assertEquals("b", queue.deQueue()); + } + + @Test + public void testIsEmpty() { + assertTrue(queue.isEmpty()); + queue.enQueue("a"); + assertFalse(queue.isEmpty()); + } + + @Test + public void testSize() { + assertEquals(0, queue.size()); + queue.enQueue("a"); + queue.enQueue("a"); + assertEquals(2, queue.size()); + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/StackTest.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/StackTest.java new file mode 100644 index 0000000000..7b75a4d218 --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/test/StackTest.java @@ -0,0 +1,67 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import main.Stack; + +public class StackTest { + private Stack stack; + + @Before + public void init(){ + stack = new Stack(); + } + + @Test + public void testPush() { + stack.push("a"); + assertEquals("a", stack.peek()); + stack.push("b"); + assertEquals("b", stack.peek()); + } + + @Test + public void testPop() { + try{ + stack.pop(); + fail("empty stack hasn't element"); + }catch (Exception e) { + } + stack.push("a"); + stack.push("b"); + stack.push("c"); + assertEquals("c", stack.pop()); + assertEquals("b", stack.pop()); + assertEquals("a", stack.pop()); + } + + @Test + public void testPeek() { + } + + @Test + public void testIsEmpty() { + assertTrue(stack.isEmpty()); + stack.push("a"); + stack.push("b"); + assertFalse(stack.isEmpty()); + stack.pop(); + assertFalse(stack.isEmpty()); + stack.pop(); + assertTrue(stack.isEmpty()); + + + } + + @Test + public void testSize() { + assertEquals(0, stack.size()); + stack.push("a"); + stack.push("b"); + assertEquals(2, stack.size()); + } + +} diff --git a/group23/1323434545/work_DataStructure/01_5BasicDS/src/utils/ListUtils.java b/group23/1323434545/work_DataStructure/01_5BasicDS/src/utils/ListUtils.java new file mode 100644 index 0000000000..0fe8959b8a --- /dev/null +++ b/group23/1323434545/work_DataStructure/01_5BasicDS/src/utils/ListUtils.java @@ -0,0 +1,11 @@ +package utils; + +public class ListUtils { + public static boolean CheckIndexInRange(int start, int end, int index) { + if (index >= start && index <= end) { + return true; + } + throw new IndexOutOfBoundsException(); + } + +} diff --git a/group23/1323434545/work_DataStructure/02_ArrayUtil/src/main/ArrayUtil.java b/group23/1323434545/work_DataStructure/02_ArrayUtil/src/main/ArrayUtil.java new file mode 100644 index 0000000000..59670e0272 --- /dev/null +++ b/group23/1323434545/work_DataStructure/02_ArrayUtil/src/main/ArrayUtil.java @@ -0,0 +1,209 @@ +package main; + +import java.util.Arrays; + +public class ArrayUtil { + /** + * 给定一个整形数组a , 对该数组的值进行置换 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] 如果 a = + * [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * + * @param origin + * @return + */ + public static void reverseArray(int[] origin) { + if (null == origin) { + return; + } + for (int temp = 0, i = 0; i < origin.length / 2; i++) { + temp = origin[i]; + origin[i] = origin[origin.length - i - 1]; + origin[origin.length - i - 1] = temp; + } + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: {1,3,4,5,6,6,5,4,7,6,7,5} + * + * @param oldArray + * @param newArray + * @return + */ + + public static int[] removeZero(int[] oldArray) { + if (null == oldArray) { + return null; + } + int counter = 0; + int[] newArray = new int[oldArray.length]; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + newArray[counter++] = oldArray[i]; + } + } + return Arrays.copyOf(newArray, counter); + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 例如 a1 = + * [3, 5, 7,8] a2 = [4, 5,6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * + * @param array1 + * @param array2 + * @return + */ + + public static int[] merge(int[] array1, int[] array2) { + if (null == array1) { + return array2; + } + if (null == array2) { + return array1; + } + if (0 == array1.length && 0 == array2.length) { + return new int[0]; + } + Arrays.sort(array1); + Arrays.sort(array2); + int[] array = new int[array1.length + array2.length]; + System.arraycopy(array1, 0, array, 0, array1.length); + System.arraycopy(array2, 0, array, array1.length, array2.length); + int counter = 0; + for (int i = 0; i < array.length - 1 - counter; i++) { + for (int j = i + 1; j < array.length - counter; j++) { + if (array[i] == array[j]) { + int k = 0; + for (k = i; k < array.length - 1; k++) { + array[k] = array[k + 1]; + } + i--; + counter++; + break; + } + } + } + array = Arrays.copyOf(array, array.length - counter); + Arrays.sort(array); + return array; + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * + * @param oldArray + * @param size + * @return + */ + public static int[] grow(int[] oldArray, int size) { + if (null == oldArray) { + return null; + } + int[] array = new int[oldArray.length + size]; + for (int i = 0; i < oldArray.length; i++) { + array[i] = oldArray[i]; + } + return array; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 例如, max = 15 , + * 则返回的数组应该为 [1,1,2,3,5,8,13] max = 1, 则返回空数组 [] + * + * @param max + * @return + */ + public static int[] fibonacci(int max) { + if (max <= 1) { + return new int[0]; + } + int[] array = new int[max]; + array[0] = 1; + array[1] = 1; + int i = 1; + do { + i++; + array[i] = array[i - 1] + array[i - 2]; + } while (array[i] < max); + return Arrays.copyOf(array, i); + } + + /** + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public static int[] getPrimes(int max) { + if (max < 3) { + return new int[0]; + } + int[] array = new int[max]; + int counter = 0; + for (int i = 2; i < max; i++) { + int j = 2; + for (; j * j <= i; j++) { + if (i % j == 0) { + break; + } + } + if (j * j > i) { + array[counter] = i; + counter++; + } + } + return Arrays.copyOf(array, counter); + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public static int[] getPerfectNumbers(int max) { + if (max < 7) { + return new int[0]; + } + int[] array = new int[2]; + int counter = 0; + for (int i = 6; i < max; i++) { + int sum = 0; + for (int j = 1; j <= i / 2; j++) { + if (i % j == 0) { + sum = sum + j; + } + } + if (sum == i) { + if (counter == array.length) { + array = ArrayUtil.grow(array, 2); + } + array[counter++] = i; + } + } + return Arrays.copyOf(array, counter); + } + + /** + * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * + * @param array + * @param s + * @return + */ + public static String join(int[] array, String seperator) { + if (null == array) { + return null; + } + if (array.length == 0) { + return ""; + } + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < array.length; i++) { + sb.append(seperator).append(array[i]); + } + return sb.toString().substring(seperator.length()); + } + +} diff --git a/group23/1323434545/work_DataStructure/02_ArrayUtil/src/test/ArrayUtilTest.java b/group23/1323434545/work_DataStructure/02_ArrayUtil/src/test/ArrayUtilTest.java new file mode 100644 index 0000000000..c87caa30c5 --- /dev/null +++ b/group23/1323434545/work_DataStructure/02_ArrayUtil/src/test/ArrayUtilTest.java @@ -0,0 +1,101 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import main.ArrayUtil; + +public class ArrayUtilTest { + @Test + public void testReverseArray() { + int[] origin = null; + ArrayUtil.reverseArray(origin); + assertEquals(null, origin); + + int[] origin1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + ArrayUtil.reverseArray(origin1); + int[] expected1 = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + for (int i = 0; i < 4; i++) { + assertEquals(expected1[i], origin1[i]); + } + + int[] origin2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + ArrayUtil.reverseArray(origin2); + int[] expected2 = { 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + for (int i = 0; i < 4; i++) { + assertEquals(expected2[i], origin2[i]); + } + } + + @Test + public void testRemoveZero() { + int oldArr[] = { 1, 3, 4, 5, 0, 0, 6, 6, 0, 5, 4, 7, 6, 7, 0, 5 }; + int excepted[] = { 1, 3, 4, 5, 6, 6, 5, 4, 7, 6, 7, 5 }; + oldArr = ArrayUtil.removeZero(oldArr); + System.out.println(oldArr.length); + for (int i = 0; i < oldArr.length; i++) { + assertEquals(excepted[i], oldArr[i]); + } + } + + @Test + public void testMerge() { + int[] array1 = { 3, 4, 4, 5, 7, 8 }; + int[] array2 = { 4, 5, 6, 7 }; + int[] expected = { 3, 4, 5, 6, 7, 8 }; + int[] array = ArrayUtil.merge(array1, array2); + for (int i = 0; i < array.length; i++) { + assertEquals(expected[i], array[i]); + } + } + + @Test + public void testGrow() { + int[] oldArray = { 2, 3, 6 }; + int[] array = ArrayUtil.grow(oldArray, 3); + int[] expected = { 2, 3, 6, 0, 0, 0 }; + for (int i = 0; i < array.length; i++) { + assertEquals(expected[i], array[i]); + } + } + + @Test + public void testFibonacci() { + int[] fibonacci = ArrayUtil.fibonacci(1); + assertEquals(0, fibonacci.length); + + int[] fibonacci1 = ArrayUtil.fibonacci(16); + int[] excepted1 = { 1, 1, 2, 3, 5, 8, 13, 15 }; + for (int i = 0; i < fibonacci1.length; i++) { + assertEquals(excepted1[i], fibonacci1[i]); + } + } + + @Test + public void testGetPrimes() { + int[] primes = ArrayUtil.getPrimes(23); + int[] excepted = { 2, 3, 5, 7, 11, 13, 17, 19 }; + for (int i = 0; i < primes.length; i++) { + assertEquals(excepted[i], primes[i]); + } + } + + @Test + public void testGetPerfectNumbers() { + int[] PerfectNumbers = ArrayUtil.getPerfectNumbers(497); + int[] excepted = { 6, 28, 496 }; + for (int i = 0; i < PerfectNumbers.length; i++) { + assertEquals(excepted[i], PerfectNumbers[i]); + } + } + + @Test + public void testJoin() { + int[] array1 = { 3 }; + assertEquals("3", ArrayUtil.join(array1, "-%")); + int[] array2 = { 3, 8, 9, 7 }; + assertEquals("3-%8-%9-%7", ArrayUtil.join(array2, "-%")); + } + +} diff --git a/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/Iterator.java b/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/Iterator.java new file mode 100644 index 0000000000..166a6181e3 --- /dev/null +++ b/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/Iterator.java @@ -0,0 +1,6 @@ +package main; + +public interface Iterator { + public boolean hasNext(); + public Object next(); +} diff --git a/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/LinkedList.java b/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/LinkedList.java new file mode 100644 index 0000000000..96ffdd77a5 --- /dev/null +++ b/group23/1323434545/work_DataStructure/03_LinkedListOperations/src/main/LinkedList.java @@ -0,0 +1,256 @@ +package main; + +import java.util.Arrays; + +import utils.ListUtils; + +public class LinkedList implements List{ + private Node head; + private int size; + + private static class Node { + private Object data; + private Node next; + } + + @Override + public void add(Object o) { + add(size, o); + } + + @Override + public void add(int index, Object o) { + ListUtils.CheckIndexInRange(0, size, index); + if (0==size) { + head = new Node(); + head.data = o; + size++; + return; + } + if (0 == index) { + Node node = new Node(); + node.data = o; + node.next = head; + head = node; + size++; + return; + } + if (index == size) { + Node node = head; + while (null != node.next) { + node = node.next; + } + Node addNode = new Node(); + addNode.data = o; + node.next = addNode; + size++; + return; + } + Node node = head; + for (int i = 0; i < index - 1; i++) { + node = node.next; + } + Node addNode = new Node(); + addNode.data = o; + addNode.next = node.next; + node.next = addNode; + size++; + } + + @Override + public Object remove(int index) { + if(size == 0){ + return null; + } + ListUtils.CheckIndexInRange(0, size - 1, index); + Node node = head; + if (0 == index) { + head = head.next; + size--; + return node.data; + } + for (int i = 0; i < index - 1; i++) { + node = node.next; + } + Node removeNode = node.next; + node.next = removeNode.next; + size--; + return removeNode.data; + } + + @Override + public Object get(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.data; + } + + @Override + public int size() { + return size; + } + + public Iterator iterator() { + return new Iterator() { + private int cursor; + + @Override + public boolean hasNext() { + if (size > 0) { + return cursor < size; + } else { + return false; + } + + } + + @Override + public Object next() { + Object tag = get(cursor); + cursor++; + return tag; + } + }; + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + if(this.size == 0){ + return; + } + LinkedList list = new LinkedList(); + for(int i =this.size-1;i>=0;i--){ + list.add(this.get(i)); + } + this.head = list.head; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf(){ + int end = size/2; + for(int i=0;isize){ + return; + } + for(int j =0;j101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + if(null==list||list.size==0){ + return new int[0]; + } + int[] result = new int[list.size]; + int counter = 0; + for(int i=0;imax){ + return; + } + for(int i=0;imin&&(int)get(i)= start && index <= end) { + return true; + } + throw new IndexOutOfBoundsException(); + } + +} diff --git a/group23/1323434545/work_DataStructure/04_LRU/src/main/LRUPageFrame.java b/group23/1323434545/work_DataStructure/04_LRU/src/main/LRUPageFrame.java new file mode 100644 index 0000000000..26a03c58f4 --- /dev/null +++ b/group23/1323434545/work_DataStructure/04_LRU/src/main/LRUPageFrame.java @@ -0,0 +1,117 @@ +package main; + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + this.currentSize = 0; + } + + /** + * 获取缓存中的对象 + * + * @param pageNum + */ + public void access(int pageNum) { + if (first == null && last == null) { + first = new Node(); + first.pageNum = pageNum; + last = first; + currentSize++; + return; + } + Node tagNode = find(pageNum); + if (tagNode != null) { + moveExistingNodeToHead(tagNode); + return; + } + Node node = new Node(); + node.pageNum = pageNum; + addNewNodeToHead(node); + + } + + private void addNewNodeToHead(Node node) { + if (currentSize == capacity) { + removeLast(); + } + Node temp = first; + temp.prev = node; + node.next = temp; + first = node; + currentSize++; + } + + private Node find(int data) { + Node node = first; + while (node != null) { + if (node.pageNum == data) { + return node; + } + node = node.next; + } + return null; + } + + /** + * 删除链表尾部节点,表示删除最小使用的缓存对象 + */ + private void removeLast() { + Node temp = last.prev; + temp.next = null; + last = temp; + currentSize--; + } + + /** + * 移动到表头,表示这个节点是最新使用过的 + */ + private void moveExistingNodeToHead(Node node) { + if (node.prev == null) { + return; + } + Node prev = node.prev; + Node next = node.next; + if (next == null) { + last = prev; + } + prev.next = next; + if (next != null) { + next.prev = prev; + } + Node temp = first; + temp.prev = node; + node.prev = null; + node.next = temp; + first = node; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + Node node = first; + while (node != null) { + sb.append(node.pageNum); + node = node.next; + if (node != null) { + sb.append(","); + } + } + return sb.toString(); + } + +} diff --git a/group23/1323434545/work_DataStructure/04_LRU/src/test/LRUPageFrameTest.java b/group23/1323434545/work_DataStructure/04_LRU/src/test/LRUPageFrameTest.java new file mode 100644 index 0000000000..e190a31b82 --- /dev/null +++ b/group23/1323434545/work_DataStructure/04_LRU/src/test/LRUPageFrameTest.java @@ -0,0 +1,35 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import main.LRUPageFrame; + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame pf = new LRUPageFrame(3); + pf.access(7); + pf.access(0); + pf.access(1); + assertEquals("1,0,7", pf.toString()); + pf.access(2); + assertEquals("2,1,0", pf.toString()); + pf.access(0); + assertEquals("0,2,1", pf.toString()); + pf.access(0); + assertEquals("0,2,1", pf.toString()); + pf.access(3); + assertEquals("3,0,2", pf.toString()); + pf.access(0); + assertEquals("0,3,2", pf.toString()); + pf.access(4); + assertEquals("4,0,3", pf.toString()); + pf.access(5); + assertEquals("5,4,0", pf.toString()); + + } + +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ArrayList.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ArrayList.java new file mode 100644 index 0000000000..3593756817 --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ArrayList.java @@ -0,0 +1,75 @@ +package main; + +import java.util.Arrays; + +public class ArrayList{ + private Object[] elementData = new Object[10]; + private int size; + + public void add(Object o) { + add(size, o); + + } + + public void add(int index, Object o) { + // 检查是否越界 + ListUtils.CheckIndexInRange(0, size, index); + if (size == elementData.length) { + elementData = Arrays.copyOf(elementData, elementData.length + 10); + } + if (index < size) { + for (int i = size; i > index; i--) { + elementData[i] = elementData[i - 1]; + } + } + elementData[index] = o; + size++; + } + + public Object remove(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + Object tag = elementData[index]; + for (int i = index; i < size - 1; i++) { + elementData[i] = elementData[i + 1]; + } + elementData[size - 1] = null; + size--; + return tag; + + } + + public Object get(int index) { + ListUtils.CheckIndexInRange(0, size - 1, index); + return elementData[index]; + + } + + public int size() { + return size; + } + + public Iterator iterator() { + return new Iterator() { + private int cursor; + + @Override + public boolean hasNext() { + if (size > 0) { + return cursor < size; + } else { + return false; + } + + } + + @Override + public Object next() { + Object tag = get(cursor); + cursor++; + return tag; + } + }; + + } + +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Iterator.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Iterator.java new file mode 100644 index 0000000000..166a6181e3 --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Iterator.java @@ -0,0 +1,6 @@ +package main; + +public interface Iterator { + public boolean hasNext(); + public Object next(); +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ListUtils.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ListUtils.java new file mode 100644 index 0000000000..379e3b5a31 --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/ListUtils.java @@ -0,0 +1,11 @@ +package main; + +public class ListUtils { + public static boolean CheckIndexInRange(int start, int end, int index) { + if (index >= start && index <= end) { + return true; + } + throw new IndexOutOfBoundsException(); + } + +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Stack.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Stack.java new file mode 100644 index 0000000000..a584680425 --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/Stack.java @@ -0,0 +1,25 @@ +package main; + +public class Stack { + private ArrayList list = new ArrayList(); + + public void push(Object o) { + list.add(o); + } + + public Object pop() { + return list.remove(list.size() - 1); + } + + public Object peek() { + return list.get(list.size() - 1); + } + + public boolean isEmpty() { + return list.size() == 0; + } + + public int size() { + return list.size(); + } +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/main/StackUtil.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/StackUtil.java new file mode 100644 index 0000000000..125c9a0d72 --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/main/StackUtil.java @@ -0,0 +1,110 @@ +package main; + +import java.util.Arrays; + +public class StackUtil { + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack stack1 = new Stack(); + while (!s.isEmpty()) { + stack1.push(s.pop()); + } + Stack stack2 = new Stack(); + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + while (!stack2.isEmpty()) { + s.push(stack2.pop()); + } + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack stack = new Stack(); + while (!s.isEmpty()) { + stack.push(s.pop()); + } + while (!stack.isEmpty()) { + Object temp = stack.pop(); + if (!o.equals(temp)) { + s.push(temp); + } + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, + * 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if (len < 0) { + return new Object[0]; + } + Object[] objArray = new Object[len]; + int i = 0; + for (; i < len; i++) { + if (s.isEmpty()) { + break; + } + objArray[i] = s.pop(); + } + objArray = Arrays.copyOf(objArray, i); + for (int j = objArray.length - 1; j >= 0; j--) { + s.push(objArray[j]); + } + return objArray; + } + + /** + * 字符串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) { + String[] array = s.split(""); + Stack stack = new Stack(); + for (String s1 : array) { + if ("{[()]}".contains(s1)) { + if (!stack.isEmpty()) { + if (")]}".contains(s1)) { + if (s1.replace(")", "(").equals(stack.peek().toString()) + || s1.replace("]", "[").equals(stack.peek().toString()) + || s1.replace("}", "{").equals(stack.peek().toString())) { + stack.pop(); + } else { + return false; + } + } else { + stack.push(s1); + } + } else { + if (")]}".contains(s1)) { + return false; + } + stack.push(s1); + } + } + } + if (stack.isEmpty()) { + return true; + } + return false; + } + +} diff --git a/group23/1323434545/work_DataStructure/05_StackUtil/src/test/StackUtilTest.java b/group23/1323434545/work_DataStructure/05_StackUtil/src/test/StackUtilTest.java new file mode 100644 index 0000000000..87cddd271b --- /dev/null +++ b/group23/1323434545/work_DataStructure/05_StackUtil/src/test/StackUtilTest.java @@ -0,0 +1,93 @@ +package test; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +import main.Stack; +import main.StackUtil; + +public class StackUtilTest { + Stack stack; + + @Before + public void setUp() throws Exception { + stack = new Stack(); + } + + @Test + public void testReverse() { + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + StackUtil.reverse(stack); + int[] expected = { 1, 2, 3, 4, 5 }; + for (int i = 0; !stack.isEmpty(); i++) { + assertEquals(expected[i], stack.pop()); + } + } + + @Test + public void testRemove() { + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + StackUtil.remove(stack, 9); + int[] expected = { 5, 4, 3, 2, 1 }; + for (int i = 0; !stack.isEmpty(); i++) { + assertEquals(expected[i], stack.pop()); + } + + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + StackUtil.remove(stack, 3); + int[] expected1 = { 5, 4, 2, 1 }; + for (int i = 0; !stack.isEmpty(); i++) { + assertEquals(expected1[i], stack.pop()); + } + } + + @Test + public void testGetTop() { + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Object[] result = StackUtil.getTop(stack, 3); + int[] expected = { 5, 4, 3 }; + for (int i = 0; i < result.length; i++) { + assertEquals(expected[i], result[i]); + } + + result = StackUtil.getTop(stack, 9); + int[] expected1 = { 5, 4, 3, 2, 1 }; + for (int i = 0; i < result.length; i++) { + assertEquals(expected1[i], result[i]); + } + + result = StackUtil.getTop(stack, -1); + assertEquals(0, result.length); + } + + @Test + public void testIsValidPairs() { + assertTrue(StackUtil.isValidPairs("12wed333")); + assertTrue(StackUtil.isValidPairs("1{2[3(4)5]6}")); + assertTrue(StackUtil.isValidPairs("{{{[[[((()))]]]}}}")); + assertTrue(StackUtil.isValidPairs("{}[]()([{}])")); + assertFalse(StackUtil.isValidPairs(")abcd{}[]()")); + assertFalse(StackUtil.isValidPairs("a{b[c}d]()")); + assertFalse(StackUtil.isValidPairs("a{b)c}[]{}")); + assertFalse(StackUtil.isValidPairs("{}[](()")); + } + +} diff --git a/group23/1323434545/work_Other/01_litestruts/src/main/LoginAction.java b/group23/1323434545/work_Other/01_litestruts/src/main/LoginAction.java new file mode 100644 index 0000000000..1d62da0e04 --- /dev/null +++ b/group23/1323434545/work_Other/01_litestruts/src/main/LoginAction.java @@ -0,0 +1,36 @@ +package main; + +public class LoginAction { + private String name; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute() { + if ("test".equals(name) && "1234".equals(password)) { + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name) { + this.name = name; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMessage() { + return this.message; + } +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/01_litestruts/src/main/Struts.java b/group23/1323434545/work_Other/01_litestruts/src/main/Struts.java new file mode 100644 index 0000000000..21b889c070 --- /dev/null +++ b/group23/1323434545/work_Other/01_litestruts/src/main/Struts.java @@ -0,0 +1,71 @@ +package main; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Map; + +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +public class Struts { + /* + * + * 0. 读取配置文件struts.xml + * + * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 ("name"="test" , + * "password"="1234") , 那就应该调用 setName和setPassword方法 + * + * 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + * + * 3. 通过反射找到对象的所有getter方法(例如 getMessage), 通过反射来调用, 把值和属性形成一个HashMap , 例如 + * {"message": "登录成功"} , 放到View对象的parameters + * + * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, 放到View对象的jsp字段中。 + * + */ + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static View runAction(String actionName, Map parameters) + throws DocumentException, ReflectiveOperationException, SecurityException { + View view = null; + SAXReader reader = new SAXReader(); + Document document = reader.read(new File("./xml/struts.xml")); + Element root = document.getRootElement(); + for (Iterator iterator = (Iterator) root.elementIterator("action"); iterator.hasNext();) { + Element actionElement = (Element) iterator.next(); + String actionElementName = actionElement.attributeValue("name"); + if (actionElementName.equals(actionName)) { + Class c = Class.forName(actionElement.attributeValue("class")); + Constructor con = c.getConstructor(); + Object o = con.newInstance(); + Method setName = c.getMethod("setName", String.class); + setName.invoke(o, parameters.get("name")); + Method setPassword = c.getMethod("setPassword", String.class); + setPassword.invoke(o, parameters.get("password")); + Method execute = c.getMethod("execute"); + String resultStr = execute.invoke(o).toString(); + + for (iterator = actionElement.elementIterator("result"); iterator.hasNext();) { + Element resultElement = (Element) iterator.next(); + if (resultElement.attributeValue("name").equals(resultStr)) { + view = new View(); + parameters.put("name", c.getMethod("getName").invoke(o).toString()); + parameters.put("password", c.getMethod("getPassword").invoke(o).toString()); + parameters.put("message", c.getMethod("getMessage").invoke(o).toString()); + view.setJsp(resultElement.getStringValue()); + view.setParameters(parameters); + } + } + } + + } + return view; + + } + +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/01_litestruts/src/main/View.java b/group23/1323434545/work_Other/01_litestruts/src/main/View.java new file mode 100644 index 0000000000..2f54206090 --- /dev/null +++ b/group23/1323434545/work_Other/01_litestruts/src/main/View.java @@ -0,0 +1,27 @@ +package main; + +import java.util.Map; + +@SuppressWarnings("rawtypes") +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + + public Map getParameters() { + return parameters; + } + + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/01_litestruts/src/test/StrutsTest.java b/group23/1323434545/work_Other/01_litestruts/src/test/StrutsTest.java new file mode 100644 index 0000000000..7d5d431ac0 --- /dev/null +++ b/group23/1323434545/work_Other/01_litestruts/src/test/StrutsTest.java @@ -0,0 +1,55 @@ +package test; + +import java.util.HashMap; +import java.util.Map; + +import org.dom4j.DocumentException; +import org.junit.Assert; +import org.junit.Test; + +import main.Struts; +import main.View; + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name", "test"); + params.put("password", "1234"); + View view = null; + try { + view = Struts.runAction(actionName, params); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name", "tes"); + params.put("password", "1234"); + View view = null; + try { + view = Struts.runAction(actionName, params); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } + +} diff --git a/group23/1323434545/work_Other/02_downloader/src/api/Connection.java b/group23/1323434545/work_Other/02_downloader/src/api/Connection.java new file mode 100644 index 0000000000..828332de3b --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/api/Connection.java @@ -0,0 +1,23 @@ +package api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group23/1323434545/work_Other/02_downloader/src/api/ConnectionException.java b/group23/1323434545/work_Other/02_downloader/src/api/ConnectionException.java new file mode 100644 index 0000000000..d6265a5c4a --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/api/ConnectionException.java @@ -0,0 +1,6 @@ +package api; + +@SuppressWarnings("serial") +public class ConnectionException extends Exception{ + +} diff --git a/group23/1323434545/work_Other/02_downloader/src/api/ConnectionManager.java b/group23/1323434545/work_Other/02_downloader/src/api/ConnectionManager.java new file mode 100644 index 0000000000..1ff4788bf4 --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/02_downloader/src/api/DownloadListener.java b/group23/1323434545/work_Other/02_downloader/src/api/DownloadListener.java new file mode 100644 index 0000000000..b8ab21d462 --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/api/DownloadListener.java @@ -0,0 +1,5 @@ +package api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionImpl.java b/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionImpl.java new file mode 100644 index 0000000000..222284c175 --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionImpl.java @@ -0,0 +1,54 @@ +package impl; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import api.Connection; + +public class ConnectionImpl implements Connection{ + private HttpURLConnection huConn; + + + public ConnectionImpl(String url) { + try { + huConn = (HttpURLConnection) new URL(url).openConnection(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + huConn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + BufferedInputStream bis = new BufferedInputStream(huConn.getInputStream()); + int len =0; + byte[] bytes = new byte[1024]; + while((len=bis.read(bytes))!=-1){ + os.write(bytes, 0, len); + } + os.flush(); + return os.toByteArray(); + } + + @Override + public int getContentLength() { + return huConn.getContentLength(); + } + + @Override + public void close() { + if(null!=huConn){ + huConn.disconnect(); + } + + } + +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionManagerImpl.java b/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..c9c9e7378b --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/impl/ConnectionManagerImpl.java @@ -0,0 +1,15 @@ +package impl; + + + +import api.Connection; +import api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) { + return new ConnectionImpl(url); + } + +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/02_downloader/src/main/DownloadThread.java b/group23/1323434545/work_Other/02_downloader/src/main/DownloadThread.java new file mode 100644 index 0000000000..138dadf32f --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/main/DownloadThread.java @@ -0,0 +1,50 @@ +package main; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import api.Connection; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + File saveLocation; + CyclicBarrier barrier; + + public DownloadThread( Connection conn, int startPos, int endPos,File saveLocation,CyclicBarrier barrier){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.saveLocation = saveLocation; + this.barrier = barrier; + } + + @Override + public void run() { + RandomAccessFile rf = null; + try { + rf = new RandomAccessFile(saveLocation,"rw"); + rf.seek(startPos); + rf.write(conn.read(startPos, endPos)); + barrier.await(); + }catch (Exception e) { + e.printStackTrace(); + }finally { + if(null!=rf){ + try { + rf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(null!=conn){ + conn.close(); + } + + } + } +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/02_downloader/src/main/FileDownloader.java b/group23/1323434545/work_Other/02_downloader/src/main/FileDownloader.java new file mode 100644 index 0000000000..13f84bcb73 --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/main/FileDownloader.java @@ -0,0 +1,73 @@ +package main; + +import java.io.File; +import java.util.concurrent.CyclicBarrier; +import api.ConnectionException; +import api.ConnectionManager; +import api.DownloadListener; +import impl.ConnectionManagerImpl; + +public class FileDownloader { + + String url; + File saveLocation; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String url,File saveLocation) { + this.url = url; + this.saveLocation = saveLocation; + } + + + public void execute() throws ConnectionException{ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + + cm = new ConnectionManagerImpl(); + int length = cm.open(this.url).getContentLength(); + System.out.println("文件长度:"+length); + long time = System.currentTimeMillis(); + CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() { + @Override + public void run() { + listener.notifyFinished(); + System.out.println("耗时:"+(System.currentTimeMillis()-time)/1000+"秒"); + } + }); + + new DownloadThread(cm.open(this.url),0,length/3-1,saveLocation,barrier).start(); + new DownloadThread(cm.open(this.url),length/3,length*2/3-1,saveLocation,barrier).start(); + new DownloadThread(cm.open(this.url),length*2/3,length-1,saveLocation,barrier).start(); + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + + +} \ No newline at end of file diff --git a/group23/1323434545/work_Other/02_downloader/src/test/DownloaderTest.java b/group23/1323434545/work_Other/02_downloader/src/test/DownloaderTest.java new file mode 100644 index 0000000000..823e5ece37 --- /dev/null +++ b/group23/1323434545/work_Other/02_downloader/src/test/DownloaderTest.java @@ -0,0 +1,21 @@ +package test; + +import java.io.File; + +import api.ConnectionException; +import api.DownloadListener; +import main.FileDownloader; + +public class DownloaderTest { + public static void main(String[] args) throws ConnectionException { + FileDownloader fd = new FileDownloader("http://mirror.bit.edu.cn/apache/tomcat/tomcat-8/v8.5.13/bin/apache-tomcat-8.5.13.exe",new File("E:\\tomcat.exe")); + fd.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + System.out.println("下载完了!"); + } + }); + fd.execute(); + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/ArrayList.java b/group23/381519422/DataStructure/src/com/xiaol/study/ArrayList.java new file mode 100644 index 0000000000..f3d936f79b --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/ArrayList.java @@ -0,0 +1,94 @@ +package com.xiaol.study; + +/** + * @Description TODO + * @date 创建时间:2017年3月4日 下午11:03:26 + */ +public class ArrayList implements List { + + // 记录有多少元素 + private int size = 0; + + // 存放元素的数组 + private Object[] elementData = new Object[10]; + + // 添加元素 + public void add(Object o) { + checkSizeAndGrow(); + elementData[size++] = o; + } + + // 检查数组容量大小,不足就扩容 + private void checkSizeAndGrow() { + if (size >= elementData.length) { + Object[] oldData = elementData; + elementData = new Object[size * 2]; + System.arraycopy(oldData, 0, elementData, 0, size); + } + } + + // 在指定位置添加元素 + public void add(int index, Object o) { + checkIndex(index); + checkSizeAndGrow(); + // 把index位置的元素往后移一位 + System.arraycopy(elementData, index, elementData, index + 1, size - index); + elementData[index] = o; + size++; + } + + // 检查插入元素的位置是否非法 + private void checkIndex(int index) { + if (index < 0 || index > size) { + throw new RuntimeException("参数非法"); + } + } + + // 获取指定位置元素 + public Object get(int index) { + checkIndex(index); + return elementData[index]; + } + + // 移除指定位置元素 + public Object remove(int index) { + checkIndex(index); + Object returnVal = elementData[index]; + System.arraycopy(elementData, index + 1, elementData, index, size - index - 1); + size--; + return returnVal; + } + + // 获取ArrayList元素数量 + public int size() { + return size; + } + + // 获取迭代器 + public Iterator iterator() { + return new ArrayListIterator(); + } + + // 尽量实现迭代器 + private class ArrayListIterator implements Iterator { + + ArrayList list = null; + + @Override + public boolean hasNext() { + + return false; + } + + @Override + public Object next() { + return null; + } + + public Object remove() { + return null; + } + + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/ArrayListTest.java b/group23/381519422/DataStructure/src/com/xiaol/study/ArrayListTest.java new file mode 100644 index 0000000000..c8d865a394 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/ArrayListTest.java @@ -0,0 +1,82 @@ +package com.xiaol.study; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ArrayListTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddObject() { + ArrayList list = new ArrayList(); + list.add("a"); + list.add("b"); + list.add("c"); + list.add("d"); + list.add("e"); + list.add("f"); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + assertEquals(12, list.size()); + } + + @Test + public void testAddIntObject() { + ArrayList list = new ArrayList(); + list.add(1); + list.add(2); + list.add(0, 3); + assertEquals(3, list.get(0)); + assertEquals(1, list.get(1)); + assertEquals(2, list.get(2)); + assertEquals(3, list.size()); + } + + @Test + public void testGet() { + ArrayList list = new ArrayList(); + list.add(1); + list.add(2); + list.add(0, 3); + assertEquals(3, list.get(0)); + assertEquals(1, list.get(1)); + assertEquals(2, list.get(2)); + assertEquals(3, list.size()); + } + + @Test + public void testRemove() { + ArrayList list = new ArrayList(); + list.add(1); + list.add(2); + list.add(0, 3); + assertEquals(3, list.remove(0)); + assertEquals(1, list.remove(0)); + assertEquals(2, list.remove(0)); + assertEquals(0, list.size()); + } + + @Test + public void testSize() { + ArrayList list = new ArrayList(); + list.add(1); + list.add(2); + list.add(0, 3); + assertEquals(3, list.size()); + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNode.java b/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNode.java new file mode 100644 index 0000000000..a6275111e3 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNode.java @@ -0,0 +1,59 @@ +package com.xiaol.study; + +/** + * @Description TODO + * @date 创建时间:2017年3月5日 上午12:57:18 + */ +public class BinaryTreeNode { + // 要求,左节点比父节点小,右节点比父节点大 + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode insert(Object o) { + // 当前没有数据就放入当前节点 + if (data == null) { + this.data = o; + } else if ((int) data >= (int) o) {// 放入左节点 + if (left == null) { + left = new BinaryTreeNode(); + left.setData(o); + } else { + left.insert(o); + } + } else if ((int) data < (int) o) {// 放入右节点 + if (right == null) { + right = new BinaryTreeNode(); + right.setData(o); + } else { + right.insert(o); + } + } + return this; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public BinaryTreeNode getLeft() { + return left; + } + + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + + public BinaryTreeNode getRight() { + return right; + } + + public void setRight(BinaryTreeNode right) { + this.right = right; + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNodeTest.java b/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..654d79f0f3 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/BinaryTreeNodeTest.java @@ -0,0 +1,82 @@ +package com.xiaol.study; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class BinaryTreeNodeTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testInsert() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + btn.insert(2); + btn.insert(0); + btn.insert(3); + assertEquals(0, btn.getLeft().getData()); + assertEquals(1, btn.getData()); + assertEquals(2, btn.getRight().getData()); + assertEquals(3, btn.getRight().getRight().getData()); + } + + @Test + public void testGetData() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + assertEquals(1, btn.getData()); + } + + @Test + public void testSetData() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.setData(1); + assertEquals(1, btn.getData()); + } + + @Test + public void testGetLeft() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + btn.insert(0); + assertEquals(0, btn.getLeft().getData()); + } + + @Test + public void testSetLeft() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + BinaryTreeNode left = new BinaryTreeNode(); + left.setData(2); + btn.setLeft(left); + assertEquals(2, btn.getLeft().getData()); + } + + @Test + public void testGetRight() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + btn.insert(2); + assertEquals(2, btn.getRight().getData()); + } + + @Test + public void testSetRight() { + BinaryTreeNode btn = new BinaryTreeNode(); + btn.insert(1); + BinaryTreeNode right = new BinaryTreeNode(); + right.setData(2); + btn.setRight(right); + assertEquals(2, btn.getRight().getData()); + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/Iterator.java b/group23/381519422/DataStructure/src/com/xiaol/study/Iterator.java new file mode 100644 index 0000000000..745c732730 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/Iterator.java @@ -0,0 +1,12 @@ +package com.xiaol.study; + +/** + * @Description TODO + * @date 创建时间:2017年3月5日 上午1:12:05 + */ +public interface Iterator { + + public boolean hasNext(); + + public Object next(); +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/LinkedList.java b/group23/381519422/DataStructure/src/com/xiaol/study/LinkedList.java new file mode 100644 index 0000000000..aecd901e2d --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/LinkedList.java @@ -0,0 +1,253 @@ +package com.xiaol.study; + +/** + * @Description TODO + * @date 创建时间:2017年3月5日 上午12:30:18 + */ +public class LinkedList implements List { + + // 头指针 + private Node head; + + // 最后一个节点 + private Node lastNode; + + // 链表长度 + private int size; + + // 添加元素到最后一个节点 + public void add(Object o) { + if (null == head) { + head = new Node(o); + head.next = null; + lastNode = head; + size++; + } else { + lastNode.next = new Node(o); + lastNode = getLastNode(); + size++; + } + } + + // 获取最后一个节点 + private Node getLastNode() { + Node last = head; + while (last.next != null) { + last = last.next; + } + return last; + } + + // 获取指定位置的Node + private Node getIndexNode(int index) { + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node; + } + + // 添加元素到指定位置 + public void add(int index, Object o) { + checkIndex(index); + if (index == 0) { + // 将head暂存为headNext + Node headNext = head; + // 创建新的head + Node newHead = new Node(o); + head = newHead; + head.next = headNext; + } else { + // 获取第index-1个位置的Node + Node node = getIndexNode(index - 1); + // 暂存index位置的Node + Node nodeNext = node.next; + // 向index位置插入数据 + node.next = new Node(o); + node.next.next = nodeNext; + } + size++; + } + + // 获取指定位置元素 + public Object get(int index) { + checkIndex(index); + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.data; + } + + private void checkIndex(int index) { + if (index < 0 || index > size) { + throw new RuntimeException("非法参数"); + } + } + + // 移除指定位置元素 + public Object remove(int index) { + checkIndex(index); + Object data = null; + if (index == 0) { + // 新的head + Node newHead = head.next; + // 获取移除元素 + data = head.data; + // 将newHead设为head + head = newHead; + } else { + // 获取第index-1个位置的Node + Node node = getIndexNode(index - 1); + // 获取返回的元素 + data = node.next.data; + // 将index位置从链表删除 + node.next = node.next.next; + } + size--; + return data; + } + + // 获取链表长度 + public int size() { + return size; + } + + // 添加元素到第一个节点 + public void addFirst(Object o) { + add(0, o); + } + + public void addLast(Object o) { + Node lastNode = getLastNode(); + lastNode.next = new Node(o); + size++; + } + + // 移除第一个元素 + public Object removeFirst() { + return remove(0); + } + + // 移除最后一个元素 + public Object removeLast() { + Node lastNode = getLastNode(); + Object data = lastNode.data; + lastNode = null; + size--; + return data; + } + + public Iterator iterator() { + return null; + } + + // 用于存储数据的节点 + private static class Node { + Object data; + Node next; + + // 无参构造 + private Node() { + + } + + // 有参构造 + private Node(Object o) { + this.data = o; + } + } + + //---------------下面的方法暂时先不实现 + // removeDuplicateValues(),removeRange()可以不实现 + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i < 0) { + throw new RuntimeException("非法参数"); + } + Node indexNode = getIndexNode(i); + Node nextNode = getIndexNode(i); + for (int j = 0; j < length; j++) { + nextNode = nextNode.next; + } + indexNode.next = nextNode; + } + + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list) { + int[] retVal = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + int index = (int) list.get(i); + Node indexNode = getIndexNode(index); + int data = (int) indexNode.data; + retVal[i] = data; + } + return retVal; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/LinkedListTest.java b/group23/381519422/DataStructure/src/com/xiaol/study/LinkedListTest.java new file mode 100644 index 0000000000..faaa113907 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/LinkedListTest.java @@ -0,0 +1,131 @@ +package com.xiaol.study; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddObject() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(3, ll.get(2)); + } + + @Test + public void testAddIntObject() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(3, 0); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(3, ll.get(2)); + assertEquals(0, ll.get(3)); + assertEquals(4, ll.size()); + } + + @Test + public void testGet() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(3, 0); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(3, ll.get(2)); + assertEquals(0, ll.get(3)); + assertEquals(4, ll.size()); + } + + @Test + public void testRemove() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(0, 0); + ll.remove(0); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(3, ll.get(2)); + } + + @Test + public void testSize() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(0, 0); + assertEquals(4, ll.size()); + } + + @Test + public void testAddFirst() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.addFirst(001); + ll.addFirst(002); + assertEquals(002, ll.get(0)); + assertEquals(001, ll.get(1)); + assertEquals(1, ll.get(2)); + assertEquals(2, ll.get(3)); + } + + @Test + public void testAddLast() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.addLast(001); + ll.addLast(002); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(001, ll.get(2)); + assertEquals(002, ll.get(3)); + } + + @Test + public void testRemoveFirst() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.removeFirst(); + ll.removeFirst(); + assertEquals(3, ll.get(0)); + assertEquals(1, ll.size()); + } + + @Test + public void testRemoveLast() { + LinkedList ll = new LinkedList(); + ll.add(1); + ll.add(2); + ll.add(3); + ll.removeLast(); + assertEquals(1, ll.get(0)); + assertEquals(2, ll.get(1)); + assertEquals(2, ll.size()); + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/List.java b/group23/381519422/DataStructure/src/com/xiaol/study/List.java new file mode 100644 index 0000000000..aa8c23fba3 --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/List.java @@ -0,0 +1,13 @@ +package com.xiaol.study; + +public interface List { + public void add(Object o); + + public void add(int index, Object o); + + public Object get(int index); + + public Object remove(int index); + + public int size(); +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/Queue.java b/group23/381519422/DataStructure/src/com/xiaol/study/Queue.java new file mode 100644 index 0000000000..cae4a91cfb --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/Queue.java @@ -0,0 +1,41 @@ +package com.xiaol.study; + +import java.util.LinkedList; + +/** + * @Description TODO + * @date 创建时间:2017年3月5日 上午12:51:34 + */ +public class Queue { + + // 队列 + private LinkedList elementData = new LinkedList(); + // 队列长度 + private int size; + + // 添加元素到队列尾 + public void enQueue(Object o) { + elementData.add(o); + size++; + } + + // 移除队列头的元素 + public Object deQueue() { + Object data = elementData.removeLast(); + size--; + return data; + } + + // 队列是否为空 + public boolean isEmpty() { + if (size == 0) { + return true; + } + return false; + } + + // 队列长度 + public int size() { + return size; + } +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/QueueTest.java b/group23/381519422/DataStructure/src/com/xiaol/study/QueueTest.java new file mode 100644 index 0000000000..88fa5597db --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/QueueTest.java @@ -0,0 +1,64 @@ +package com.xiaol.study; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class QueueTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEnQueue() { + Queue q = new Queue(); + assertEquals(0, q.size()); + q.enQueue(1); + q.enQueue(2); + assertEquals(2, q.size()); + } + + @Test + public void testDeQueue() { + Queue q = new Queue(); + assertEquals(0, q.size()); + q.enQueue(1); + q.enQueue(2); + assertEquals(2, q.size()); + q.deQueue(); + q.deQueue(); + assertEquals(0, q.size()); + } + + @Test + public void testIsEmpty() { + Queue q = new Queue(); + assertEquals(true, q.isEmpty()); + q.enQueue(1); + q.enQueue(2); + assertEquals(false, q.isEmpty()); + q.deQueue(); + q.deQueue(); + assertEquals(true, q.isEmpty()); + } + + @Test + public void testSize() { + Queue q = new Queue(); + assertEquals(0, q.size()); + q.enQueue(1); + q.enQueue(2); + assertEquals(2, q.size()); + q.deQueue(); + q.deQueue(); + assertEquals(0, q.size()); + } + +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/Stack.java b/group23/381519422/DataStructure/src/com/xiaol/study/Stack.java new file mode 100644 index 0000000000..7a71ab6c6b --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/Stack.java @@ -0,0 +1,49 @@ +package com.xiaol.study; + +import java.util.ArrayList; + +/** + * @Description TODO + * @date 创建时间:2017年3月5日 上午12:47:15 + */ +public class Stack { + // 存数据的List + private ArrayList elementData = new ArrayList(); + + // 栈元素数量 + private int size; + + // 压栈 + public void push(Object o) { + elementData.add(o); + size++; + } + + // 弹出栈顶元素 + public Object pop() { + if (size == 0) { + throw new RuntimeException("Stack is Empty"); + } + Object data = elementData.remove(size - 1); + size--; + return data; + } + + // 获取栈顶元素 + public Object peek() { + return elementData.get(size - 1); + } + + // 是否为空 + public boolean isEmpty() { + if (size == 0) { + return true; + } + return false; + } + + // 栈大小 + public int size() { + return size; + } +} diff --git a/group23/381519422/DataStructure/src/com/xiaol/study/StackTest.java b/group23/381519422/DataStructure/src/com/xiaol/study/StackTest.java new file mode 100644 index 0000000000..937bbb831b --- /dev/null +++ b/group23/381519422/DataStructure/src/com/xiaol/study/StackTest.java @@ -0,0 +1,68 @@ +package com.xiaol.study; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class StackTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPush() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assertEquals(3, s.size()); + } + + @Test + public void testPop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assertEquals(3, s.pop()); + assertEquals(2, s.pop()); + assertEquals(1, s.pop()); + assertEquals(0, s.size()); + } + + @Test + public void testPeek() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assertEquals(3, s.peek()); + } + + @Test + public void testIsEmpty() { + Stack s = new Stack(); + assertEquals(true, s.isEmpty()); + s.push(1); + s.push(2); + s.push(3); + assertEquals(false, s.isEmpty()); + } + + @Test + public void testSize() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + assertEquals(3, s.size()); + } + +} diff --git a/group23/381519422/array/src/array/ArrayUtil.java b/group23/381519422/array/src/array/ArrayUtil.java new file mode 100644 index 0000000000..cb1d3f49dc --- /dev/null +++ b/group23/381519422/array/src/array/ArrayUtil.java @@ -0,0 +1,354 @@ +package array; + +import java.util.ArrayList; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin) { + if (origin == null || origin.length <= 1) { + return; + } + //第1和第length互换位置,第2和第length-1互换,以此类推 + for (int i = 0; i < origin.length / 2; i++) { + int temp = origin[i]; + origin[i] = origin[origin.length - 1 - i]; + origin[origin.length - 1 - i] = temp; + } + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + public int[] removeZero(int[] oldArray) { + // 判断非法输入 + if (oldArray == null || oldArray.length == 0) { + return null; + } + + // 创建临时数组,长度与原oldArray一样长 + int[] temp = new int[oldArray.length]; + int tempCount = 0; + for (int i = 0; i < oldArray.length; i++) { + // 判断元素是0跳过 + if (oldArray[i] == 0) { + continue; + } else {// 非零放入临时数组,计数器加1 + temp[tempCount++] = oldArray[i]; + } + } + + // 如果计数器与原数组长度一致,直接返回临时数组 + if (tempCount == oldArray.length) { + return temp; + } else {// 否则返回长度为tempCount的数组 + int[] retVal = new int[tempCount]; + System.arraycopy(temp, 0, retVal, 0, tempCount); + return retVal; + } + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + public int[] merge(int[] array1, int[] array2) { + // 创建临时数组,长度为array1+array2的长度 + int[] temp = new int[array1.length + array2.length]; + int index = 0;// temp的下标 + int i = 0;// array1的下标 + int j = 0;// array2的下标 + int count = 0;// temp存放元素的计数器 + + while (true) { + + if (i == array1.length) {// 当array1已经全部添加到temp,就把array2剩余的放入temp + for (int l = j; l < array2.length; l++) { + temp[index++] = array2[l]; + count++; + } + break; + } else if (j == array2.length) {// 当array2已经全部添加到temp,就把array1剩余的放入temp + for (int l = i; l < array1.length; l++) { + temp[index++] = array1[l]; + count++; + } + break; + } + + // 取array1第i和array2第j个元素比较。如果array1[i]的小于array2[j],则array1[i]放入temp + // 同时i++,使得下次为i+1和j个元素比较。 + // 如果array1第i和array2第j个元素相等。则array1[i]放入temp + // 同时i++,j++,使得下次为i+1和j+1个元素比较。 + if (array1[i] < array2[j]) { + temp[index++] = array1[i++]; + count++; + } else if (array1[i] > array2[j]) { + temp[index++] = array2[j++]; + count++; + } else { + temp[index++] = array1[i]; + i++; + j++; + count++; + } + } + + // 如果计数器和temp.length相等,直接返回 + if (count == temp.length) { + return temp; + } else {// 否则创建长度为count的新数组返回 + int[] retVal = new int[count]; + System.arraycopy(temp, 0, retVal, 0, count); + return retVal; + } + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int[] oldArray, int size) { + // 参数校验 + if (size < 0) { + throw new RuntimeException("非法参数"); + } + if (size == 0) { + return oldArray; + } + + // 扩容 + int[] retVal = new int[oldArray.length + size]; + for (int i = 0; i < oldArray.length; i++) { + retVal[i] = oldArray[i]; + } + return retVal; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max) { + // 0直接返回空数组 + if (max == 1) { + return new int[0]; + } + + int retVal = 0;// 每一轮循环的斐波那契数 + int i = 1;// 获取第几个斐波那契数 + ArrayList list = new ArrayList();// 用于暂时保存斐波那契数 + while (retVal < max) {// 获取所有小于max的斐波那契数 + retVal = getFibonacci(i++); + if (retVal < max) { + list.add(retVal); + } else { + break; + } + } + + // 将arraylist转为array + int[] retArray = new int[list.size()]; + for (int j = 0; j < list.size(); j++) { + retArray[j] = list.get(j); + } + return retArray; + } + + /** + * 循环获取第N个斐波那契数 + * @param index + * @return + */ + private int getFibonacci(int index) { + if (index < 1) { + throw new RuntimeException("非法参数"); + } + if (index == 1 || index == 2) { + return 1; + } + + int first = 1; + int second = 1; + int retVal = 0; + for (int i = 3; i <= index; i++) { + retVal = first + second; + first = second; + second = retVal; + } + return retVal; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max) { + // 排除非法参数 + if (max < 0) { + throw new RuntimeException("非法参数"); + } + + // 小于2没有素数 + if (max <= 1) { + return new int[0]; + } + + ArrayList list = new ArrayList(); + // 取出每个数判断是不是素数,是就放入arraylist + for (int i = 2; i < max; i++) { + boolean primes = isPrimes(i); + if (primes) { + list.add(i); + } + } + + int[] retArray = new int[list.size()]; + // 将ArrayList转为数组返回 + for (int i = 0; i < list.size(); i++) { + retArray[i] = list.get(i); + } + return retArray; + } + + /** + * 判断输入的数字是不是素数 + * @param num + * @return + */ + private boolean isPrimes(int num) { + // 排除非法参数 + if (num <= 0) { + throw new RuntimeException("非法参数"); + } + + // 小于2没有素数 + if (num == 1) { + return false; + } + + // 2是素数,但是2%2==0为true,所以单独列出 + if (num == 2) { + return true; + } + + // num依次从2到num的平方根取余数,如果余数为零说明不是素数 + for (int i = 2; i <= Math.sqrt(num); i++) { + if (num % i == 0) { + return false; + } + } + return true; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max) { + if (max < 0) { + throw new RuntimeException("非法参数"); + } + if (max <= 2) { + return new int[0]; + } + + // 获取小于max 的所有完数 + ArrayList list = new ArrayList(); + for (int i = 1; i < max; i++) { + if (isPerfectNumber(i)) { + list.add(i); + } + } + + // 将ArrayList转为array返回 + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; + } + + /** + * 判断输入的数是不是完美数 + * @param num + * @return + */ + private boolean isPerfectNumber(int num) { + if (num <= 0) { + throw new RuntimeException("非法参数"); + } + + // 放置num的所有约数 + ArrayList divisorList = new ArrayList(); + for (int i = 1; i < num; i++) { + if (num % i == 0) { + divisorList.add(i); + } + } + + // 所有因数相加是否等于num,是就是完美数 + int count = 0; + for (int i = 0; i < divisorList.size(); i++) { + count += divisorList.get(i); + } + if (count == num) { + return true; + } else { + return false; + } + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator) { + // 检查非法输入 + if (array == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + if (i == array.length - 1) {// 最后一个元素后面不拼接- + sb.append(array[i]); + } else { + sb.append(array[i]); + sb.append("-"); + } + } + return sb.toString(); + } + + +} \ No newline at end of file diff --git a/group23/381519422/array/src/array/ArrayUtilTest.java b/group23/381519422/array/src/array/ArrayUtilTest.java new file mode 100644 index 0000000000..a202afdb20 --- /dev/null +++ b/group23/381519422/array/src/array/ArrayUtilTest.java @@ -0,0 +1,116 @@ +package array; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ArrayUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReverseArray() { + int[] a = { 7, 9, 30, 3, 4 }; + int[] expecteds = { 4, 3, 30, 9, 7 }; + ArrayUtil util = new ArrayUtil(); + util.reverseArray(a); + assertArrayEquals(expecteds, a); + } + + @Test + public void testRemoveZero() { + int[] oldArr = { 1, 3, 4, 5, 0, 0, 6, 6, 0, 5, 4, 7, 6, 7, 0, 5 }; + int[] expecteds = { 1, 3, 4, 5, 6, 6, 5, 4, 7, 6, 7, 5 }; + ArrayUtil util = new ArrayUtil(); + int[] removeZero = util.removeZero(oldArr); + assertArrayEquals(expecteds, removeZero); + } + + @Test + public void testMerge() { + int[] a1 = { 3, 5, 7, 8 }; + int[] a2 = { 4, 5, 6, 7 }; + ArrayUtil util = new ArrayUtil(); + int[] merge = util.merge(a1, a2); + int[] expecteds = { 3, 4, 5, 6, 7, 8 }; + assertArrayEquals(expecteds, merge); + } + + @Test + public void testGrow() { + int[] oldArray = { 2, 3, 6 }; + int size = 3; + int[] expecteds = { 2, 3, 6, 0, 0, 0 }; + ArrayUtil util = new ArrayUtil(); + int[] grow = util.grow(oldArray, size); + assertArrayEquals(expecteds, grow); + } + + @Test + public void testFibonacci() { + int max1 = 15; + int[] expecteds1 = { 1, 1, 2, 3, 5, 8, 13 }; + ArrayUtil util = new ArrayUtil(); + int[] fibonacci1 = util.fibonacci(max1); + assertArrayEquals(expecteds1, fibonacci1); + + int max2 = 1; + int[] expecteds2 = {}; + int[] fibonacci2 = util.fibonacci(max2); + assertArrayEquals(expecteds2, fibonacci2); + } + + @Test + public void testGetPrimes() { + int max1 = 23; + int[] expecteds1 = { 2, 3, 5, 7, 11, 13, 17, 19 }; + ArrayUtil util = new ArrayUtil(); + int[] primes1 = util.getPrimes(max1); + assertArrayEquals(expecteds1, primes1); + + int max2 = 2; + int[] expecteds2 = {}; + int[] primes2 = util.getPrimes(max2); + assertArrayEquals(expecteds2, primes2); + } + + @Test + public void testGetPerfectNumbers() { + int max1 = 2; + int[] expecteds1 = {}; + ArrayUtil util = new ArrayUtil(); + int[] perfectNumbers1 = util.getPerfectNumbers(max1); + assertArrayEquals(expecteds1, perfectNumbers1); + + // 6=1+2+3 + int max2 = 7; + int[] expecteds2 = { 6 }; + int[] perfectNumbers2 = util.getPerfectNumbers(max2); + assertArrayEquals(expecteds2, perfectNumbers2); + + // 28=1+2+4+7+14 + int max3 = 30; + int[] expecteds3 = { 6, 28 }; + int[] perfectNumbers3 = util.getPerfectNumbers(max3); + assertArrayEquals(expecteds3, perfectNumbers3); + } + + @Test + public void testJoin() { + int[] array = { 3, 8, 9 }; + String seperator = "-"; + String expecteds = "3-8-9"; + ArrayUtil util = new ArrayUtil(); + String join = util.join(array, seperator); + assertEquals(expecteds, join); + } + +} diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/DownloadDemo.java b/group23/381519422/download/src/main/java/com/xiaol/download/DownloadDemo.java new file mode 100644 index 0000000000..fc1ec892f9 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/DownloadDemo.java @@ -0,0 +1,53 @@ +package com.xiaol.download; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +/** + * 下载DEMO + * @author ShawnLin + */ +public class DownloadDemo { + + public void download(String url) { + URL u; + try { + u = new URL(url); + HttpURLConnection httpURLConnection = (HttpURLConnection) u.openConnection(); + int contentLength = httpURLConnection.getContentLength(); + httpURLConnection.connect(); + InputStream inputStream = httpURLConnection.getInputStream(); + File file = new File(getFileName(url)); + RandomAccessFile raf = new RandomAccessFile(file, "rwd"); + byte[] read = new byte[1024]; + int length = 0; + while ((length = inputStream.read(read)) != -1) { + raf.write(read, 0, length); + } + inputStream.close(); + raf.close(); + System.out.println("下载完毕,位置[" + file.getAbsolutePath() + "]"); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public String getFileName(String path) { + int index = path.lastIndexOf("/"); + return path.substring(index + 1); + } + + public static void main(String[] args) { + DownloadDemo dd = new DownloadDemo(); + String url = "http://ww3.sinaimg.cn/large/729119fdgw1f0nnftw3hij21kw11x4qp.jpg"; + dd.download(url); + } +} diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/DownloadThread.java b/group23/381519422/download/src/main/java/com/xiaol/download/DownloadThread.java new file mode 100644 index 0000000000..bb9c5cdac7 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/DownloadThread.java @@ -0,0 +1,37 @@ +package com.xiaol.download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.xiaol.download.api.Connection; +import com.xiaol.download.api.DownloadListener; + +public class DownloadThread extends Thread { + + Connection conn; + int startPos; + int endPos; + RandomAccessFile randomAccessFile; + DownloadListener listener; + + public DownloadThread(Connection conn, int startPos, int endPos, RandomAccessFile randomAccessFile) { + this.randomAccessFile = randomAccessFile; + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + + @Override + public void run() { + try { + byte[] read = conn.read(startPos, endPos); + randomAccessFile.seek(startPos); + randomAccessFile.write(read, 0, endPos - startPos); + System.out.println(this.getName() + "完成下载,从" + startPos + "到" + endPos + "共" + (endPos - startPos)); + conn.close(); + FileDownloader.finishCount(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloader.java b/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloader.java new file mode 100644 index 0000000000..e56d9d8939 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloader.java @@ -0,0 +1,133 @@ +package com.xiaol.download; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.xiaol.download.api.Connection; +import com.xiaol.download.api.ConnectionException; +import com.xiaol.download.api.ConnectionManager; +import com.xiaol.download.api.DownloadListener; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + private static int count = 0; + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute() { + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, + // endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, + // 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + // Connection conn = null; + // try { + // + // conn = cm.open(this.url); + // + // int length = conn.getContentLength(); + // + // new DownloadThread(conn,0,length-1).start(); + // + // } catch (ConnectionException e) { + // e.printStackTrace(); + // }finally{ + // if(conn != null){ + // conn.close(); + // } + // } + + Connection conn = null; + try { + + File file = new File(getFileName(url)); + RandomAccessFile raf = new RandomAccessFile(file, "rwd"); + System.out.println("文件下载位置:[" + file.getAbsolutePath() + "]"); + int threadNum = 3; + conn = cm.open(this.url); + int length = conn.getContentLength(); + int avg = length / threadNum; + for (int i = 0; i < threadNum; i++) { + Connection cTemp = cm.open(this.url); + int start = i * avg; + int end = start + avg - 1; + if (i == threadNum - 1) { + end = length - 1; + } + new DownloadThread(cTemp, start, end, raf).start(); + } + + while (true) { + if (threadNum == getFinishCount()) { + listener.notifyFinished(); + try { + raf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + break; + } + } + } catch (ConnectionException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (conn != null) { + conn.close(); + } + } + + } + + /** + * 获取文件名 + * + * @param path + * @return + */ + public String getFileName(String path) { + int index = path.lastIndexOf("/"); + return path.substring(index + 1); + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm) { + this.cm = ucm; + } + + public DownloadListener getListener() { + return this.listener; + } + + public static void finishCount() { + count++; + } + + public int getFinishCount() { + return count; + } +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloaderTest.java b/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloaderTest.java new file mode 100644 index 0000000000..ee724f5d44 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/FileDownloaderTest.java @@ -0,0 +1,60 @@ +package com.xiaol.download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.xiaol.download.api.ConnectionManager; +import com.xiaol.download.api.DownloadListener; +import com.xiaol.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + +// String url = "http://localhost:8080/test.jpg"; + String url = "http://ww3.sinaimg.cn/large/729119fdgw1f0nnftw3hij21kw11x4qp.jpg"; + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/api/Connection.java b/group23/381519422/download/src/main/java/com/xiaol/download/api/Connection.java new file mode 100644 index 0000000000..dc688e1fbe --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.xiaol.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionException.java b/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionException.java new file mode 100644 index 0000000000..813f6756bf --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.xiaol.download.api; + +public class ConnectionException extends Exception { + +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionManager.java b/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionManager.java new file mode 100644 index 0000000000..84adef2054 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.xiaol.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/api/DownloadListener.java b/group23/381519422/download/src/main/java/com/xiaol/download/api/DownloadListener.java new file mode 100644 index 0000000000..30e7eaced2 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.xiaol.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionImpl.java b/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..fcd2a37cdc --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionImpl.java @@ -0,0 +1,60 @@ +package com.xiaol.download.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import com.xiaol.download.api.Connection; + +public class ConnectionImpl implements Connection { + + private HttpURLConnection httpURLConnection; + + public ConnectionImpl(String url) { + try { + this.httpURLConnection = (HttpURLConnection) new URL(url).openConnection(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + httpURLConnection.setRequestMethod("GET"); + httpURLConnection.setConnectTimeout(5000); + httpURLConnection.setReadTimeout(5000); + httpURLConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + httpURLConnection.connect(); + List list = new ArrayList<>(); + byte[] byteArray = null; + byte[] read = new byte[1024]; + int length = 0; + if (httpURLConnection.getResponseCode() == 206) { + InputStream inputStream = httpURLConnection.getInputStream(); + byteArray = new byte[endPos - startPos + 1]; + while ((length = inputStream.read(byteArray)) != -1) { + + } + inputStream.close(); + } + close(); + return byteArray; + } + + @Override + public int getContentLength() { + return httpURLConnection.getContentLength(); + } + + @Override + public void close() { + httpURLConnection.disconnect(); + } + +} \ No newline at end of file diff --git a/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionManagerImpl.java b/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..730aaca153 --- /dev/null +++ b/group23/381519422/download/src/main/java/com/xiaol/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,15 @@ +package com.xiaol.download.impl; + +import com.xiaol.download.api.Connection; +import com.xiaol.download.api.ConnectionException; +import com.xiaol.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + Connection connection = new ConnectionImpl(url); + return connection; + } + +} \ No newline at end of file diff --git a/group23/381519422/litestruts/src/main/java/com/xiaol/study/LoginAction.java b/group23/381519422/litestruts/src/main/java/com/xiaol/study/LoginAction.java new file mode 100644 index 0000000000..0a0bde6888 --- /dev/null +++ b/group23/381519422/litestruts/src/main/java/com/xiaol/study/LoginAction.java @@ -0,0 +1,36 @@ +package com.xiaol.study; + +public class LoginAction { + private String name; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute() { + if ("test".equals(name) && "1234".equals(password)) { + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name) { + this.name = name; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMessage() { + return this.message; + } +} diff --git a/group23/381519422/litestruts/src/main/java/com/xiaol/study/Struts.java b/group23/381519422/litestruts/src/main/java/com/xiaol/study/Struts.java new file mode 100644 index 0000000000..cadbfc9300 --- /dev/null +++ b/group23/381519422/litestruts/src/main/java/com/xiaol/study/Struts.java @@ -0,0 +1,176 @@ +package com.xiaol.study; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import javax.management.RuntimeErrorException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + + +public class Struts { + + // 每一个action的信息存放到一个Map里 + // 所有的Map放到rootMap方便统一管理 + private static HashMap> rootMap = new HashMap>(); + + public static View runAction(String actionName, Map parameters) { + View view = new View(); + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + try { + // 1、初始化读取配置文件 + init(); + + // 2、获取根据参数获取对应的class的名字 + Map actionMap = rootMap.get(actionName); + String className = actionMap.get("class"); + // 3、根据名字获取Class对象 + Class clazzType = Class.forName(className); + // 4、通过无参构造获取一个对象 + Object newInstance = clazzType.getConstructor(new Class[] {}).newInstance(new Object[] {}); + // 5、调用set方法,把("name"="test" , "password"="1234")值set进去 + Set> entrySet = parameters.entrySet(); + Iterator> iterator = entrySet.iterator(); + while (iterator.hasNext()) { + Entry next = iterator.next(); + String key = next.getKey(); + String value = next.getValue(); + String setMethodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1); + Field declaredField = clazzType.getDeclaredField(key); + Method setMehtod = clazzType.getDeclaredMethod(setMethodName, new Class[] { declaredField.getType() }); + setMehtod.invoke(newInstance, value); + } + // 6、执行execute方法 + String executeMethodName = "execute"; + Method executeMethod = clazzType.getDeclaredMethod(executeMethodName); + Object resultString = (String) executeMethod.invoke(newInstance); + + // 7、通过反射获取message信息 + String getMethodName = "getMessage"; + Field declaredField = clazzType.getDeclaredField("message"); + Method getMehtod = clazzType.getDeclaredMethod(getMethodName); + String message = (String) getMehtod.invoke(newInstance); + + // 8\ + String jsp = actionMap.get(resultString); + view.setJsp(jsp); + Map hashMap = new HashMap<>(); + hashMap.put("message", message); + view.setParameters(hashMap); + } catch (Exception e) { + e.printStackTrace(); + throw new ExceptionInInitializerError(); + } + return view; + } + + public static void init() throws Exception { + + // 1、获取工厂实例 + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + // 2、获取dom解析器 + DocumentBuilder db = dbf.newDocumentBuilder(); + // 3、解析xml文档,获取document对象(根节点) + // 也可以获取流使用db.parse(InputStream) + // InputStream is = + // this.getClass().getResourceAsStream("D:\\GitHub\\coding2017\\group23\\381519422\\litestruts\\src\\main\\resources\\struts.xml"); + Document document = db.parse( + new File("D:\\GitHub\\coding2017\\group23\\381519422\\litestruts\\src\\main\\resources\\struts.xml")); + NodeList list = document.getElementsByTagName("action"); + + /* + * 开始循环list,list中每一个元素结构如下 + * + /jsp/homepage.jsp + /jsp/showLogin.jsp + + */ + for (int i = 0; i < list.getLength(); i++) { + Map actionMap = new HashMap(); + // 注意:使用的都是org.w3c.dom包下的 + Element element = (Element) list.item(i); + // 获取中 name对应的属性值 + String actionAttributeName = element.getAttribute("name"); + String className = element.getAttribute("class"); + actionMap.put("class", className); + + // 读取第一个action + NamedNodeMap nnm = element.getElementsByTagName("result").item(0).getAttributes(); + // 获取的属性 name + // String nodeName = nnm.item(0).getNodeName(); + // element.getElementsByTagName("result").item(0) + // 是/jsp/homepage.jsp + // getFirstChild().getNodeValue() 是获取上面内容的/jsp/homepage.jsp + String context = element.getElementsByTagName("result").item(0).getTextContent(); + // 获取的属性 name对应的值success + String nodeValue = nnm.item(0).getNodeValue(); + actionMap.put(nodeValue, context); + + // 读取第二个action + nnm = element.getElementsByTagName("result").item(1).getAttributes(); + // 获取的属性 name + // nodeName = nnm.item(0).getNodeName(); + context = element.getElementsByTagName("result").item(1).getFirstChild().getNodeValue(); + // 获取的属性 name对应的值success + nodeValue = nnm.item(0).getNodeValue(); + actionMap.put(nodeValue, context); + + rootMap.put(actionAttributeName, actionMap); + } + } + + public static void main(String[] args) { + try { + init(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + // 内部类用于存放从配置文件读取的数据 + class StrutsMap { + private HashMap map; + + public String get(String key) { + return map.get(key); + } + + public void set(String key, String value) { + map.put(key, value); + } + } +} diff --git a/group23/381519422/litestruts/src/main/java/com/xiaol/study/StrutsTest.java b/group23/381519422/litestruts/src/main/java/com/xiaol/study/StrutsTest.java new file mode 100644 index 0000000000..40bc45d280 --- /dev/null +++ b/group23/381519422/litestruts/src/main/java/com/xiaol/study/StrutsTest.java @@ -0,0 +1,43 @@ +package com.xiaol.study; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group23/381519422/litestruts/src/main/java/com/xiaol/study/View.java b/group23/381519422/litestruts/src/main/java/com/xiaol/study/View.java new file mode 100644 index 0000000000..03a1538403 --- /dev/null +++ b/group23/381519422/litestruts/src/main/java/com/xiaol/study/View.java @@ -0,0 +1,26 @@ +package com.xiaol.study; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + + public Map getParameters() { + return parameters; + } + + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group23/563253496/week4_jvm1/src/com/coderising/jvm/loader/ClassFileLoader.java b/group23/563253496/week4_jvm1/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..5f56b80bff --- /dev/null +++ b/group23/563253496/week4_jvm1/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,81 @@ +package com.coderising.jvm.loader; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + String path = getClassFilePath(className); + if (path != null) { + try { + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path)); + int count = bis.available(); + byte[] content = new byte[count]; + int len = bis.read(content,0,count); + return content; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + + + } + + private byte[] loadClassFile(String clzFileName) { + + return null; + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + public String getClassPath_V1() { + + return null; + } + + public String getClassPath() { + StringBuilder sb = new StringBuilder(); + for (String s : clzPaths) { + sb.append(s); + sb.append(";"); + } + sb.deleteCharAt(sb.length() - 1); + return sb.toString(); + } + + private String getClassFilePath(String className) { + StringBuilder sb = new StringBuilder(); + for (String path : clzPaths + ) { + sb.append(path); + sb.append("\\"); + char[] classname = className.toCharArray(); + for (int i = 0; i < classname.length; i++) { + if (classname[i] == '.') { + sb.append("\\"); + + } else { + sb.append(classname[i]); + } + } + sb.append(".class"); + String classpath = sb.toString(); + File file = new File(classpath); + if (file.exists()) { + return classpath; + } + } + return null; + } +} diff --git a/group23/563253496/week4_jvm1/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group23/563253496/week4_jvm1/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..1e00b5f2f5 --- /dev/null +++ b/group23/563253496/week4_jvm1/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,92 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.loader.ClassFileLoader; + + + + + +public class ClassFileloaderTest { + + + static String path1 = "D:\\mygit\\coding2017\\group23\\563253496\\week5_jvm\\out\\production\\untitled"; + static String path2 = "C:\\temp"; + + + + @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 = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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 +* @since
 29, 2017
+* @version 1.0 +*/ public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + } + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + 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 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(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/StringInfo.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..577e41536b --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + this.pos = 0; + } + + public byte[] getCodes(int length) { + if (this.pos + length >= this.codes.length) { + throw new IndexOutOfBoundsException(); + } + + byte[] buffer = new byte[length]; + for (int i = 0; i < length; i++) { + buffer[i] = this.codes[pos++]; + } + return buffer; + } + + 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[] buffer = new byte[len]; + for (int i = 0; i < len; i++) { + buffer[i] = this.codes[pos++]; + } + return Util.byteToHexString(buffer); + } + + public void back(int i) { + this.pos -= i; + + } +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..be4e12c7de --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +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", 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()); + } + + + +} diff --git a/group23/563253496/week5_jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..c3e3931582 --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.test; + +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/group23/563253496/week5_jvm/src/com/coderising/jvm/util/Util.java b/group23/563253496/week5_jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group23/563253496/week5_jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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.size()) { + throw new IndexOutOfBoundsException(); + } + Object[] o = new Object[len]; + Stack temp = new Stack(); + + for (int i = 0; i < len; i++) { + o[i] = s.peek(); + temp.push(s.pop()); + + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + return o; + + } + + + /** + * 字符串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) { + char[] chars = s.toCharArray(); + Stack stack = new Stack(); + + for (int i = 0; i < chars.length; i++) { + switch (chars[i]) { + case '(': + stack.push('('); + break; + case '[': + stack.push('['); + break; + case '{': + stack.push('{'); + break; + case ')': + if (!stack.pop().equals('(')) { + return false; + } + break; + case ']': + if (!stack.pop().equals('[')) { + return false; + } + break; + case '}': + if (!stack.pop().equals('{')) { + return false; + } + break; + } + } + + return true; + } + + +} diff --git a/group23/563253496/week5_stack/src/test/StackUtilTest.java b/group23/563253496/week5_stack/src/test/StackUtilTest.java new file mode 100644 index 0000000000..fc1e727103 --- /dev/null +++ b/group23/563253496/week5_stack/src/test/StackUtilTest.java @@ -0,0 +1,95 @@ +package test; + +import junit.framework.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +import stack.Stack; +import stack.StackUtil; + +import static com.sun.xml.internal.ws.dump.LoggingDumpTube.Position.After; +import static com.sun.xml.internal.ws.dump.LoggingDumpTube.Position.Before; + +/** +* stack.StackUtil Tester. +* +* @author +* @since
 8, 2017
+* @version 1.0 +*/ +public class StackUtilTest { + +@Before +public void before() throws Exception { +} + +@After +public void after() throws Exception { +} + +/** +* +* Method: reverse(stack.Stack s) +* +*/ +@Test +public void testReverse() throws Exception { +//TODO: Test goes here... + Stack s = new Stack(); + for (int i = 1; i <=5 ; i++) { + s.push(i); + } + Assert.assertEquals("5,4,3,2,1,",s.toString()); + StackUtil.reverse(s); + + Assert.assertEquals("1,2,3,4,5,",s.toString()); +} + +/** +* +* Method: remove(stack.Stack s, Object o) +* +*/ +@Test +public void testRemove() throws Exception { + Stack s = new Stack(); + for (int i = 1; i <=5 ; i++) { + s.push(i); + } + Assert.assertEquals("5,4,3,2,1,",s.toString()); + StackUtil.remove(s,1); + + Assert.assertEquals("5,4,3,2,",s.toString()); +//TODO: Test goes here... +} + +/** +* +* Method: getTop(stack.Stack s, int len) +* +*/ +@Test +public void testGetTop() throws Exception { +//TODO: Test goes here... +} + +/** +* +* Method: isValidPairs(String s) +* +*/ +@Test +public void testIsValidPairs() throws Exception { +//TODO: Test goes here... + String s = "([e{d}f])"; + boolean b = StackUtil.isValidPairs(s); + Assert.assertEquals(true,b); + s = "([b{x]y})"; + b = StackUtil.isValidPairs(s); + Assert.assertEquals(false,b); + +} + + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..9bace446db --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,142 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.cmd.*; +import sun.text.CodePointIterator; + +import java.io.UnsupportedEncodingException; + + +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 attribute_name_index = iter.nextU2ToInt(); + if (!clzFile.getConstantPool().getUTF8String(attribute_name_index).equalsIgnoreCase(CODE)) { + throw new RuntimeException("CODE属性的attributenameindex解析错误"); + } + + int attribute_len = iter.nextU4ToInt(); + byte[] bytes = iter.getBytes(attribute_len); + ByteCodeIterator codeIter = new ByteCodeIterator(bytes); + + int max_stack = codeIter.nextU2ToInt(); + int max_locals = codeIter.nextU2ToInt(); + int code_len = codeIter.nextU4ToInt(); + /*byte[] codes = codeIter.getBytes(code_len); + + String code = null; + try { + + code = new String(codes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } +*/ + + String code = codeIter.nextUxToHexString(code_len); + + ByteCodeCommand[] cmds = CommandParser.parse(clzFile, code); + + CodeAttr codeAttr = new CodeAttr(attribute_name_index, attribute_len, max_stack, max_locals, code_len, code, cmds); + + int exception_table_len = codeIter.nextU2ToInt(); + if (exception_table_len > 0) { + throw new RuntimeException("方法的code属性中有异常未进行解析"); + } + + //code中的属性 + int attribute_count = codeIter.nextU2ToInt(); + /*byte[] bytes1 = codeIter.getBytes(attribute_length); + ByteCodeIterator codeAttrIter = new ByteCodeIterator(bytes1); + + while (codeAttrIter.isNotEnd()) { + int attributenameindex = codeAttrIter.nextU2ToInt(); + if (clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(LINE_NUM_TABLE)) { + LineNumberTable table = LineNumberTable.parse(codeAttrIter, attributenameindex); + codeAttr.setLineNumberTable(table); + } else if (clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(LOCAL_VAR_TABLE)) { + LocalVariableTable table = LocalVariableTable.parse(codeAttrIter,attributenameindex); + codeAttr.setLocalVariableTable(table); + }else if(clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(STACK_MAP_TABLE)){ + codeIter.back(2); + StackMapTable table = StackMapTable.parse(codeIter); + codeAttr.setStackMapTable(table); + } + }*/ + for (int i = 0; i < attribute_count; i++) { + int attributenameindex = codeIter.nextU2ToInt(); + if (clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(LINE_NUM_TABLE)) { + LineNumberTable table = LineNumberTable.parse(codeIter, attributenameindex); + codeAttr.setLineNumberTable(table); + } else if (clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(LOCAL_VAR_TABLE)) { + LocalVariableTable table = LocalVariableTable.parse(codeIter,attributenameindex); + codeAttr.setLocalVariableTable(table); + }else if(clzFile.getConstantPool().getUTF8String(attributenameindex).equalsIgnoreCase(STACK_MAP_TABLE)){ + codeIter.back(2); + StackMapTable table = StackMapTable.parse(codeIter); + codeAttr.setStackMapTable(table); + } + + } + + + + + return codeAttr; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + 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 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 attribute_name_index) { + int ccc = (iter.codes.length); + long attribute_len = iter.nextU4ToInt(); + int line_number_table_len = iter.nextU2ToInt(); + LineNumberTable table = new LineNumberTable(attribute_name_index,(int)attribute_len); + + /*byte[] bytes = iter.getBytes(line_number_table_len); + ByteCodeIterator lntIter = new ByteCodeIterator(bytes);*/ + + + /*while (lntIter.isNotEnd()) { + //int c = lntIter.codes.length; + LineNumberItem item = new LineNumberItem(); + item.setStartPC(lntIter.nextU2ToInt()); + item.setLineNum(lntIter.nextU2ToInt()); + table.addLineNumberItem(item); + }*/ + + + + for (int i = 0; i items = new ArrayList(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LocalVariableTable parse(ByteCodeIterator iter,int attribute_name_index) { + int attribute_len = iter.nextU2ToInt(); + + byte[] bytes = iter.getBytes(attribute_len); + ByteCodeIterator lvtIter = new ByteCodeIterator(bytes); + + LocalVariableTable table = new LocalVariableTable(attribute_name_index,attribute_len); + + while(lvtIter.isNotEnd()){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(lvtIter.nextU2ToInt()); + item.setLength(lvtIter.nextU2ToInt()); + item.setNameIndex(lvtIter.nextU2ToInt()); + item.setDescIndex(lvtIter.nextU2ToInt()); + item.setIndex(lvtIter.nextU2ToInt()); + 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(); + } + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.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/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..aa4f4cb5ad --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,113 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +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()); + + + } + + private String getClassName() { + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo) this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo) this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public Method getMethod(String methodName, String paramAndReturnType) { + Method method = new Method(this,this.accessFlag,) + + } + + public Method getMainMethod() { + + + } +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..d84508c68b --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,130 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; +import com.sun.org.apache.bcel.internal.generic.BIPUSH; +import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; + +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) { + + codes = codes.toUpperCase(); + if (codes == "" || codes == null) { + throw new RuntimeException("codes为空!"); + } + List cmds = new LinkedList(); + + CommandIterator iter = new CommandIterator(codes); + while (iter.hasNext()) { + String opCode = iter.next2CharAsString(); + if (opCode.equals(new_object)) { + NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile,opCode); + newObjectCmd.setOprand1(iter.next2CharAsInt()); + newObjectCmd.setOprand2(iter.next2CharAsInt()); + cmds.add(newObjectCmd); + } else if (opCode.equals(dup)||opCode.equals(astore_1)||opCode.equals(aload_0)||opCode.equals(aload_1)||opCode.equals(aload_2)||opCode.equals(voidreturn)) { + NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, opCode); + cmds.add(noOperandCmd); + + }else if (opCode.equals(ldc)){ + LdcCmd cmd = new LdcCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + }else if (opCode.equals(bipush)){ + BiPushCmd cmd = new BiPushCmd(clzFile, opCode); + cmd.setOperand(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equals(invokespecial)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if (opCode.equals(invokevirtual)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + }else{ + throw new RuntimeException(opCode + "未进行判断!"); + } + } + + calcuateOffset(cmds); + ByteCodeCommand[] cmd = (ByteCodeCommand[])cmds.toArray(); + return cmd; + } + + 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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.UTF8Info; + + +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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; + + +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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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 = (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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/StringInfo.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/field/Field.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..dc4dfff971 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,44 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 static Field parse(ConstantPool pool,ByteCodeIterator iter){ + int accessflag = iter.nextU2ToInt(); + int nameindex = iter.nextU2ToInt(); + int descriptorindex = iter.nextU2ToInt(); + int attributecount = iter.nextU2ToInt(); + if (attributecount > 0) { + throw new RuntimeException("该字段中有属性" + attributecount + "个,未进行解析"); + } + Field field = new Field(accessflag, nameindex, descriptorindex, pool); + return field; + + } + public String toString() { + return pool.getUTF8String(this.nameIndex)+":"+pool.getUTF8String(this.descriptorIndex); + } + +} diff --git a/group23/563253496/week6_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..40b792eda5 --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,65 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + public byte[] codes; + public int pos = 0; + + public 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; + } + + public boolean isNotEnd(){ + if(pos 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", 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/group23/563253496/week6_jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group23/563253496/week6_jvm/src/com/coderising/jvm/util/Util.java b/group23/563253496/week6_jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group23/563253496/week6_jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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 parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + return null; + } + +} diff --git a/group23/563253496/week6_stack/src/com/coderising/litestruts/StrutsTest.java b/group23/563253496/week6_stack/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..b8c81faf3c --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group23/563253496/week6_stack/src/com/coderising/litestruts/View.java b/group23/563253496/week6_stack/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coderising/litestruts/View.java @@ -0,0 +1,23 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/BinaryTreeNode.java b/group23/563253496/week6_stack/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..d7ac820192 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/BinaryTreeNode.java @@ -0,0 +1,32 @@ +package com.coding.basic; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/Iterator.java b/group23/563253496/week6_stack/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/Iterator.java @@ -0,0 +1,7 @@ +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/List.java b/group23/563253496/week6_stack/src/com/coding/basic/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/List.java @@ -0,0 +1,9 @@ +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/Queue.java b/group23/563253496/week6_stack/src/com/coding/basic/Queue.java new file mode 100644 index 0000000000..36e516e266 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/Queue.java @@ -0,0 +1,19 @@ +package com.coding.basic; + +public class Queue { + + public void enQueue(Object o){ + } + + public Object deQueue(){ + return null; + } + + public boolean isEmpty(){ + return false; + } + + public int size(){ + return -1; + } +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayList.java b/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..4576c016af --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,35 @@ +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + public void add(Object o){ + + } + public void add(int index, Object o){ + + } + + public Object get(int index){ + return null; + } + + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public Iterator iterator(){ + return null; + } + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayUtil.java b/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..45740e6d57 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,96 @@ +package com.coding.basic.array; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin){ + + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray){ + return null; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + return null; + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + return null; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + return null; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + return null; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + return null; + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator){ + return null; + } + + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrame.java b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..24b9d8b155 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,164 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + Node node = find(pageNum); + //在该队列中存在, 则提到队列头 + if (node != null) { + + moveExistingNodeToHead(node); + + } else{ + + node = new Node(); + node.pageNum = pageNum; + + // 缓存容器是否已经超过大小. + if (currentSize >= capacity) { + removeLast(); + + } + + addNewNodetoHead(node); + + + + + } + } + + private void addNewNodetoHead(Node node) { + + if(isEmpty()){ + + node.prev = null; + node.next = null; + first = node; + last = node; + + } else{ + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + this.currentSize ++; + } + + private Node find(int data){ + + Node node = first; + while(node != null){ + if(node.pageNum == data){ + return node; + } + node = node.next; + } + return null; + + } + + + + + + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize --; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + * + * @param node + */ + private void moveExistingNodeToHead(Node node) { + + if (node == first) { + + return; + } + else if(node == last){ + //当前节点是链表尾, 需要放到链表头 + Node prevNode = node.prev; + prevNode.next = null; + last.prev = null; + last = prevNode; + + } else{ + //node 在链表的中间, 把node 的前后节点连接起来 + Node prevNode = node.prev; + prevNode.next = node.next; + + Node nextNode = node.next; + nextNode.prev = prevNode; + + + } + + node.prev = null; + node.next = first; + first.prev = node; + first = node; + + } + private boolean isEmpty(){ + return (first == null) && (last == null); + } + + 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/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/linklist/LinkedList.java b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/linklist/LinkedList.java @@ -0,0 +1,125 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/stack/Stack.java b/group23/563253496/week6_stack/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..fff3778da5 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,64 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; +import java.util.ArrayList; + +/** + * Created by bdl19 on 2017/4/8. + */ +public class Stack { + private int count; + private ArrayList elementData; + + public Stack() { + this.count = 0; + elementData = new ArrayList(); + } + + public void push(Object o) { + count++; + elementData.add(o); + + } + + public Object pop() { + count--; + Object o = elementData.get(count); + elementData.remove(count); + return o; + } + + public Object peek() { + + return elementData.get(count-1); + } + + public boolean isEmpty() { + if (count == 0) { + return true; + } else { + return false; + } + } + + public int size() { + return count; + } + + public String toString(){ + StringBuilder sb = new StringBuilder(); + Stack s = new Stack(); + while(!this.isEmpty()){ + sb.append(this.peek().toString()); + sb.append(","); + s.push(this.pop()); + } + while(!s.isEmpty()){ + this.push(s.pop()); + } + +// sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } +} + diff --git a/group23/563253496/week6_stack/src/com/coding/basic/stack/StackUtil.java b/group23/563253496/week6_stack/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..70bd34e37f --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,136 @@ +package com.coding.basic.stack; +import java.util.Stack; +public class StackUtil { + + public static void bad_reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + Integer top = s.pop(); + reverse(s); + addToBottom(s,top); + + + } + public static void addToBottom(Stack s, Integer value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Integer top = s.pop(); + addToBottom(s,value); + s.push(top); + } + + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + + while(!s.isEmpty()){ + Object value = s.pop(); + if(!value.equals(o)){ + tmpStack.push(value); + } + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + + if(s == null || s.isEmpty() || s.size() stack = new Stack(); + for(int i=0;i s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExpr.java b/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..091c670ba8 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,112 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +import java.util.HashMap; + +public class InfixExpr { + String expr = null; + char[] chars; + Stack opStack; + Stack numStack; + private HashMap level = new HashMap<>(); + + int pos; + + public InfixExpr(String expr) { + this.expr = expr; + + + this.level.put('+', 0); + this.level.put('-', 0); + this.level.put('*', 1); + this.level.put('/', 1); + + + this.opStack = new Stack(); + this.numStack = new Stack(); + this.pos = 0; + } + + public float evaluate() { + chars = expr.toCharArray(); + while (this.pos < chars.length) { + if (isOp(chars[pos])) { + if (opStack.isEmpty()) { + opStack.push(chars[pos]); + pos++; + } else { + //TODO analyze + char op = (char) opStack.pop(); + if (level.get(chars[pos]) <= level.get(op)) { + + int c = this.caculate(op); + numStack.push(c); + opStack.push(chars[pos]); + pos++; + + + }else { + opStack.push(op); + opStack.push(chars[pos]); + pos++; + } + } + } else { + int num = this.getNumber(); + numStack.push(num); + + } + } + + while(!opStack.isEmpty()){ + char op = (char) opStack.pop(); + + int c = this.caculate(op); + numStack.push(c); + } + + return (int)numStack.pop(); + } + + private boolean isOp(char c) { + switch (c) { + case '+': + case '-': + case '*': + case '/': + return true; + + default: + return false; + } + } + + private int getNumber() { + int num = Integer.parseInt("" + chars[pos]); + pos++; + while ((pos < chars.length)&&(!isOp(chars[pos])) ) { + num *= 10; + num += Integer.parseInt("" + chars[pos]); + pos++; + } + return num; + } + + private int caculate(char c) { + int b = (int) numStack.pop(); + int a = (int) numStack.pop(); + switch (c) { + case '+': + return a + b; + case '-': + return a - b; + case '*': + return a * b; + case '/': + return a / b; + } + return -1; + } +} + diff --git a/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExprTest.java b/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20f52b4c63 --- /dev/null +++ b/group23/563253496/week6_stack/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..a57a8b5446 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,72 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.cmd.CommandParser; +import com.coderising.jvm.constant.ConstantPool; +import com.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){ + + return null; + } + + + 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 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){ + + return null; + } + + 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/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..14db5dca46 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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){ + + return null; + } + + + 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/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.attr; + + +import com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2a8dfb6123 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,102 @@ +package com.coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +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){ + + + return null; + } + public Method getMainMethod(){ + + return null; + } +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,128 @@ +package com.coderising.jvm.cmd; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/CommandParser.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,85 @@ +package com.coderising.jvm.cmd; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clz.ClassFile; + +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) { + + + return null; + } + + 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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.UTF8Info; + + +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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.MethodRefInfo; + + +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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.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 = (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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.cmd; + +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.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/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodRefInfo; + +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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,40 @@ +package com.coderising.jvm.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 static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,60 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,17 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + @Override + public void accept(Visitor visitor) { + + } + +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/StringInfo.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.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.visistUTF8(this); + + } + + + +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/field/Field.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.UTF8Info; +import com.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 desc = ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + return name +":"+ desc; + } + + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descIndex = iter.nextU2ToInt(); + int attribCount = iter.nextU2ToInt(); + //System.out.println("field attribute count:"+ attribCount); + + Field f = new Field(accessFlag, nameIndex, descIndex,pool); + + if(attribCount > 0){ + throw new RuntimeException("Field Attribute has not been implemented"); + } + + return f; + } + +} diff --git a/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,57 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; + +import com.coderising.jvm.util.Util; + +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/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +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", 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/group23/563253496/week7_jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group23/563253496/week7_jvm/src/com/coderising/jvm/util/Util.java b/group23/563253496/week7_jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group23/563253496/week7_jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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 parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + return null; + } + +} diff --git a/group23/563253496/week7_stack/src/com/coderising/litestruts/StrutsTest.java b/group23/563253496/week7_stack/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..b8c81faf3c --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group23/563253496/week7_stack/src/com/coderising/litestruts/View.java b/group23/563253496/week7_stack/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coderising/litestruts/View.java @@ -0,0 +1,23 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/BinaryTreeNode.java b/group23/563253496/week7_stack/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..d7ac820192 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/BinaryTreeNode.java @@ -0,0 +1,32 @@ +package com.coding.basic; + +public class BinaryTreeNode { + + private Object data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public Object getData() { + return data; + } + public void setData(Object data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/Iterator.java b/group23/563253496/week7_stack/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/Iterator.java @@ -0,0 +1,7 @@ +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/List.java b/group23/563253496/week7_stack/src/com/coding/basic/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/List.java @@ -0,0 +1,9 @@ +package com.coding.basic; + +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayList.java b/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..4576c016af --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,35 @@ +package com.coding.basic.array; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + public void add(Object o){ + + } + public void add(int index, Object o){ + + } + + public Object get(int index){ + return null; + } + + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public Iterator iterator(){ + return null; + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayUtil.java b/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..45740e6d57 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,96 @@ +package com.coding.basic.array; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * @param origin + * @return + */ + public void reverseArray(int[] origin){ + + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray){ + return null; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + return null; + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + return null; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * @param max + * @return + */ + public int[] fibonacci(int max){ + return null; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + return null; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + return null; + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator){ + return null; + } + + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrame.java b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..994a241a3d --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,57 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + + + } + + + 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/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/linklist/LinkedList.java b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/linklist/LinkedList.java @@ -0,0 +1,125 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + return -1; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/queue/CircleQueue.java b/group23/563253496/week7_stack/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..1ac659da3d --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,5 @@ +package com.coding.basic.queue; + +public class CircleQueue { + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/queue/Josephus.java b/group23/563253496/week7_stack/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..d629d847f4 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,19 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 知道最后一个人留下来 + * @author liuxin + * + */ +public class Josephus { + + public static List execute(int n, int m){ + + return null; + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/queue/JosephusTest.java b/group23/563253496/week7_stack/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/queue/Queue.java b/group23/563253496/week7_stack/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group23/563253496/week7_stack/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group23/563253496/week7_stack/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..bbd4715ca6 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,40 @@ +package com.coding.basic.queue; + +import java.util.Stack; + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + + + + public boolean isEmpty() { + return false; + } + + + + public int size() { + return -1; + } + + + + public void enQueue(E item) { + + } + + public E deQueue() { + return null; + } + + + } + diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/Stack.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..de597befb4 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,64 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; +import java.util.ArrayList; + +/** + * Created by bdl19 on 2017/4/8. + */ +public class Stack { + private int count; + private ArrayList elementData; + + public Stack() { + this.count = 0; + elementData = new ArrayList(); + } + + public void push(Object o) { + count++; + elementData.add(o); + + } + + public Object pop() { + count--; + Object o = elementData.get(count); + elementData.remove(count); + return o; + } + + public Object peek() { + + return elementData.get(count-1); + } + + public boolean isEmpty() { + if (count == 0) { + return true; + } else { + return false; + } + } + + public int size() { + return count; + } + + public String toString(){ + StringBuilder sb = new StringBuilder(); + Stack s = new Stack(); + while(!this.isEmpty()){ + sb.append(this.peek().toString()); + sb.append(","); + s.push(this.pop()); + } + while(!s.isEmpty()){ + this.push(s.pop()); + } + +// sb.deleteCharAt(sb.length()-1); + return sb.toString(); + } +} + diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/StackUtil.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..0148188b29 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,136 @@ +package com.coding.basic.stack; +import java.util.Stack; +public class StackUtil { + + public static void bad_reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + Integer top = s.pop(); + reverse(s); + addToBottom(s,top); + + + } + public static void addToBottom(Stack s, Integer value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Integer top = s.pop(); + addToBottom(s,value); + s.push(top); + } + + } + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + + while(!s.isEmpty()){ + Object value = s.pop(); + if(!value.equals(o)){ + tmpStack.push(value); + } + } + + while(!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + + if(s == null || s.isEmpty() || s.size() stack = new Stack(); + for(int i=0;i s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExpr.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..ef85ff007f --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,15 @@ +package com.coding.basic.stack.expr; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + return 0.0f; + } + + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExprTest.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20e34e8852 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,52 @@ +package com.coding.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixToPostfix.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..92c31a1085 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,110 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class InfixToPostfix { + private static List op = new ArrayList(); + + public static List convert(String expr) { + op.add('+'); + op.add('-'); + op.add('*'); + op.add('/'); + List numList = new LinkedList<>(); + List opList = new LinkedList<>(); + + List list = new ArrayList(); + + + char[] chars = expr.toCharArray(); + + int index = 0; + while (index < chars.length) { + if (op.contains(chars[index])) { + if (chars[index] == '*' || chars[index] == '/') { + + char oper = chars[index]; + + StringBuilder sb = new StringBuilder(); + index++; + while (chars[index] >= '0' && chars[index] <= '9') { + sb.append(chars[index]); + index++; + } + String s = numList.get(numList.size() - 1); + numList.remove(numList.size() - 1); + StringBuilder buffer = new StringBuilder(); + buffer.append(s + ' '); + buffer.append(sb); + buffer.append(oper); + numList.add(buffer.toString()); + //numStack.push(buffer.toString()); + + } else { + opList.add("" + chars[index]); + //opStack.push(chars[index]); + } + index++; + } else if (chars[index] == ' ') { + index++; + } else { + StringBuilder sb = new StringBuilder(); + while (chars[index] >= '0' && chars[index] <= '9') { + sb.append(chars[index]); + index++; + } + numList.add(sb.toString()); + //numStack.push(sb.toString()); + } + + } + + int opListIndex = 0; + while (opListIndex < opList.size()) { + for (int i = 0; i < opList.size(); i++) { + String a = numList.get(0); + String b = numList.get(1); + numList.set(0, a + " " + b + " " + opList.get(opListIndex)); + numList.remove(1); + } + } + + String postfixExpr = numList.get(0); + char[] chars1 = postfixExpr.toCharArray(); + index = 0; + while (index < chars1.length) { + if (chars1[index] == '+') { + Token token = new Token(1, "+"); + list.add(token); + } else if (chars1[index] == '-') { + Token token = new Token(1, "-"); + list.add(token); + } else if (chars1[index] == '*') { + Token token = new Token(1, "*"); + list.add(token); + } else if (chars1[index] == '/') { + Token token = new Token(1, "/"); + list.add(token); + }else if (chars1[index] == ' '){ + index++; + }else { + StringBuilder sb = new StringBuilder(); + while (chars1[index] >= '0' && chars1[index] <= '9') { + sb.append(chars1[index]); + index++; + } + Token token = new Token(2, sb.toString()); + list.add(token); + } + + } + + return list; + } + + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExpr.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..8400bef4f8 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,95 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { + String expr = null; + int count; + ArrayList operator = new ArrayList(); + Stack numStack = new Stack(); + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + operator.add('+'); + operator.add('-'); + operator.add('*'); + operator.add('/'); + this.count = 0; + char[] exprs = this.expr.toCharArray(); + + + + while (count < exprs.length) { + if (operator.contains(exprs[count])) { + switch (exprs[count]) { + case '+': + add(); + break; + case '-': + subtract(); + break; + case '*': + multiply(); + break; + case '/': + divide(); + break; + + } + this.count++; + } else if (exprs[count] == ' ') { + this.count++; + } else { + int num = getNum(exprs); + numStack.push(num); + } + + } + int result = (int)numStack.pop(); + return result; + } + + private int getNum(char[] exprs) { + + int num = exprs[count]-'0'; + this.count++; + + while (exprs[count] >= '0' && exprs[count] <= '9') { + + num *= 10; + num += exprs[count]-'0'; + this.count++; + } + return num; + } + + private void add() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(a + b); + } + + private void subtract() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(b - a); + } + + private void multiply() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(b * a); + } + + private void divide() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(b / a); + } + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExprTest.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,41 @@ +package com.coding.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/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExpr.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..7a2c0379a1 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,98 @@ +package com.coding.basic.stack.expr; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + int index; + ArrayList operator = new ArrayList(); + Stack numStack = new Stack(); + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + operator.add('+'); + operator.add('-'); + operator.add('*'); + operator.add('/'); + char[] exprs = this.expr.toCharArray(); + this.index = exprs.length - 1; + + while (index >= 0) { + if (operator.contains(exprs[index])) { + switch (exprs[index]) { + case '+': + add(); + break; + case '-': + subtract(); + break; + case '*': + multiply(); + break; + case '/': + divide(); + break; + + } + this.index--; + } else if (exprs[index] == ' ') { + this.index--; + } else { + int num = getNum(exprs); + numStack.push(num); + } + + } + int result = (int) numStack.pop(); + return result; + + } + + private int getNum(char[] exprs) { + + int num = exprs[index] - '0'; + this.index--; + int i = 10; + while (exprs[index] >= '0' && exprs[index] <= '9') { + + int temp = exprs[index] - '0'; + temp *= i; + num += temp; + i *= 10; + this.index--; + } + return num; + } + + private void add() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(a + b); + } + + private void subtract() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(a - b); + } + + private void multiply() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(b * a); + } + + private void divide() { + int a = (int) numStack.pop(); + int b = (int) numStack.pop(); + numStack.push(a / b); + } + + +} diff --git a/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExprTest.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.coding.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/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/Token.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,50 @@ +package com.coding.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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParser.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d3b0f167e1 --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,57 @@ +package com.coding.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/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParserTest.java b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/group23/563253496/week7_stack/src/com/coding/basic/stack/expr/TokenParserTest.java @@ -0,0 +1,41 @@ +package com.coding.basic.stack.expr; + +import static org.junit.Assert.*; + +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"); + + 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/group23/563253496/week8_datastructure/src/CircleQueue.java b/group23/563253496/week8_datastructure/src/CircleQueue.java new file mode 100644 index 0000000000..f69e5e6c5b --- /dev/null +++ b/group23/563253496/week8_datastructure/src/CircleQueue.java @@ -0,0 +1,53 @@ +/** + * Created by bdl19 on 2017/4/25. + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return this.front == this.rear; + } + + public int size() { + int size = this.rear - this.front; + return size < 0 ? size += DEFAULT_SIZE : size; + + } + + + public void enQueue(E data) { + if (this.isFull()) { + System.out.println("队列已满"); + return; + } + elementData[this.rear] = data; + this.rear = ++this.rear % DEFAULT_SIZE; + } + + + public E deQueue() { + if (this.isEmpty()) { + System.out.println("队列为空"); + return null; + } + E ele; + ele = (E) elementData[this.front]; + this.front = (++this.front) % DEFAULT_SIZE; + return ele; + } + + public boolean isFull() { + if ((this.rear + 1) % DEFAULT_SIZE == this.front) { + return true; + } else return false; + } +} \ No newline at end of file diff --git a/group23/563253496/week8_datastructure/src/Josephus.java b/group23/563253496/week8_datastructure/src/Josephus.java new file mode 100644 index 0000000000..3d1425e125 --- /dev/null +++ b/group23/563253496/week8_datastructure/src/Josephus.java @@ -0,0 +1,47 @@ +/** + * Created by bdl19 on 2017/4/25. + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, + * N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * "[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2) + * + * @author liuxin + */ +public class Josephus { + + public static List execute(int n, int m) { + List result = new ArrayList<>(); + + List list = new LinkedList(); + int interval = m - 1; + + for (int i = 0; i < n; i++) { + list.add(i); + } + int index = 0; + while (list.size() > 0) { + /*for (int i = 0; i < m; i++) { + index = (++index) % list.size(); + + }*/ + index += interval; + index %= list.size(); + result.add(list.get(index)); + list.remove(index); + + } + + + return result; + } + +} \ No newline at end of file diff --git a/group23/563253496/week8_datastructure/src/JosephusTest.java b/group23/563253496/week8_datastructure/src/JosephusTest.java new file mode 100644 index 0000000000..fb38138a32 --- /dev/null +++ b/group23/563253496/week8_datastructure/src/JosephusTest.java @@ -0,0 +1,28 @@ +/** + * Created by bdl19 on 2017/4/25. + */ +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} \ No newline at end of file diff --git a/group23/563253496/week8_datastructure/src/Queue.java b/group23/563253496/week8_datastructure/src/Queue.java new file mode 100644 index 0000000000..e2f5ce9a41 --- /dev/null +++ b/group23/563253496/week8_datastructure/src/Queue.java @@ -0,0 +1,62 @@ +/** + * Created by bdl19 on 2017/4/25. + */ +import java.util.NoSuchElementException; + +public class Queue { + 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; + } + +} \ No newline at end of file diff --git a/group23/563253496/week8_datastructure/src/QueueWithTwoStacks.java b/group23/563253496/week8_datastructure/src/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c960f09bbb --- /dev/null +++ b/group23/563253496/week8_datastructure/src/QueueWithTwoStacks.java @@ -0,0 +1,60 @@ +/** + * Created by bdl19 on 2017/4/25. + */ +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(); + } + + + + public int size() { + return stack1.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + E ele ; + if (stack1.size() == 0) { + throw new RuntimeException("队列为空!"); + } + while (stack1.size() > 1) { + stack2.push(stack1.pop()); + } + ele = stack1.pop(); + while(!stack2.isEmpty()){ + stack1.push(stack2.pop()); + } + + return ele; + } + + + +} \ No newline at end of file diff --git a/group23/563253496/week9_datastructure/src/QuickMinStack.java b/group23/563253496/week9_datastructure/src/QuickMinStack.java new file mode 100644 index 0000000000..3b135521a0 --- /dev/null +++ b/group23/563253496/week9_datastructure/src/QuickMinStack.java @@ -0,0 +1,40 @@ +//package com.coding.basic.stack; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * + * @author liuxin + */ +public class QuickMinStack { + LinkedList list = new LinkedList(); + LinkedList temp = new LinkedList<>(); + int min = Integer.MAX_VALUE; + + public void push(int data) { + if (data < min) { + min = data; + } + list.add(data); + } + + public int pop() { + int num = list.remove(list.size() - 1); + if (num == min) { + for (int tmp : list) { + temp.add(tmp); + } + } + Collections.sort(temp); + min = temp.get(0); + return list.remove(list.size() - 1); + } + + public int findMin() { + return min; + } +} \ No newline at end of file diff --git a/group23/563253496/week9_datastructure/src/StackWithTwoQueues.java b/group23/563253496/week9_datastructure/src/StackWithTwoQueues.java new file mode 100644 index 0000000000..238f5cff0f --- /dev/null +++ b/group23/563253496/week9_datastructure/src/StackWithTwoQueues.java @@ -0,0 +1,53 @@ +/** + * Created by bdl19 on 2017/5/6. + */ + +import java.util.*; + + +public class StackWithTwoQueues { + + private Queue queue1 = new LinkedList(); + private Queue queue2 = new LinkedList(); + + public void push(int data) { + if(queue2.isEmpty()){ + queue1.add(data); + }else{ + queue2.add(data); + } + } + + public int pop() { + if (queue1.size() == 0 && queue2.size() == 0) { + throw new IndexOutOfBoundsException(); + } + + + + if(queue2.isEmpty()){ + while(!(queue1.size()==1)){ + queue2.add(queue1.remove()); + } + return queue1.remove(); + + }else{ + while(!(queue2.size()==1)){ + queue1.add(queue2.remove()); + } + return queue2.remove(); + } + + + } + + public static void main(String[] args) { + StackWithTwoQueues s = new StackWithTwoQueues(); + s.push(1); + s.push(2); + s.push(3); + for (int i = 0; i < 3; i++) { + System.out.println(s.pop()); + } + } +} \ No newline at end of file diff --git a/group23/563253496/week9_datastructure/src/TwoStackInOneArray.java b/group23/563253496/week9_datastructure/src/TwoStackInOneArray.java new file mode 100644 index 0000000000..28bc0a30af --- /dev/null +++ b/group23/563253496/week9_datastructure/src/TwoStackInOneArray.java @@ -0,0 +1,100 @@ +/** + * Created by bdl19 on 2017/5/6. + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2 = data.length - 1; + + private boolean isFull() { + if (index1 == index2) { + return true; + } else return false; + } + + private void extendCapacity() { + Object[] temp = new Object[data.length + data.length / 2]; + for (int i = 0; i <= index1; i++) { + temp[i] = data[i]; + } + int indext = data.length - 1; + for (int i = temp.length - 1; i >= data.length - index2; i--) { + temp[i] = indext; + indext--; + } + index2 = temp.length - (temp.length - index1); + this.data = temp; + } + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + if (this.isFull()) { + extendCapacity(); + } + data[index1] = o; + index1++; + + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + index1--; + Object o = data[index1]; + data[index1] = null; + return o; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return data[index1 - 1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + if (this.isFull()) { + extendCapacity(); + } + data[index2] = o; + index2--; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + + Object o = data[++index2]; + data[index2] = null; + return o; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + + return data[index2 + 1]; + } + +} \ No newline at end of file diff --git a/group23/565832157/src/com/coderising/litestruts/struts.xml b/group23/565832157/src/com/coderising/litestruts/struts.xml deleted file mode 100644 index e5d9aebba8..0000000000 --- a/group23/565832157/src/com/coderising/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/565832157/src/com/coding/basic/LinkedList.java b/group23/565832157/src/com/coding/basic/LinkedList.java index 7d037a6428..77657e57c1 100644 --- a/group23/565832157/src/com/coding/basic/LinkedList.java +++ b/group23/565832157/src/com/coding/basic/LinkedList.java @@ -1,144 +1,144 @@ <<<<<<< HEAD:liuxin/src/com/coding/basic/LinkedList.java -package com.coding.basic; - -public class LinkedList implements List { - private int size; - - private Node head; - - public void add(Object o){ - - } - public void add(int index , Object o){ - - } - public Object get(int index){ - return null; - } - public Object remove(int index){ - return null; - } - - public int size(){ - - return size; - } - - public void addFirst(Object o){ - - } - public void addLast(Object o){ - - } - public Object removeFirst(){ - return null; - } - public Object removeLast(){ - return null; - } - public Iterator iterator(){ - return null; - } - - - private static class Node{ - Object data; - Node next; - } - - /** - * 把该链表逆置 - * head head - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - /** - * 长度超过1的单链表需要逆转 - */ - if(size>1){ - Node pre = head; - Node cur = head.next; - Node next = null; - while(cur!=null){ - next = cur.next; - cur.next = pre; - pre = cur; - cur = next; - } - - } - } - - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - - } - - /** - * 从第i个元素开始,删除length个元素 ,注意i从0开始 - * @param i - * @param length - */ - public void remove(int i, int length){ - - } - /** - * 假定当前链表和listB均包含已升序排列的整数 - * 从当前链表中取出那些listB所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public int[] getElements(LinkedList list){ - return null; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在listB中出现的元素 - - * @param list - */ - - public void subtract(LinkedList list){ - - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max){ - - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList intersection(LinkedList list){ - - return null; - } -} +package com.coding.basic; + +public class LinkedList implements List { + private int size; + + private Node head; + + public void add(Object o){ + + } + public void add(int index , Object o){ + + } + public Object get(int index){ + return null; + } + public Object remove(int index){ + return null; + } + + public int size(){ + + return size; + } + + public void addFirst(Object o){ + + } + public void addLast(Object o){ + + } + public Object removeFirst(){ + return null; + } + public Object removeLast(){ + return null; + } + public Iterator iterator(){ + return null; + } + + + private static class Node{ + Object data; + Node next; + } + + /** + * 把该链表逆置 + * head head + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + /** + * 长度超过1的单链表需要逆转 + */ + if(size>1){ + Node pre = head; + Node cur = head.next; + Node next = null; + while(cur!=null){ + next = cur.next; + cur.next = pre; + pre = cur; + cur = next; + } + + } + } + + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + + } + + /** + * 从第i个元素开始,删除length个元素 ,注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + return null; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection(LinkedList list){ + + return null; + } +} ======= package com.coding.basic; diff --git a/group23/601689050/.gitattributes b/group23/601689050/.gitattributes new file mode 100644 index 0000000000..bdb0cabc87 --- /dev/null +++ b/group23/601689050/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/group23/601689050/ArrayList.java b/group23/601689050/1List&BinaryTreeNode/ArrayList.java similarity index 100% rename from group23/601689050/ArrayList.java rename to group23/601689050/1List&BinaryTreeNode/ArrayList.java diff --git a/group23/601689050/BinaryTreeNode.java b/group23/601689050/1List&BinaryTreeNode/BinaryTreeNode.java similarity index 100% rename from group23/601689050/BinaryTreeNode.java rename to group23/601689050/1List&BinaryTreeNode/BinaryTreeNode.java diff --git a/group23/601689050/1List&BinaryTreeNode/Iterator.java b/group23/601689050/1List&BinaryTreeNode/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/group23/601689050/1List&BinaryTreeNode/Iterator.java @@ -0,0 +1,7 @@ +package com.coding.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group23/601689050/LinkedList.java b/group23/601689050/1List&BinaryTreeNode/LinkedList.java similarity index 100% rename from group23/601689050/LinkedList.java rename to group23/601689050/1List&BinaryTreeNode/LinkedList.java diff --git a/group23/601689050/List.java b/group23/601689050/1List&BinaryTreeNode/List.java similarity index 100% rename from group23/601689050/List.java rename to group23/601689050/1List&BinaryTreeNode/List.java diff --git a/group23/601689050/Queue.java b/group23/601689050/1List&BinaryTreeNode/Queue.java similarity index 100% rename from group23/601689050/Queue.java rename to group23/601689050/1List&BinaryTreeNode/Queue.java diff --git a/group23/601689050/Stack.java b/group23/601689050/1List&BinaryTreeNode/Stack.java similarity index 100% rename from group23/601689050/Stack.java rename to group23/601689050/1List&BinaryTreeNode/Stack.java diff --git a/group23/601689050/4weekLRU&JVM/JVM/loader/ClassFileLoader.java b/group23/601689050/4weekLRU&JVM/JVM/loader/ClassFileLoader.java new file mode 100644 index 0000000000..3c6244ff90 --- /dev/null +++ b/group23/601689050/4weekLRU&JVM/JVM/loader/ClassFileLoader.java @@ -0,0 +1,65 @@ +package loader; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +/** + * Created by Lxx on 2017/4/23. + */ +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,";"); + } + + +} diff --git a/group23/601689050/4weekLRU&JVM/JVM/test/loader/ClassFileLoaderTest.java b/group23/601689050/4weekLRU&JVM/JVM/test/loader/ClassFileLoaderTest.java new file mode 100644 index 0000000000..8e4e172f25 --- /dev/null +++ b/group23/601689050/4weekLRU&JVM/JVM/test/loader/ClassFileLoaderTest.java @@ -0,0 +1,86 @@ +package test.loader; + +import loader.ClassFileLoader; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ClassFileLoaderTest { + static String path1 = "D:\\JavaProject\\4week_minijvm\\out\\production\\4week_minijvm"; + static String path2 = "D:\\temp"; + + + + @Before +public void before() throws Exception { +} + +@After +public void after() throws Exception { +} + +/** +* +* Method: readBinaryCode(String className) +* +*/ +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 = "test.loader.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "test.loader.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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 capacity) { + last = last.prev; + last.next = null; + } + } else { + moveToFirst(iteratorNode); + } + } + } + + } + + private void moveLastToFirst() { + last.next = first; + first.prev = last; + first = last; + last = last.prev; + last.next = null; + first.prev = null; + } + private void moveToFirst(Node iteratorNode){ + iteratorNode.prev.next = iteratorNode.next; + iteratorNode.next.prev = iteratorNode.prev; + iteratorNode.prev = null; + iteratorNode.next = first; + first.prev = iteratorNode; + first = iteratorNode; + } + + private void addToFirst(int pageNum) { + Node node = new Node(); + node.pageNum = pageNum; + node.prev = null; + node.next = first; + first.prev = node; + first = node; + size++; + } + + + 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/group23/601689050/4weekLRU&JVM/LRU/LRUPageFrameTest.java b/group23/601689050/4weekLRU&JVM/LRU/LRUPageFrameTest.java new file mode 100644 index 0000000000..a7dd99ec58 --- /dev/null +++ b/group23/601689050/4weekLRU&JVM/LRU/LRUPageFrameTest.java @@ -0,0 +1,29 @@ +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + } + +} diff --git a/group23/601689050/4weekLRU&JVM/LRU/LinkedList.java b/group23/601689050/4weekLRU&JVM/LRU/LinkedList.java new file mode 100644 index 0000000000..4a71816e5d --- /dev/null +++ b/group23/601689050/4weekLRU&JVM/LRU/LinkedList.java @@ -0,0 +1,313 @@ +import java.util.Objects; +import java.util.Stack; + +public class LinkedList implements List { + + private Node head; + private Node rear; + public boolean isEmpty(){ + return true; + } + + public void add(Object o){ + if(isEmpty()) + addFirst(o); + else + addLast(o); + } + public void add(int index , Object o){ + if(index<0 || o ==null){ + throw new IllegalArgumentException("不合法"); + } else if (index == 0 && head == null){ + addFirst(o); + }else if(index>0 && head == null){ + throw new IllegalArgumentException("不合法"); + }else{ + Node srcNode = (Node) this.get(index); + Node newNode = new Node(); + newNode.data = o; + newNode.next = srcNode.next; + srcNode.next.previous = newNode; + srcNode.next = newNode; + newNode.previous = srcNode; + } + } + public Object get(int index){ + Node newNode = new Node(); + for(int i = 0;i7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node p1,p2 = null; + p1 = head; + while (head.next != null){ + p2 = head.next; + head.next = p2.next; + p2.next = p1; + p1 = p2; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int size = this.size(); + Node newNode = new Node(); + newNode = head; + if(size%2 == 0){ + int length = size/2; + for(int i = 0;i101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + int[] listB = new int[list.size()-1]; + int[] listA = new int[list.size()-1]; + int size = list.size(); + for(int i=0;i min && (int)newNode.data min && (int)newNode.data > max){ + break; + } + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + LinkedList listA = this; + LinkedList listB = list; + LinkedList listC = new LinkedList(); + if(listA == null){ + return list; + } + if(listB == null){ + return this; + } + Node p1 = listA.head; + Node p2 = listB.head; + Node p3 = listC.head; + while(p1 != null && p2 !=null) { + if ((int) p1.data <= (int) p2.data) { + p3.next = p1; + p1 = p1.next; + } else { + p3.next = p2; + p2 = p2.next; + } + p3 = p3.next; + } + if(p1 == null){ + p3.next = p2; + } + if(p2 == null){ + p3.next = p1; + } + return listC; + } +} diff --git a/group23/601689050/4weekLRU&JVM/LRU/List.java b/group23/601689050/4weekLRU&JVM/LRU/List.java new file mode 100644 index 0000000000..4f7bcc71a8 --- /dev/null +++ b/group23/601689050/4weekLRU&JVM/LRU/List.java @@ -0,0 +1,7 @@ +public interface List { + public void add(Object o); + public void add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); +} diff --git a/group23/601689050/5weekStack/stack/Stack.java b/group23/601689050/5weekStack/stack/Stack.java new file mode 100644 index 0000000000..7b394d9f30 --- /dev/null +++ b/group23/601689050/5weekStack/stack/Stack.java @@ -0,0 +1,70 @@ +package stack; + +import java.util.ArrayList; +import java.util.EmptyStackException; + +/** + * Created by Lxx on 2017/4/23. + */ +public class Stack { + + private ArrayList array; + private int count; + + + public Stack() { + array = new ArrayList(); + } + + public void push(Object o) { + count++; + array.add(o); + + } + + public Object pop() { + count--; + Object o = array.get(count); + array.remove(count); + + return o; + } + + public Object peek() { + + if(count == 0){ + throw new EmptyStackException(); + } + return array.get(array.size()-1); + } + + public boolean isEmpty() { + return array.size() == 0; + } + + public int size() { + + return count; + } + + public String toString(){ + + StringBuilder string = new StringBuilder(); + Stack s = new Stack(); + int size = this.size(); + for(int i = 0; i < size; i++){ + string.append(this.peek().toString()); + if(i < size-1 ) + string.append(","); + s.push(this.pop()); + } + + while(!s.isEmpty()){ + this.push(s.pop()); + } + + return string.toString(); + } + + +} diff --git a/group23/601689050/5weekStack/stack/StackUtil.java b/group23/601689050/5weekStack/stack/StackUtil.java new file mode 100644 index 0000000000..00920cdb08 --- /dev/null +++ b/group23/601689050/5weekStack/stack/StackUtil.java @@ -0,0 +1,133 @@ +package stack; + +/** + * Created by Lxx on 2017/4/23. + */ +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + if(s == null || s.isEmpty()){ + return; + } + + Stack tmp = new Stack(); + while(!s.isEmpty()){ + tmp.push(s.pop()); + } + while(!tmp.isEmpty()){ + Integer top = (Integer) tmp.pop(); + addToBottom(s,top); + } + + + } + public static void addToBottom(Stack s, Integer value){ + if(s.isEmpty()){ + s.push(value); + } else{ + Integer top = (Integer) s.pop(); + addToBottom(s,value); + s.push(top); + } + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + + if(s == null || s.isEmpty()){ + return; + } + Stack tmpStack = new Stack(); + Stack s1 = new Stack(); + while(!s.isEmpty()){ + Object value = s.pop(); + if(!value.equals(o)){ + tmpStack.push(value); + } + } + + while(!tmpStack.isEmpty()){ + s1.push(tmpStack.pop()); + } + while(!s1.isEmpty()){ + s.push(s1.pop()); + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + + if(s == null || s.isEmpty() || s.size() < len || len <= 0){ + return null; + } + Stack tmpStack = new Stack(); + int i = 0; + Object[] topElement = new Object[len]; + while(!s.isEmpty()){ + Object top = s.pop(); + tmpStack.push(top); + topElement[i++] = top; + if(i == len){ + break; + } + } + while (!tmpStack.isEmpty()){ + s.push(tmpStack.pop()); + } + return topElement; + } + + + /** + * 字符串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 tmpStack = new Stack(); + for (int i = 0; i < s.length(); i++) { + char tmpChar = s.charAt(i); + if (tmpChar == '(' || tmpChar == '{' || tmpChar == '[') { + tmpStack.push(tmpChar); + } else if (tmpChar == ')') { + char compareChar = (char) tmpStack.pop(); + if (compareChar != '(') { + return false; + } + } else if (tmpChar == ']') { + char compareChar = (char) tmpStack.pop(); + if (compareChar != '[') { + return false; + } + } else if (tmpChar == '}') { + char compareChar = (char) tmpStack.pop(); + if (compareChar != '{') { + return false; + } + } + } + return tmpStack.size() == 0; + } +} diff --git a/group23/601689050/5weekStack/test/StackUtilTest.java b/group23/601689050/5weekStack/test/StackUtilTest.java new file mode 100644 index 0000000000..413d9f3c4e --- /dev/null +++ b/group23/601689050/5weekStack/test/StackUtilTest.java @@ -0,0 +1,69 @@ +package test; +import stack.*; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import stack.StackUtil; + +/** + * Created by Lxx on 2017/4/23. + */ +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("5,4,3,2,1", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("1,2,3,4,5", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("1,3", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + } + + @Test + public void testIsValidPairs() { + + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group23/601689050/6weekInfixExpr/InfixExpr.java b/group23/601689050/6weekInfixExpr/InfixExpr.java new file mode 100644 index 0000000000..7b833931b3 --- /dev/null +++ b/group23/601689050/6weekInfixExpr/InfixExpr.java @@ -0,0 +1,61 @@ +import java.util.*; +import java.util.Stack; + +/** + * Created by Lxx on 2017/4/28. + */ +public class InfixExpr { + String expr = null; + public InfixExpr(String expr){ + this.expr = expr; + } + public float evaluate(){ + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack opStack = new Stack<>(); + Stack numStack = new Stack(); + for(Token token : tokens){ + if(token.isOpretor()){ + if(opStack.isEmpty()){ + opStack.push(token); + }else { + while(!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(),f1,f2); + numStack.push(result); + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + while (!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(),f1,f2)); + } + return numStack.pop().floatValue(); + + } + + private Float calculate(String op, float f1, float f2) { + if(op.equals("+")){ + return f1 + f2; + } + if(op.equals("-")){ + return f1 - f2; + } + if(op.equals("*")){ + return f1 * f2; + } + if(op.equals("/")){ + return f1 / f2; + } + return null; + } +} diff --git a/group23/601689050/6weekInfixExpr/InfixExprTest.java b/group23/601689050/6weekInfixExpr/InfixExprTest.java new file mode 100644 index 0000000000..bf2f8e91a9 --- /dev/null +++ b/group23/601689050/6weekInfixExpr/InfixExprTest.java @@ -0,0 +1,50 @@ +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Lxx on 2017/4/28. + */ +public class InfixExprTest { + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + + } +} diff --git a/group23/601689050/6weekInfixExpr/Stack.java b/group23/601689050/6weekInfixExpr/Stack.java new file mode 100644 index 0000000000..8a15be4366 --- /dev/null +++ b/group23/601689050/6weekInfixExpr/Stack.java @@ -0,0 +1,50 @@ +import java.util.ArrayList; +import java.util.EmptyStackException; + +/** + * Created by Lxx on 2017/4/28. + */ +public class Stack { + public ArrayList array; + public int count; + public Stack(){ + array = new ArrayList(); + } + public void push (Object o){ + count ++ ; + array.add(o); + } + public Object pop(){ + count -- ; + Object o = array.get(count); + array.remove(o); + return o; + } + public Object peek(){ + if(count == 0){ + throw new EmptyStackException(); + } + return array.get(array.size()-1); + } + public boolean isEmpty(){ + return array.size() == 0; + } + public int size(){ + return count; + } + public String toString(){ + StringBuilder string = new StringBuilder(); + Stack s = new Stack(); + int size = this.size(); + for(int i = 0;i OPERATORS = Arrays.asList("+","-","*","/"); + public 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 isOpretor(){ + return type == OPERATOR; + } + public int getIntValue(){ + return Integer.valueOf(value).intValue(); + } + public String toString(){ + return value; + } + public boolean hasHigherPriority(Token t){ + if (!this.isOpretor() && !t.isOpretor()){ + throw new RuntimeException(); + } + return priorities.get(this.value) - priorities.get(t.value) > 0; + } +} diff --git a/group23/601689050/6weekInfixExpr/TokenParser.java b/group23/601689050/6weekInfixExpr/TokenParser.java new file mode 100644 index 0000000000..3e966cc0a3 --- /dev/null +++ b/group23/601689050/6weekInfixExpr/TokenParser.java @@ -0,0 +1,47 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Lxx on 2017/4/28. + */ +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("输入值不符合要求"); + 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/group23/601689050/7weekExpr2/InfixExpr.java b/group23/601689050/7weekExpr2/InfixExpr.java new file mode 100644 index 0000000000..77c310465e --- /dev/null +++ b/group23/601689050/7weekExpr2/InfixExpr.java @@ -0,0 +1,61 @@ +import java.util.List; +import java.util.Stack; + +/** + * Created by Lxx on 2017/4/29. + */ +public class InfixExpr { + String expr = null; + public InfixExpr(String expr){ + this.expr = expr; + } + public float evaluate(){ + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack opStack = new Stack<>(); + Stack numStack = new Stack(); + for(Token token : tokens){ + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + }else { + while(!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())){ + Token prevOperator = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + Float result = calculate(prevOperator.toString(),f1,f2); + numStack.push(result); + } + opStack.push(token); + } + } + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + } + while (!opStack.isEmpty()){ + Token token = opStack.pop(); + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(),f1,f2)); + } + return numStack.pop().floatValue(); + + } + + private Float calculate(String op, float f1, float f2) { + if(op.equals("+")){ + return f1 + f2; + } + if(op.equals("-")){ + return f1 - f2; + } + if(op.equals("*")){ + return f1 * f2; + } + if(op.equals("/")){ + return f1 / f2; + } + return null; + } +} diff --git a/group23/601689050/7weekExpr2/InfixToPostfix.java b/group23/601689050/7weekExpr2/InfixToPostfix.java new file mode 100644 index 0000000000..7833ebf8f7 --- /dev/null +++ b/group23/601689050/7weekExpr2/InfixToPostfix.java @@ -0,0 +1,35 @@ +import java.util.*; +import java.util.Stack; + +/** + * Created by Lxx on 2017/4/29. + */ +public class InfixToPostfix { + + String expr = null; + public InfixToPostfix(String expr){ + this.expr = expr; + } + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack opStack = new Stack<>(); + Stack allStack = new Stack<>(); + public Stack change(){ + for(Token token : tokens){ + if(token.isOperator()){ + if(opStack.isEmpty()){ + opStack.push(token); + }else{ + while(!opStack.isEmpty() && !token.hasHigherPriority(opStack.peek())){ + Token preOperator = opStack.pop(); + allStack.push(preOperator.toString()); + } + } + } + if (token.isNumber()){ + allStack.push(token.toString()); + } + } + return allStack; + } +} diff --git a/group23/601689050/7weekExpr2/PostfixExpr.java b/group23/601689050/7weekExpr2/PostfixExpr.java new file mode 100644 index 0000000000..5c128db330 --- /dev/null +++ b/group23/601689050/7weekExpr2/PostfixExpr.java @@ -0,0 +1,45 @@ +import java.util.*; +import java.util.Stack; + +/** + * Created by Lxx on 2017/4/29. + */ +public class PostfixExpr { + String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack numStack = new Stack<>(); + for(Token token : tokens){ + if(token.isNumber()){ + numStack.push(new Float(token.getIntValue())); + } + if(token.isOperator()){ + Float f2 = numStack.pop(); + Float f1 = numStack.pop(); + numStack.push(calculate(token.toString(),f1,f2)); + } + } + return numStack.pop().floatValue(); + } + private Float calculate(String op, float f1, float f2){ + if(op.equals("+")){ + return f1 + f2; + } + if(op.equals("-")){ + return f1 - f2; + } + if(op.equals("*")){ + return f1 * f2; + } + if (op.equals("/")){ + return f1 / f2; + } + return null; + } +} diff --git a/group23/601689050/7weekExpr2/PostfixExprTest.java b/group23/601689050/7weekExpr2/PostfixExprTest.java new file mode 100644 index 0000000000..bad5b82bec --- /dev/null +++ b/group23/601689050/7weekExpr2/PostfixExprTest.java @@ -0,0 +1,37 @@ +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Lxx on 2017/4/29. + */ +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/group23/601689050/7weekExpr2/PrefixExpr.java b/group23/601689050/7weekExpr2/PrefixExpr.java new file mode 100644 index 0000000000..77652af742 --- /dev/null +++ b/group23/601689050/7weekExpr2/PrefixExpr.java @@ -0,0 +1,51 @@ +import java.util.*; +import java.util.Stack; + +/** + * Created by Lxx on 2017/4/29. + */ +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + TokenParser parser = new TokenParser(); + List tokens = parser.parse(this.expr); + Stack numStack = new Stack<>(); + Stack allStack = new Stack<>(); + for (Token token : tokens) { + allStack.push(token); + } + while (!allStack.isEmpty()) { + if (allStack.peek().isNumber()) { + numStack.push(new Float(allStack.pop().getIntValue())); + } + if (allStack.peek().isOperator()) { + Token token = allStack.pop(); + Float f1 = numStack.pop(); + Float f2 = numStack.pop(); + numStack.push(calculate(token.toString(), f1, f2)); + } + } + return numStack.pop().floatValue(); + } + + private Float calculate(String op, float f1, float f2){ + if(op.equals("+")){ + return f1 + f2; + } + if(op.equals("-")){ + return f1 - f2; + } + if(op.equals("*")){ + return f1 * f2; + } + if (op.equals("/")){ + return f1 / f2; + } + return null; + } +} diff --git a/group23/601689050/7weekExpr2/PrefixExprTest.java b/group23/601689050/7weekExpr2/PrefixExprTest.java new file mode 100644 index 0000000000..8d1074d5d3 --- /dev/null +++ b/group23/601689050/7weekExpr2/PrefixExprTest.java @@ -0,0 +1,42 @@ +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Lxx on 2017/4/29. + */ +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/group23/601689050/7weekExpr2/Stack.java b/group23/601689050/7weekExpr2/Stack.java new file mode 100644 index 0000000000..614ba2860c --- /dev/null +++ b/group23/601689050/7weekExpr2/Stack.java @@ -0,0 +1,50 @@ +import java.util.ArrayList; +import java.util.EmptyStackException; + +/** + * Created by Lxx on 2017/4/29. + */ +public class Stack { + public ArrayList array; + public int count; + public Stack(){ + array = new ArrayList(); + } + public void push (Object o){ + count ++ ; + array.add(o); + } + public Object pop(){ + count -- ; + Object o = array.get(count); + array.remove(o); + return o; + } + public Object peek(){ + if(count == 0){ + throw new EmptyStackException(); + } + return array.get(array.size()-1); + } + public boolean isEmpty(){ + return array.size() == 0; + } + public int size(){ + return count; + } + public String toString(){ + StringBuilder string = new StringBuilder(); + Stack s = new Stack(); + int size = this.size(); + for(int i = 0;i 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + 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; + } + +} diff --git a/group23/601689050/7weekExpr2/TokenParser.java b/group23/601689050/7weekExpr2/TokenParser.java new file mode 100644 index 0000000000..17716e0c08 --- /dev/null +++ b/group23/601689050/7weekExpr2/TokenParser.java @@ -0,0 +1,47 @@ +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Lxx on 2017/4/29. + */ +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("输入值不符合要求"); + 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/group23/601689050/8weekQueue/CircleQueue.java b/group23/601689050/8weekQueue/CircleQueue.java new file mode 100644 index 0000000000..7ca98467ec --- /dev/null +++ b/group23/601689050/8weekQueue/CircleQueue.java @@ -0,0 +1,44 @@ +/** + * Created by lxx on 2017/5/6. + */ +public class CircleQueue{ + + private int size; + private int first; + private int last; + Object[] queue; + + public CircleQueue(int size){ + queue = new Object[size]; + first = 0; + last = 0; + } + + public boolean isEmpty(){ + return first == last; + } + + public void enCircleQueue(Object o){ + if( (last+1) % size == first){ + System.out.println("Circle Queue is full"); + }else { + queue[last] = o; + last = (last+1) % queue.length; + } + } + + public int getSize(){ + return (last - first + queue.length) % queue.length; + } + + public Object deCircleQueue(){ + if(isEmpty()){ + return null; + }else{ + Object item = queue[first]; + first = (first+1)%queue.length; + return item; + } + + } +} diff --git a/group23/601689050/8weekQueue/Josephus.java b/group23/601689050/8weekQueue/Josephus.java new file mode 100644 index 0000000000..6e24811da3 --- /dev/null +++ b/group23/601689050/8weekQueue/Josephus.java @@ -0,0 +1,50 @@ + +/** + * Created by lxx on 2017/5/6. + */ + + + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * @author + * + */ +public class Josephus { + + private static class Node { + int data; + Node next; + + public Node(int i) { + data = i; + } + } + + public static void execute(int n, int m) { + + Node header = new Node(0); + Node pointer = header; + for (int i = 1; i < n; i++) { + pointer.next = new Node(i); + pointer = pointer.next; + } + pointer.next = header; + while (pointer != pointer.next) { + for (int i = 1; i <= m; i++) { + pointer = pointer.next; + } + System.out.println(pointer.next.data); + pointer.next = pointer.next.next; + } + System.out.println(pointer.next.data); + + } + public static void main(String args[]){ + Josephus circle = new Josephus(); + circle.execute(8,4); + } +} diff --git a/group23/601689050/8weekQueue/Queue.java b/group23/601689050/8weekQueue/Queue.java new file mode 100644 index 0000000000..bdfd22b16f --- /dev/null +++ b/group23/601689050/8weekQueue/Queue.java @@ -0,0 +1,55 @@ +import javax.xml.soap.Node; +import java.util.NoSuchElementException; + +/** + * Created by lxx on 2017/5/6. + */ +public class Queue { + + 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 is empty"); + }else{ + E item = first.item; + first = first.next; + size--; + if(isEmpty()){ + last = null; + } + return item; + } + } + + +} diff --git a/group23/601689050/8weekQueue/QueueWithTwoStacks.java b/group23/601689050/8weekQueue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c8976aca56 --- /dev/null +++ b/group23/601689050/8weekQueue/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +import java.util.Stack; + +/** + * Created by lxx on 2017/5/6. + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + public QueueWithTwoStacks(){ + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty(){ + return stack1.isEmpty() && stack2.isEmpty(); + } + + public int size() + { + return stack1.size() + stack2.size(); + } + + public void enQueue(E item){ + + stack1.push(item); + } + + public E deQueue(){ + if(stack2.isEmpty()){ + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + return stack2.pop(); + } + public static void main(String args[]){ + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + queue.enQueue(1); + queue.enQueue(5); + queue.enQueue(4); + queue.enQueue(0); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + } +} diff --git a/group23/601689050/9weekStack/QuickMinStack.java b/group23/601689050/9weekStack/QuickMinStack.java new file mode 100644 index 0000000000..4033461599 --- /dev/null +++ b/group23/601689050/9weekStack/QuickMinStack.java @@ -0,0 +1,50 @@ +/** + * Created by lxx on 2017/5/6. + */ + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack extends Stack { + + Stack sMin; + public QuickMinStack(){ + sMin = new Stack(); + } + public void push(int data){ + if(data <= findMin()){ + sMin.push(data); + } + super.push(data); + } + public Integer pop(){ + int value = super.pop(); + if(value == findMin()){ + sMin.pop(); + } + return value; + } + public int findMin(){ + if(sMin.isEmpty()){ + return Integer.MAX_VALUE; + } + return sMin.peek(); + } + + public static void main(String args[]){ + QuickMinStack stack = new QuickMinStack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(0); + System.out.println(stack.pop().intValue()); + System.out.println(stack.findMin()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + } +} diff --git a/group23/601689050/9weekStack/StackWithTwoQueues.java b/group23/601689050/9weekStack/StackWithTwoQueues.java new file mode 100644 index 0000000000..8eb1d996bf --- /dev/null +++ b/group23/601689050/9weekStack/StackWithTwoQueues.java @@ -0,0 +1,52 @@ +import java.util.LinkedList; + + +/** + * Created by lxx on 2017/5/6. + */ +public class StackWithTwoQueues { + + LinkedList queue1=new LinkedList(); + LinkedList queue2=new LinkedList(); + public void push(int data){ + queue1.addLast(data); + } + public int pop() { + if (sSize() > 0) { + if (!queue1.isEmpty()) { + while (queue1.size() > 1) { + queue2.addLast(queue1.removeFirst()); + } + return queue1.removeFirst(); + } else { + while (queue2.size() > 1) { + queue1.addLast(queue2.removeFirst()); + } + return queue2.removeFirst(); + } + } else { + System.out.println("栈空,不能出栈"); + return Integer.MAX_VALUE; + } + } + public int sSize(){ + return queue1.size() + queue2.size(); + } + public static void main(String[] args) + { + StackWithTwoQueues stack=new StackWithTwoQueues(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + stack.push(5); + stack.push(6); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + } +} diff --git a/group23/601689050/9weekStack/TwoStackInOneArray.java b/group23/601689050/9weekStack/TwoStackInOneArray.java new file mode 100644 index 0000000000..916e1dab3b --- /dev/null +++ b/group23/601689050/9weekStack/TwoStackInOneArray.java @@ -0,0 +1,81 @@ +import java.util.Stack; + +/** + * Created by lxx on 2017/5/6. + */ +public class TwoStackInOneArray { + + + + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2 = data.length - 1; + + + private boolean isFull() { + if (index1 == index2) { + return true; + } else + return false; + } + + private void extendCapacity() { + + } + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return null; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + return null; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + return null; + } + +} diff --git a/group23/609041842/.classpath b/group23/609041842/.classpath deleted file mode 100644 index 4449a3dae9..0000000000 --- a/group23/609041842/.classpath +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/group23/609041842/.gitignore b/group23/609041842/.gitignore deleted file mode 100644 index ae3c172604..0000000000 --- a/group23/609041842/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/group23/609041842/.project b/group23/609041842/.project deleted file mode 100644 index b2b4094e01..0000000000 --- a/group23/609041842/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - 609041842coding - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/group23/609041842/.settings/org.eclipse.jdt.ui.prefs b/group23/609041842/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index b6ec1a71fb..0000000000 --- a/group23/609041842/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,60 +0,0 @@ -eclipse.preferences.version=1 -editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true -sp_cleanup.add_default_serial_version_id=true -sp_cleanup.add_generated_serial_version_id=false -sp_cleanup.add_missing_annotations=true -sp_cleanup.add_missing_deprecated_annotations=true -sp_cleanup.add_missing_methods=false -sp_cleanup.add_missing_nls_tags=false -sp_cleanup.add_missing_override_annotations=true -sp_cleanup.add_missing_override_annotations_interface_methods=true -sp_cleanup.add_serial_version_id=false -sp_cleanup.always_use_blocks=true -sp_cleanup.always_use_parentheses_in_expressions=false -sp_cleanup.always_use_this_for_non_static_field_access=false -sp_cleanup.always_use_this_for_non_static_method_access=false -sp_cleanup.convert_functional_interfaces=false -sp_cleanup.convert_to_enhanced_for_loop=false -sp_cleanup.correct_indentation=false -sp_cleanup.format_source_code=true -sp_cleanup.format_source_code_changes_only=false -sp_cleanup.insert_inferred_type_arguments=false -sp_cleanup.make_local_variable_final=true -sp_cleanup.make_parameters_final=false -sp_cleanup.make_private_fields_final=true -sp_cleanup.make_type_abstract_if_missing_method=false -sp_cleanup.make_variable_declarations_final=false -sp_cleanup.never_use_blocks=false -sp_cleanup.never_use_parentheses_in_expressions=true -sp_cleanup.on_save_use_additional_actions=false -sp_cleanup.organize_imports=true -sp_cleanup.qualify_static_field_accesses_with_declaring_class=false -sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true -sp_cleanup.qualify_static_member_accesses_with_declaring_class=false -sp_cleanup.qualify_static_method_accesses_with_declaring_class=false -sp_cleanup.remove_private_constructors=true -sp_cleanup.remove_redundant_type_arguments=true -sp_cleanup.remove_trailing_whitespaces=false -sp_cleanup.remove_trailing_whitespaces_all=true -sp_cleanup.remove_trailing_whitespaces_ignore_empty=false -sp_cleanup.remove_unnecessary_casts=true -sp_cleanup.remove_unnecessary_nls_tags=false -sp_cleanup.remove_unused_imports=false -sp_cleanup.remove_unused_local_variables=false -sp_cleanup.remove_unused_private_fields=true -sp_cleanup.remove_unused_private_members=false -sp_cleanup.remove_unused_private_methods=true -sp_cleanup.remove_unused_private_types=true -sp_cleanup.sort_members=false -sp_cleanup.sort_members_all=false -sp_cleanup.use_anonymous_class_creation=false -sp_cleanup.use_blocks=false -sp_cleanup.use_blocks_only_for_return_and_throw=false -sp_cleanup.use_lambda=true -sp_cleanup.use_parentheses_in_expressions=false -sp_cleanup.use_this_for_non_static_field_access=false -sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true -sp_cleanup.use_this_for_non_static_method_access=false -sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true -sp_cleanup.use_type_arguments=false diff --git a/group23/609041842/src/code/ArrayList.java b/group23/609041842/src/code/ArrayList.java new file mode 100644 index 0000000000..8acbfe7de5 --- /dev/null +++ b/group23/609041842/src/code/ArrayList.java @@ -0,0 +1,49 @@ +package code; + +import java.util.Arrays; + +public class ArrayList { + + private Object[] obj = new Object[0]; + + public void add(Object o) { + Object[] tar = new Object[obj.length + 1]; + System.arraycopy(obj, 0, tar, 0, obj.length); + tar[tar.length - 1] = o; + obj = tar; + System.out.println(Arrays.toString(obj)); + } + + public void add(int index, Object o) { + Object[] tar = new Object[obj.length + 1]; + System.arraycopy(obj, 0, tar, 0, index); + tar[index] = o; + System.arraycopy(obj, index, tar, index + 1, obj.length - index); + obj = tar; + } + + public Object get(int index) { + return obj[index]; + } + + public int size(){ + return obj.length; + } + + public Object remove(int index){ + Object[] tar = new Object[obj.length-1]; + System.arraycopy(obj, 0, tar, 0, index); + System.arraycopy(obj, index+1, tar, index, obj.length-index-1); + Object o = obj[index]; + obj = tar; + return o;//رɾԪ + } + public static void main(String[] args) { + ArrayList al = new ArrayList(); + al.add("hello"); + al.add("java"); + al.add(2, "addm"); + System.out.println(al.remove(1)); + } + +} diff --git a/group23/609041842/src/code/LinkedList.java b/group23/609041842/src/code/LinkedList.java new file mode 100644 index 0000000000..e42138022e --- /dev/null +++ b/group23/609041842/src/code/LinkedList.java @@ -0,0 +1,87 @@ +package code; + +public class LinkedList { + private static Node head; + private Node last; + public int size; + + public void add(Object o) { + Node l = last; + Node newNode = new Node(l, o, null); + last = newNode; + if (head == null) { + head = newNode; + size = 1; + } else { + l.next = newNode; + size++; + } + } + + public void add(int index, Object o) { + Node n = node(index); + System.out.println(n.data); + Node pred = n.prev; + Node newNode = new Node(pred, o, n); + if (pred == null) { + head = newNode; + } else { + pred.next = newNode; + } + size++; + } + + + public Node get(int index){ + return node(index); + } + public Node node(int index) { + Node n = head; + for (int i = 0; i < index; i++) { + n = n.next; + } + return n; + } + + public Node remove(int index){ + Node del = node(index); + Node after = del.next; + Node before = del.prev; + before.next = after; + after.prev = before; + size--; + return del; + } + private static class Node { + Node next; + Object data; + Node prev; + + private Node(Node prev, Object data, Node next) { + this.data = data; + this.next = next; + this.prev = prev; + } + } + + public static void main(String[] arg) { + LinkedList ll = new LinkedList(); + ll.add("hello"); + ll.add("java"); + ll.add("jvm"); + ll.add("jvmd"); + // System.out.println(ll.get(2)); +// ll.add(1, "ds"); + System.out.println(ll.get(0).data); + System.out.println(ll.get(1).data); + System.out.println(ll.get(2).data); + System.out.println(ll.get(3).data); + System.out.println(ll.size); + System.out.println(ll.remove(1).data); + System.out.println(ll.get(0).data); + System.out.println(ll.get(1).data); + System.out.println(ll.get(2).data); + System.out.println(ll.size); + } + +} diff --git a/group23/609041842/src/code/Queue.java b/group23/609041842/src/code/Queue.java new file mode 100644 index 0000000000..d4f70c2125 --- /dev/null +++ b/group23/609041842/src/code/Queue.java @@ -0,0 +1,17 @@ +package code; + +public class Queue { + + private LinkedList lk = new LinkedList(); + public void enQueue(Object o){ + lk.add(o); + } + public void deQueue(){ + lk.remove(lk.size-1); + } + public boolean isEmpty(){ + if(lk.size == 0) + return true; + return false; + } +} diff --git a/group23/609041842/src/code/Stack.java b/group23/609041842/src/code/Stack.java new file mode 100644 index 0000000000..7226d4d403 --- /dev/null +++ b/group23/609041842/src/code/Stack.java @@ -0,0 +1,30 @@ +package code; + +public class Stack { + + private ArrayList array = new ArrayList(); + + public void push(Object o){ + array.add(o); + } + public Object pop(){ + return array.remove(array.size()-1); + } + + public boolean isEmpty(){ + if(array.size()<=0) + return true; + return false; + } + + public int size(){ + return array.size(); + } + public static void main(String[] args) { + Stack sc = new Stack(); + sc.push("hello world"); + sc.push("java"); + sc.push("jvm"); + } + +} diff --git a/group23/609041842/src/com/homework01/ArrayList.java b/group23/609041842/src/com/homework01/ArrayList.java index 1feb6162ad..1702690ae7 100644 --- a/group23/609041842/src/com/homework01/ArrayList.java +++ b/group23/609041842/src/com/homework01/ArrayList.java @@ -1,49 +1,49 @@ -package com.homework01; - -import java.util.Arrays; - -public class ArrayList { - - private Object[] obj = new Object[0]; - - public void add(Object o) { - Object[] tar = new Object[obj.length + 1]; - System.arraycopy(obj, 0, tar, 0, obj.length); - tar[tar.length - 1] = o; - obj = tar; - System.out.println(Arrays.toString(obj)); - } - - public void add(int index, Object o) { - Object[] tar = new Object[obj.length + 1]; - System.arraycopy(obj, 0, tar, 0, index); - tar[index] = o; - System.arraycopy(obj, index, tar, index + 1, obj.length - index); - obj = tar; - } - - public Object get(int index) { - return obj[index]; - } - - public int size(){ - return obj.length; - } - - public Object remove(int index){ - Object[] tar = new Object[obj.length-1]; - System.arraycopy(obj, 0, tar, 0, index); - System.arraycopy(obj, index+1, tar, index, obj.length-index-1); - Object o = obj[index]; - obj = tar; - return o;//���ر�ɾԪ�� - } - public static void main(String[] args) { - ArrayList al = new ArrayList(); - al.add("hello"); - al.add("java"); - al.add(2, "addm"); - System.out.println(al.remove(1)); - } - -} +package com.homework01; + +import java.util.Arrays; + +public class ArrayList { + + private Object[] obj = new Object[0]; + + public void add(Object o) { + Object[] tar = new Object[obj.length + 1]; + System.arraycopy(obj, 0, tar, 0, obj.length); + tar[tar.length - 1] = o; + obj = tar; + System.out.println(Arrays.toString(obj)); + } + + public void add(int index, Object o) { + Object[] tar = new Object[obj.length + 1]; + System.arraycopy(obj, 0, tar, 0, index); + tar[index] = o; + System.arraycopy(obj, index, tar, index + 1, obj.length - index); + obj = tar; + } + + public Object get(int index) { + return obj[index]; + } + + public int size(){ + return obj.length; + } + + public Object remove(int index){ + Object[] tar = new Object[obj.length-1]; + System.arraycopy(obj, 0, tar, 0, index); + System.arraycopy(obj, index+1, tar, index, obj.length-index-1); + Object o = obj[index]; + obj = tar; + return o;//���ر�ɾԪ�� + } + public static void main(String[] args) { + ArrayList al = new ArrayList(); + al.add("hello"); + al.add("java"); + al.add(2, "addm"); + System.out.println(al.remove(1)); + } + +} diff --git a/group23/609041842/src/com/homework01/LinkedList.java b/group23/609041842/src/com/homework01/LinkedList.java index f18c110c7c..cc72fc2e4c 100644 --- a/group23/609041842/src/com/homework01/LinkedList.java +++ b/group23/609041842/src/com/homework01/LinkedList.java @@ -1,87 +1,87 @@ -package com.homework01; - -public class LinkedList { - private static Node head; - private Node last; - public int size; - - public void add(Object o) { - Node l = last; - Node newNode = new Node(l, o, null); - last = newNode; - if (head == null) { - head = newNode; - size = 1; - } else { - l.next = newNode; - size++; - } - } - - public void add(int index, Object o) { - Node n = node(index); - System.out.println(n.data); - Node pred = n.prev; - Node newNode = new Node(pred, o, n); - if (pred == null) { - head = newNode; - } else { - pred.next = newNode; - } - size++; - } - - - public Node get(int index){ - return node(index); - } - public Node node(int index) { - Node n = head; - for (int i = 0; i < index; i++) { - n = n.next; - } - return n; - } - - public Node remove(int index){ - Node del = node(index); - Node after = del.next; - Node before = del.prev; - before.next = after; - after.prev = before; - size--; - return del; - } - private static class Node { - Node next; - Object data; - Node prev; - - private Node(Node prev, Object data, Node next) { - this.data = data; - this.next = next; - this.prev = prev; - } - } - - public static void main(String[] arg) { - LinkedList ll = new LinkedList(); - ll.add("hello"); - ll.add("java"); - ll.add("jvm"); - ll.add("jvmd"); - // System.out.println(ll.get(2)); -// ll.add(1, "ds"); - System.out.println(ll.get(0).data); - System.out.println(ll.get(1).data); - System.out.println(ll.get(2).data); - System.out.println(ll.get(3).data); - System.out.println(ll.size); - System.out.println(ll.remove(1).data); - System.out.println(ll.get(0).data); - System.out.println(ll.get(1).data); - System.out.println(ll.get(2).data); - System.out.println(ll.size); - } - -} +package com.homework01; + +public class LinkedList { + private static Node head; + private Node last; + public int size; + + public void add(Object o) { + Node l = last; + Node newNode = new Node(l, o, null); + last = newNode; + if (head == null) { + head = newNode; + size = 1; + } else { + l.next = newNode; + size++; + } + } + + public void add(int index, Object o) { + Node n = node(index); + System.out.println(n.data); + Node pred = n.prev; + Node newNode = new Node(pred, o, n); + if (pred == null) { + head = newNode; + } else { + pred.next = newNode; + } + size++; + } + + + public Node get(int index){ + return node(index); + } + public Node node(int index) { + Node n = head; + for (int i = 0; i < index; i++) { + n = n.next; + } + return n; + } + + public Node remove(int index){ + Node del = node(index); + Node after = del.next; + Node before = del.prev; + before.next = after; + after.prev = before; + size--; + return del; + } + private static class Node { + Node next; + Object data; + Node prev; + + private Node(Node prev, Object data, Node next) { + this.data = data; + this.next = next; + this.prev = prev; + } + } + + public static void main(String[] arg) { + LinkedList ll = new LinkedList(); + ll.add("hello"); + ll.add("java"); + ll.add("jvm"); + ll.add("jvmd"); + // System.out.println(ll.get(2)); +// ll.add(1, "ds"); + System.out.println(ll.get(0).data); + System.out.println(ll.get(1).data); + System.out.println(ll.get(2).data); + System.out.println(ll.get(3).data); + System.out.println(ll.size); + System.out.println(ll.remove(1).data); + System.out.println(ll.get(0).data); + System.out.println(ll.get(1).data); + System.out.println(ll.get(2).data); + System.out.println(ll.size); + } + +} diff --git a/group23/609041842/src/com/homework01/Queue.java b/group23/609041842/src/com/homework01/Queue.java index afc54a2dda..db8fb359b5 100644 --- a/group23/609041842/src/com/homework01/Queue.java +++ b/group23/609041842/src/com/homework01/Queue.java @@ -1,17 +1,17 @@ -package com.homework01; - -public class Queue { - - private LinkedList lk = new LinkedList(); - public void enQueue(Object o){ - lk.add(o); - } - public void deQueue(){ - lk.remove(lk.size-1); - } - public boolean isEmpty(){ - if(lk.size == 0) - return true; - return false; - } -} +package com.homework01; + +public class Queue { + + private LinkedList lk = new LinkedList(); + public void enQueue(Object o){ + lk.add(o); + } + public void deQueue(){ + lk.remove(lk.size-1); + } + public boolean isEmpty(){ + if(lk.size == 0) + return true; + return false; + } +} diff --git a/group23/609041842/src/com/homework01/Stack.java b/group23/609041842/src/com/homework01/Stack.java index a5bc4488af..ee5d71d830 100644 --- a/group23/609041842/src/com/homework01/Stack.java +++ b/group23/609041842/src/com/homework01/Stack.java @@ -1,30 +1,30 @@ -package com.homework01; - -public class Stack { - - private ArrayList array = new ArrayList(); - - public void push(Object o){ - array.add(o); - } - public Object pop(){ - return array.remove(array.size()-1); - } - - public boolean isEmpty(){ - if(array.size()<=0) - return true; - return false; - } - - public int size(){ - return array.size(); - } - public static void main(String[] args) { - Stack sc = new Stack(); - sc.push("hello world"); - sc.push("java"); - sc.push("jvm"); - } - -} +package com.homework01; + +public class Stack { + + private ArrayList array = new ArrayList(); + + public void push(Object o){ + array.add(o); + } + public Object pop(){ + return array.remove(array.size()-1); + } + + public boolean isEmpty(){ + if(array.size()<=0) + return true; + return false; + } + + public int size(){ + return array.size(); + } + public static void main(String[] args) { + Stack sc = new Stack(); + sc.push("hello world"); + sc.push("java"); + sc.push("jvm"); + } + +} diff --git a/group23/632678665/com/basic/datastructure/ArrayList.java b/group23/632678665/com/basic/datastructure/ArrayList.java index 35fb185737..7669e8fba0 100644 --- a/group23/632678665/com/basic/datastructure/ArrayList.java +++ b/group23/632678665/com/basic/datastructure/ArrayList.java @@ -2,7 +2,6 @@ import java.util.Arrays; -import org.junit.Test; public class ArrayList implements List{ private Object [] array =new Object [15]; @@ -60,5 +59,4 @@ public int size() { Object [] newArray; return newArray=Arrays.copyOf(o, (int) (o.length*1.5)); } - } diff --git a/group23/632678665/com/basic/week2/litestruts/LoginAction.java b/group23/632678665/com/basic/week2/litestruts/LoginAction.java new file mode 100644 index 0000000000..80133805ac --- /dev/null +++ b/group23/632678665/com/basic/week2/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package com.basic.week2.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * @author liuxin + * + */ +public class LoginAction{ + private String name ; + private String password; + private String message; + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String execute(){ + if("test".equals(name) && "1234".equals(password)){ + this.message = "login successful"; + return "success"; + } + this.message = "login failed,please check your user/pwd"; + return "fail"; + } + + public void setName(String name){ + this.name = name; + } + public void setPassword(String password){ + this.password = password; + } + public String getMessage(){ + return this.message; + } +} diff --git a/group23/632678665/com/basic/week2/litestruts/Struts.java b/group23/632678665/com/basic/week2/litestruts/Struts.java new file mode 100644 index 0000000000..0b1a7c03f0 --- /dev/null +++ b/group23/632678665/com/basic/week2/litestruts/Struts.java @@ -0,0 +1,35 @@ +package com.basic.week2.litestruts; + + +import java.util.Map; + + + +public class Struts { + + public static View runAction(String actionName, Map parameters) { + + /* + + 0. 读取配置文件struts.xml + + 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + ("name"="test" , "password"="1234") , + 那就应该调用 setName和setPassword方法 + + 2. 通过反射调用对象的exectue 方法, 并获得返回值,例如"success" + + 3. 通过反射找到对象的所有getter方法(例如 getMessage), + 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + 放到View对象的parameters + + 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + 放到View对象的jsp字段中。 + + */ + + return null; + } + +} diff --git a/group23/632678665/com/basic/week2/litestruts/StrutsTest.java b/group23/632678665/com/basic/week2/litestruts/StrutsTest.java new file mode 100644 index 0000000000..5549100269 --- /dev/null +++ b/group23/632678665/com/basic/week2/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package com.basic.week2.litestruts; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + + + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() { + + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + Assert.assertEquals("login successful", view.getParameters().get("message")); + } + + @Test + public void testLoginActionFailed() { + String actionName = "login"; + Map params = new HashMap(); + params.put("name","test"); + params.put("password","123456"); //密码和预设的不一致 + + View view = Struts.runAction(actionName,params); + + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + } +} diff --git a/group23/632678665/com/basic/week2/litestruts/View.java b/group23/632678665/com/basic/week2/litestruts/View.java new file mode 100644 index 0000000000..7260afd69b --- /dev/null +++ b/group23/632678665/com/basic/week2/litestruts/View.java @@ -0,0 +1,24 @@ +package com.basic.week2.litestruts; + + +import java.util.Map; + +public class View { + private String jsp; + private Map parameters; + + public String getJsp() { + return jsp; + } + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + public Map getParameters() { + return parameters; + } + public View setParameters(Map parameters) { + this.parameters = parameters; + return this; + } +} diff --git a/group23/632678665/com/basic/week3/datastructure/LinkedList.java b/group23/632678665/com/basic/week3/datastructure/LinkedList.java new file mode 100644 index 0000000000..09b08dd25f --- /dev/null +++ b/group23/632678665/com/basic/week3/datastructure/LinkedList.java @@ -0,0 +1,446 @@ +package com.basic.week3.datastructure; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +public class LinkedList implements List { + + private int size = 0; + // 头结点 + private Node head; + // 尾结点 + private Node tail; + + private void rangeCheck(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(); + } + } + +// public void add(Object o) { +// Node node = new Node(o, null); +// if (head == null) { +// head = tail = node; +// } +// Node oldTail = tail; +// tail = node; +// oldTail.next = tail; +// size++; +// } + + public void add(int index, Object o) { + rangeCheck(index); + if (index == size) { + this.add(o); + } else { + // 保存index处节点 + Node x = head; + // 保存index-1处的节点 + Node y = null; + for (int i = 0; i < index; i++) { + y = x; + x = x.next; + } + Node node = new Node(o, x); + y.next = node; + size++; + } + } + + public Object get(int index) { + rangeCheck(index); + Node x = head; + for (int i = 0; i < index; i++) { + x = x.next; + } + return x.data; + } + + public Object remove(int index) { + rangeCheck(index); + Object removeData; + if (index == 0) { + removeData = removeFirst(); + } else if (index == size - 1) { + removeData = removeLast(); + } else { + Node x = head; + Node y = head; + for (int i = 0; i < index; i++) { + y = x; + x = x.next; + } + y.next = x.next; + size--; + removeData = x.data; + } + return removeData; + } + + @Override + public int size() { + return size; + } + + public void addFirst(Object o) { + Node oldHead = head; + head = new Node(o, oldHead); + size++; + } + + public void addLast(Object o) { + Node oldTail = tail; + tail = new Node(o, null); + oldTail.next = tail; + size++; + } + + public Object removeFirst() { + Node next = head.next; + Object data = head.data; + head.data = null; + head.next = null; + head = next; + size--; + return data; + } + + public Object removeLast() { + Node oldTail = tail; + Node temp = head; + for (int i = 0; i < size - 2; i++) { + temp = temp.next; + } + tail = temp; + size--; + return oldTail.data; + } + + public void clear() { + for (Node x = head; x != null;) { + Node next = x.next; + x.data = null; + x.next = null; + x = next; + } + head = tail = null; + size = 0; + } + + public Object getTail() { + Node l = tail; + // 如果链表为空 + if (l == null) { + throw new NoSuchElementException(); + } + return l.data; + } + + public Object getHead() { + Node l = head; + // 如果链表为空 + if (l == null) { + throw new NoSuchElementException(); + } + return l.data; + } + + public Iterator iterator() { + return new LinkedListIterator(); + } + + private static class Node { + Object data; + Node next; + + Node(Object data, Node next) { + this.data = data; + this.next = next; + } + + } + + private class LinkedListIterator implements Iterator { + Node x = head; + + @Override + public boolean hasNext() { + return x != null; + } + + @Override + public Object next() { + Object data = x.data; + x = x.next; + return data; + } + + @Override + public void remove() { + // TODO Auto-generated method stub + + } + + } + + /** + * 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Object[] temp = new Object[size]; + for (int i = 0; i < size; i++) { + temp[i] = this.get(i); + } + this.clear(); + for (int i = temp.length - 1; i >= 0; i--) { + this.add(temp[i]); + } + } + + /** + * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 + * ,删除以后的值为7,8,10 + * + */ + public void removeFirstHalf() { + int s = size; + for (int i = 0; i < s / 2; i++) { + this.removeFirst(); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + * @throws Exception + */ + public void remove(int i, int length) throws Exception { + if (i + length > size) { + throw new Exception(); + } + for (int j = i; j < i + length; j++) { + this.remove(i); + } + } + + /** + * 假定当前链表和list均包含已升序排列的整数 从当前链表中取出那些list所指定的元素 例如当前链表 = + * 11->101->201->301->401->501->601->701 listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + * @throws Exception + */ + public int[] getElements(LinkedList list) throws Exception { + if ((int) list.getTail() > this.size()) { + throw new Exception(); + } + int[] temp = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + temp[i] = (int) this.get((int) list.get(i)); + } + return temp; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + Node x = head; + Node y = list.head; + while (x != null && y != null) { + if ((int) x.data < (int) y.data) { + x = x.next; + continue; + } + if ((int) x.data == (int) y.data) { + Node next = x.next; + continue; + } + if ((int) x.data > (int) y.data) { + y = y.next; + continue; + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + for (Node x = head; x != null;) { + Node next = x.next; + if (next == null) { + return; + } + if (x.data == next.data) { + x.next = next.next; + size--; + } else { + x = x.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if ((int) this.getTail() < min) { + this.clear(); + } + + if ((int) this.getHead() > max) { + return; + } + + for (Node x = head; x != null; x = x.next) { + if ((int) x.data <= min) { + continue; + } + + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList linkedList = new LinkedList(); + Node x = head; + Node y = list.head; + while (x != null && y != null) { + if ((int) x.data < (int) y.data) { + x = x.next; + continue; + } + if ((int) x.data == (int) y.data) { + linkedList.add(x.data); + x = x.next; + y = y.next; + continue; + } + if ((int) x.data > (int) y.data) { + y = y.next; + continue; + } + } + return linkedList; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean contains(Object o) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Object[] toArray() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object[] toArray(Object[] a) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean remove(Object o) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean containsAll(Collection c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean addAll(Collection c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean addAll(int index, Collection c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean removeAll(Collection c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean retainAll(Collection c) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Object set(int index, Object element) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int indexOf(Object o) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int lastIndexOf(Object o) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public ListIterator listIterator() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ListIterator listIterator(int index) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List subList(int fromIndex, int toIndex) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean add(Object e) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/group23/632678665/com/basic/week3/download/Demo.java b/group23/632678665/com/basic/week3/download/Demo.java new file mode 100644 index 0000000000..f4dc344cb5 --- /dev/null +++ b/group23/632678665/com/basic/week3/download/Demo.java @@ -0,0 +1,36 @@ +package com.basic.week3.download; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.RandomAccessFile; +import java.net.URL; + +public class Demo { + + public static void main(String[] args) throws Exception { +// File f=new File("E://123.txt"); +// InputStream ii=new FileInputStream(f); +// byte [] b=new byte [2]; +// int j; +// while(true){ +// if(ii.read(b)==0){ +// System.out.println("1111"); +// } +// if(ii.read(b)==-1){ +// System.out.println("3333"); +// } +// } + URL url=new URL("Http://localhsot:8080/123.txt"); + String [] s=url.toString().split("/"); + for(String str:s){ + + } + } + +} diff --git a/group23/632678665/com/basic/week3/download/DownloadThread.java b/group23/632678665/com/basic/week3/download/DownloadThread.java new file mode 100644 index 0000000000..89b7fdc3f5 --- /dev/null +++ b/group23/632678665/com/basic/week3/download/DownloadThread.java @@ -0,0 +1,31 @@ +package com.basic.week3.download; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.basic.week3.download.api.Connection; + +public class DownloadThread extends Thread{ + public static int count=0; + Connection conn; + int startPos; + int endPos; + + public DownloadThread(Connection conn, int startPos, int endPos){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + } + public void run(){ + try { + count++; + conn.read(startPos, endPos); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }finally{ + count--; + } + } +} diff --git a/group23/632678665/com/basic/week3/download/FileDownloader.java b/group23/632678665/com/basic/week3/download/FileDownloader.java new file mode 100644 index 0000000000..d32975f4b5 --- /dev/null +++ b/group23/632678665/com/basic/week3/download/FileDownloader.java @@ -0,0 +1,97 @@ +package com.basic.week3.download; + +import com.basic.week3.download.api.Connection; +import com.basic.week3.download.api.ConnectionException; +import com.basic.week3.download.api.ConnectionManager; +import com.basic.week3.download.api.DownloadListener; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + Connection conn; + + DownloadThread dt; + + private static final int THREAD_NUM=4; + public FileDownloader(String _url) { + this.url = _url; + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + /*Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + new DownloadThread(conn,0,length-1).start(); + + } catch (ConnectionException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + }*/ + try { + //打开url + conn=cm.open(url); + //判断资源长度 + int length=conn.getContentLength(); + //每个线程所占的资源 + int off=(int)(length/3); + int start=0; + for(int i=0;i clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + List list = DOT_SPLITTER.splitToList(className); + String childDirectory = SLASH_JOINER.join(list); + for (String clzPath : clzPaths) { + String fullPath = makeFullPath(clzPath, childDirectory); + if (fileExist(fullPath)) { + return readFileBytes(fullPath); + } + } + System.out.println("no this class file: " + className); + return null; + } + + private byte[] readFileBytes(String filePath) { + try { + File file = new File(filePath); + long length = file.length(); + byte[] fileBytes = new byte[(int) length]; + int readLength = new FileInputStream(filePath).read(fileBytes); + if (readLength != length) { + System.out.println("read file error. read length: " + readLength + ", full length : " + length); + return null; + } + return fileBytes; + } catch (IOException e) { + System.out.println("read file error. " + filePath); + return null; + } + } + + private boolean fileExist(String fullPath) { + File classFile = new File(fullPath); + return classFile.exists() && classFile.isFile(); + } + + private String makeFullPath(String clzPath, String childDirectory) { + if (clzPath.endsWith("/") || clzPath.endsWith("\\")) { + return clzPath + childDirectory + CLASS_SUFFIX; + } else { + return clzPath + "/" + childDirectory + CLASS_SUFFIX; + } + } + + public void addClassPath(String path) { + if (!clzPaths.contains(path)) { + clzPaths.add(path); + } + } + + public String getClassPath() { + return SEMICOLON_JOINER.join(clzPaths); + } + +} diff --git a/group23/632678665/com/basic/week4/jvm/test/EmployeeV1.java b/group23/632678665/com/basic/week4/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..7d0419dc77 --- /dev/null +++ b/group23/632678665/com/basic/week4/jvm/test/EmployeeV1.java @@ -0,0 +1,30 @@ +package com.coding2017.week4.jvm.test; + +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/group23/632678665/com/basic/week4/lru/LRUPageFrame.java b/group23/632678665/com/basic/week4/lru/LRUPageFrame.java new file mode 100644 index 0000000000..55039dda56 --- /dev/null +++ b/group23/632678665/com/basic/week4/lru/LRUPageFrame.java @@ -0,0 +1,131 @@ +package com.coding2017.week4.lru; + +/** + * 用双向链表实现LRU算法 + * + * @author liuxin + * + */ +public class LRUPageFrame { + private static class Node { + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + private Node first;// 链表头 + private Node last;// 链表尾 + private int size; // 当前个数 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + size = 0; + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @return + */ + public void access(int pageNum) { + Node node = query(pageNum); + if (node == null) { + Node newNode = new Node(); + newNode.pageNum = pageNum; + accessNotExist(newNode); + } else { + accessExist(node); + } + } + + private void accessExist(Node node) { + removeNode(node); + addFirst(node); + } + + /** + * 此处没有要求传入的node的prev和next, 所以需要自己处理 + * + * @param node + */ + private void addFirst(Node node) { + node.prev = null; + node.next = null; + if (first == null) { + first = node; + last = node; + } else { + first.prev = node; + node.next = first; + first = node; + } + size++; + } + + /** + * 需要考虑删除的节点是头结点, 或尾节点的情况 + */ + private void removeNode(Node node) { + if (node.prev == null) { + first = node.next; + } + if (node.next == null) { + last = node.prev; + } + if (node.prev != null) { + node.prev.next = node.next; + } + if (node.next != null) { + node.next.prev = node.prev; + } + size--; + } + + /** + * 如果已经满了, 则挤出去一个, 然后追加 + * + * @param node + */ + private void accessNotExist(Node node) { + if (size == capacity) { + removeLast(); + } + addFirst(node); + } + + private void removeLast() { + last.prev.next = null; + last = last.prev; + size--; + } + + private Node query(int pageNum) { + for (Node node = first; node != null; node = node.next) { + if (pageNum == node.pageNum) { + return node; + } + } + return null; + } + + 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/group23/632678665/com/basic/week5/stack/StackUtil.java b/group23/632678665/com/basic/week5/stack/StackUtil.java new file mode 100644 index 0000000000..7b750b3549 --- /dev/null +++ b/group23/632678665/com/basic/week5/stack/StackUtil.java @@ -0,0 +1,103 @@ +package com.coding.week5.stack; + +import com.coding.weak1.Stack; + +public class StackUtil { + + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack stack = new Stack(); + Stack stack1 = new Stack(); + while (!s.isEmpty()) { + stack.push(s.pop()); + } + while (!stack.isEmpty()) { + stack1.push(stack.pop()); + } + while (!stack1.isEmpty()) { + s.push(stack1.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + Stack stack = new Stack(); + while (!s.isEmpty()){ + Object o1 = s.pop(); + if (!o.equals(o1)) { + stack.push(o1); + } + } + while (!stack.isEmpty()) { + s.push(stack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (len > s.size() || len <= 0) { + throw new IllegalArgumentException(len+""); + } + + Object[] objects = new Object[len]; + for (int i = 0; i < len; i++) { + objects[i] = s.pop(); + } + for (int i = len - 1; i >= 0 ; i--) { + s.push(objects[i]); + } + return objects; + } + /** + * 字符串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 stack = new Stack(); + char[] chars = s.toCharArray(); + for (char c : chars) { + if (c == '(' || c == '{' || c == '[') { + stack.push(c); + } else if (c == ')' || c == '}' || c == ']'){ + if (stack.isEmpty()) { + return false; + } + if (!isPair((char)stack.pop(), c)){ + return false; + } + } + } + return stack.isEmpty(); + } + + private static boolean isPair(char left, char right) { + switch (left) { + case '{': + return right == '}'; + case '[': + return right == ']'; + case '(': + return right == ')'; + default: + return false; + } + } + +} diff --git a/group23/632678665/com/basic/week6/expr/InfixExpr.java b/group23/632678665/com/basic/week6/expr/InfixExpr.java new file mode 100644 index 0000000000..34c1b15123 --- /dev/null +++ b/group23/632678665/com/basic/week6/expr/InfixExpr.java @@ -0,0 +1,127 @@ +package com.coding.week6.expr; + +import com.coding.weak1.Stack; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class InfixExpr { + String expr = null; + private Stack numberStack; + private Stack operatorStack; + private List tokens; + public InfixExpr(String expr) { + this.expr = expr; + this.numberStack = new Stack(); + this.operatorStack = new Stack(); + tokens = new ArrayList<>(); + } + + + public float evaluate() { + fillStack(); + while (!operatorStack.isEmpty()) { + char symbol = (char) operatorStack.pop(); + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(symbol, operTop2, operTop1)); + } + return (float)numberStack.pop(); + } + + public void parseTokens() { + char[] chars = expr.toCharArray(); + for (int i = 0; i < chars.length; i++) { + char c = chars[i]; + if (Token.isOperator(c)) { + Token token = new Token(c+""); + tokens.add(token); + } else { + String t = ""; + while (Token.isDigit(c)){ + t += c; + i++; + if (i == chars.length) + break; + c = chars[i]; + } + Token token = new Token(t); + tokens.add(token); + i--; + } + } + } + + + public void fillStack() { + parseTokens(); + Iterator iterator = tokens.iterator(); + while (iterator.hasNext()) { + Token token = iterator.next(); + if (token.isNumber()) { + numberStack.push((float)token.parseInt()); + continue; + } + if (token.isOperator()) { + char operator = token.parseOperator(); + if (operatorStack.isEmpty()) { + operatorStack.push(operator); + }else { + char topSymbol = (char)operatorStack.peek(); + if (compare(operator, topSymbol) > 0) { + operatorStack.push(operator); + } else { + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(caculate(topSymbol, operTop2, operTop1)); + operatorStack.pop(); + operatorStack.push(operator); + } + } + } + + } + } + + + private float caculate(char symbol, float oper1, float oper2) { + if ('*' == symbol) + return oper1 * oper2; + else if ('/' == symbol) + return oper1 / oper2; + else if ('+' == symbol) + return oper1 + oper2; + else if ('-' == symbol) + return oper1 - oper2; + else + throw new RuntimeException("this operation has not implement"); + } + + public int compare(char opertor1, char opertor2) { + if (!Token.isOperator(opertor1) ) + throw new IllegalArgumentException(opertor1 + "is not supported opertor"); + if (!Token.isOperator(opertor2)) + throw new IllegalArgumentException(opertor2 + "is not supported opertor"); + if (Token.isAddOrSub(opertor1)) { + if (Token.isAddOrSub(opertor2)) + return 0; + else + return -1; + } + else { + if (Token.isAddOrSub(opertor2)) + return 1; + else + return 0; + } + } + + public String printNumberStack() { + return numberStack.toString(); + } + + public String printOperatorStack() { + return operatorStack.toString(); + } +} diff --git a/group23/632678665/com/basic/week6/expr/Token.java b/group23/632678665/com/basic/week6/expr/Token.java new file mode 100644 index 0000000000..b58aa36968 --- /dev/null +++ b/group23/632678665/com/basic/week6/expr/Token.java @@ -0,0 +1,52 @@ +package com.coding.week6.expr; + +/** + * Created by Administrator on 2017/4/16 0016. + */ +public class Token { + + private String symbol; + + public Token(String symbol) { + this.symbol = symbol; + } + + public boolean isNumber() { + return symbol.matches("^\\d+$"); + } + + + public boolean isOperator() { + return symbol.matches("^[\\+|\\*|\\-|\\/]$"); + } + + public int parseInt() { + return Integer.valueOf(symbol); + } + + public char parseOperator() { + return symbol.charAt(0); + } + + + public static boolean isOperator(char c) { + return isAddOrSub(c) || isMulityOrDivide(c); + } + + public static boolean isAddOrSub(char c) { + return c == '+' || c == '-'; + } + + public static boolean isMulityOrDivide(char c) { + return c == '/' || c == '*'; + } + + public static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + @Override + public String toString(){ + return symbol; + } +} diff --git a/group23/632678665/com/basic/week6/exprNew/InfixExpr.java b/group23/632678665/com/basic/week6/exprNew/InfixExpr.java new file mode 100644 index 0000000000..3962b49fce --- /dev/null +++ b/group23/632678665/com/basic/week6/exprNew/InfixExpr.java @@ -0,0 +1,57 @@ +package com.coding.week6.exprNew; + +import com.coding.weak1.Stack; + +import java.util.List; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + + public float evaluate() { + + Stack operatorStack = new Stack(); + Stack numberStack = new Stack(); + fillStack(numberStack, operatorStack); + while (!operatorStack.isEmpty()) { + Operator symbol = (Operator) operatorStack.pop(); + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(symbol.apply(operTop2, operTop1)); + } + return (float)numberStack.pop(); + } + + public void fillStack(Stack numberStack, Stack operatorStack) { + TokenParser tokenParser = new TokenParser(); + List tokens = tokenParser.parse(expr); + for (Token token : tokens) { + if (token.isNumber()) { + numberStack.push(token.getFloatValue()); + } + else if (token.isOperator()) { + Operator o = token.getOperator(); + if (operatorStack.isEmpty()) { + operatorStack.push(o); + }else { + Operator top = (Operator)operatorStack.peek(); + if (o.hasHigherPriority(top)) { + operatorStack.push(o); + } else { + float operTop1 = (float) numberStack.pop(); + float operTop2 = (float) numberStack.pop(); + numberStack.push(top.apply(operTop2, operTop1)); + operatorStack.pop(); + operatorStack.push(o); + } + } + } + + } + } + +} diff --git a/group23/632678665/com/basic/week6/exprNew/Operator.java b/group23/632678665/com/basic/week6/exprNew/Operator.java new file mode 100644 index 0000000000..f6b4681e46 --- /dev/null +++ b/group23/632678665/com/basic/week6/exprNew/Operator.java @@ -0,0 +1,75 @@ +package com.coding.week6.exprNew; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public enum Operator { + ADD("+", 1) { + public float apply(float x, float y){ + return x + y; + } + }, + + SUB("-", 1) { + @Override + public float apply(float x, float y) { + return x - y; + } + }, + + MULT("*", 2) { + @Override + public float apply(float x, float y) { + return x * y; + } + }, + + DIVI("/", 2) { + @Override + public float apply(float x, float y) { + return x / y; + } + }; + private String symbol; + private int priority; + + Operator(String symbol, int priority) { + this.symbol = symbol; + this.priority = priority; + } + + public boolean hasHigherPriority(Operator o) { + return this.priority > o.priority; + } + + public String symbol() { + return symbol; + } + + public static List symbols() { + List symbos = new ArrayList<>(); + for (Operator o : Operator.values()) { + symbos.add(o.symbol); + } + return symbos; + } + + public abstract float apply(float x, float y); + + private static final Map map = new HashMap(); + + static { + for (Operator o : Operator.values()) { + map.put(o.symbol, o); + } + } + + public static Map getOperatorMap() { + return map; + } +} diff --git a/group23/632678665/com/basic/week6/exprNew/Token.java b/group23/632678665/com/basic/week6/exprNew/Token.java new file mode 100644 index 0000000000..c925a22705 --- /dev/null +++ b/group23/632678665/com/basic/week6/exprNew/Token.java @@ -0,0 +1,63 @@ +package com.coding.week6.exprNew; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public class Token { + + private int type; + private String value; + + static final int NUMBER = 1; + static final int OPERATOR = 2; + static final int LEFT_BRACKET = 3; + static final int RIGHT_BRACKET = 4; + 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 isLeftBracket() { + return type == LEFT_BRACKET; + } + + public boolean isRightBracket() { + return type == RIGHT_BRACKET; + } + + public float getFloatValue() { + if (isNumber()) + return Integer.valueOf(value); + else + throw new RuntimeException("not a number"); + } + + public String toString() { + return value; + } + + + public Operator getOperator() { + if (isOperator()) { + return Operator.getOperatorMap().get(value); + } else { + throw new RuntimeException("not a operator"); + } + } + + + public String getValue() { + return value; + } + + +} diff --git a/group23/632678665/com/basic/week6/exprNew/TokenParser.java b/group23/632678665/com/basic/week6/exprNew/TokenParser.java new file mode 100644 index 0000000000..52757dc0c7 --- /dev/null +++ b/group23/632678665/com/basic/week6/exprNew/TokenParser.java @@ -0,0 +1,60 @@ +package com.coding.week6.exprNew; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/4/22 0022. + */ +public class TokenParser { + + private static List operators = Operator.symbols(); + public List parse(String expr) { + List tokens = new ArrayList<>(); + int i = 0; + while (i < expr.length()) { + char c = expr.charAt(i); + Token token; + if (Character.isDigit(c)) { + int nextOperIndex = getNextOperIndex(i, expr); + String n = expr.substring(i, nextOperIndex); + token = new Token(Token.NUMBER, n); + tokens.add(token); + i = nextOperIndex; + } else if (isOperator(c)) { + token = new Token(Token.OPERATOR, c+""); + tokens.add(token); + i++; + } else if (String.valueOf(c).matches("\\s")){ + i++; + } else if (c == '(') { + token = new Token(Token.LEFT_BRACKET, String.valueOf(c)); + tokens.add(token); + i++; + } else if (c == ')') { + token = new Token(Token.RIGHT_BRACKET, String.valueOf(c)); + tokens.add(token); + i++; + } else { + throw new RuntimeException(c +" is not number or support operator"); + } + } + return tokens; + } + + private int getNextOperIndex(int i, String expr) { + while (Character.isDigit(expr.charAt(i))) { + i++; + if (i == expr.length()) { + break; + } + } + return i; + } + + private boolean isOperator(char c) { + return operators.contains(String.valueOf(c)); + } + + +} diff --git a/group23/632678665/com/basic/week7/stack/MyStack.java b/group23/632678665/com/basic/week7/stack/MyStack.java new file mode 100644 index 0000000000..9a8bf42296 --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/MyStack.java @@ -0,0 +1,42 @@ +package com.ralf.stack; + +import java.util.LinkedList; +import java.util.NoSuchElementException; + +/** + * ʵֻݽṹջ + * + * @author chk + * + */ +public class MyStack { + + private LinkedList linkedList = new LinkedList<>(); + + public MyStack() { + + } + + public void push(T t) { + linkedList.addFirst(t); + } + + public T pop() { + if (size() == 0) { + throw new NoSuchElementException(); + } + return linkedList.removeFirst(); + } + + public T peek() { + return (size() == 0) ? null : linkedList.getFirst(); + } + + public int size() { + return linkedList.size(); + } + + public boolean isEmpty(){ + return linkedList.isEmpty(); + } +} diff --git a/group23/632678665/com/basic/week7/stack/StackUtil.java b/group23/632678665/com/basic/week7/stack/StackUtil.java new file mode 100644 index 0000000000..758178131c --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/StackUtil.java @@ -0,0 +1,173 @@ +package com.ralf.stack; + +import java.util.NoSuchElementException; + +public class StackUtil { + + private static MyStack myStack = new MyStack<>(); + + /** + * ջеԪInteger, ջջ : 5,4,3,2,1 ø÷ ԪشΪ: 1,2,3,4,5 + * ע⣺ֻʹStackĻpush,pop,peek,isEmpty ʹһջ + * + * @param + */ + public static void reverse(MyStack stack) { + + if (stack.isEmpty()) { + System.out.println("ջΪջ"); + return; + } + @SuppressWarnings("unchecked") + T[] elements = (T[]) new Object[stack.size()]; + for (int i = 0; i < elements.length; i++) { + elements[i] = stack.pop(); + } + for (int i = 0; i < elements.length; i++) { + stack.push(elements[i]); + } + + } + + public static void bad_reverse(MyStack s) { + if(s == null || s.isEmpty()){ + return; + } + MyStack tmpStack = new MyStack<>(); + while(!s.isEmpty()){ + tmpStack.push(s.pop()); + } + + s = tmpStack; + + } + + + /** + * ɾջеijԪ ע⣺ֻʹStackĻpush,pop,peek,isEmpty ʹһջ + * + * @param o + */ + public static void remove(MyStack s, T o) { + if (s.isEmpty()) { + System.out.println("ջΪգ"); + return; + } + MyStack stack = new MyStack<>(); + + while (!s.isEmpty()) { + T t = s.pop(); + if (t.equals(o)) { + PopAndPush(s, stack); + return; + } + stack.push(t); + } + throw new NoSuchElementException("ջûиԪأ"); + + } + + private static void PopAndPush(MyStack s, MyStack stack) { + while (!stack.isEmpty()) { + T t = stack.pop(); + s.push(t); + } + } + + /** + * ջȡlenԪ, ԭջԪرֲ ע⣺ֻʹStackĻpush,pop,peek,isEmpty + * ʹһջ + * + * @param len + * @return + */ + @SuppressWarnings("unchecked") + public static T[] getTop(MyStack s, int len) { + + if (s.isEmpty() || len > s.size()) { + return null; + } + MyStack oldStack = s; + T[] elements = (T[]) new Object[len]; + for (int i = 0; i < len; i++) { + elements[i] = s.pop(); + } + s = oldStack; + return elements; + } + + /** + * ַs ܰЩַ ( ) [ ] { }, a,b,c... x,yz ʹöջַsеDzdzɶԳֵġ s = + * "([e{d}f])" , ַеdzɶԳ֣ ÷true s = "([b{x]y})", + * ַеŲdzɶԳֵģ ÷false; + * + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + + char[] ch = s.toCharArray(); + if (ch.length < 1) { + return false; + } + + MyStack leftStack = new MyStack<>(); + MyStack rightStack = new MyStack<>(); + + for (int i = 0; i < ch.length; i++) { + + switch (ch[i]) { + case '(': + leftStack.push(String.valueOf(ch[i])); + break; + + case '[': + leftStack.push(String.valueOf(ch[i])); + break; + + case '{': + leftStack.push(String.valueOf(ch[i])); + break; + + case ')': + rightStack.push(String.valueOf(ch[i])); + break; + + case ']': + rightStack.push(String.valueOf(ch[i])); + break; + + case '}': + rightStack.push(String.valueOf(ch[i])); + break; + + default: + break; + } + } + return isPair(leftStack, rightStack); + + } + + private static boolean isPair(MyStack leftStack, + MyStack rightStack) { + + if (leftStack.size() != rightStack.size()) { + return false; + } + + reverse(rightStack); + while (!leftStack.isEmpty()) { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(leftStack.pop()).append(rightStack.pop()); + + String pair = stringBuilder.toString(); + if (!pair.equals("()") && !pair.equals("[]") && !pair.equals("{}")) { + return false; + } + } + return true; + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/ExprIterator.java b/group23/632678665/com/basic/week7/stack/expr/ExprIterator.java new file mode 100644 index 0000000000..d82db3e915 --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/ExprIterator.java @@ -0,0 +1,57 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; + +public class ExprIterator { + + private int operPos; + private int numPos; + private ArrayList operateList = new ArrayList<>(); + private ArrayList numList = new ArrayList<>(); + + public ExprIterator(String exprString) { + char[] chs = exprString.toCharArray(); + transToString(chs); + } + + public Integer nextNumString() { + if (hasNextNum()) { + return Integer.parseInt(numList.get(numPos++)); + } + return null; + } + public String nextOperateString() { + if (hasNextOperate()) { + return operateList.get(operPos++); + } + return null; + } + + public boolean hasNextNum() { + return numPos < numList.size(); + } + + public boolean hasNextOperate() { + return operPos < operateList.size(); + } + + private void transToString(char[] chs) { + + StringBuilder stringBuilder = new StringBuilder(); + + for (int i = 0; i < chs.length; i++) { + if (chs[i] == '+' || chs[i] == '-' || chs[i] == '*' + || chs[i] == '/') { + numList.add(stringBuilder.toString()); + operateList.add(String.valueOf(chs[i])); + stringBuilder.delete(0, stringBuilder.length()); + } + else { + stringBuilder.append(chs[i]); + } + + } + numList.add(stringBuilder.toString()); + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/InfixExpr.java b/group23/632678665/com/basic/week7/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..86a060845c --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/InfixExpr.java @@ -0,0 +1,74 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class InfixExpr { + + private String exprString; + + public InfixExpr(String exprString) { + this.exprString = exprString; + } + + public double evaluate() { + + MyStack numStack = new MyStack(); + MyStack operStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + + List list = parser.parse(exprString); + + for (Token token : list) { + if (token.isOperator()) { + if (operStack.isEmpty()) { + operStack.push(token); + } else { + while (!operStack.isEmpty() + && !token.hasHigherPriority(operStack.peek())) { + String operator = operStack.pop().toString(); + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = operate(operator,num1,num2); + numStack.push(result); + } + operStack.push(token); + } + } + if (token.isNumber()) { + numStack.push(new Float(token.getValue())); + } + } + + while(!operStack.isEmpty()){ + String operator = operStack.pop().toString(); + Float num1 = numStack.pop(); + Float num2 = numStack.pop(); + Float result = operate(operator,num1,num2); + numStack.push(result); + } + + return numStack.pop().floatValue(); + } + + private Float operate(String operator,Float num1, Float num2) { + float result = 0.0f; + switch (operator) { + case "+": + result = num2 + num1; + break; + case "-": + result = num2 - num1; + break; + case "*": + result = num2 * num1; + break; + case "/": + result = num2 / num1; + break; + } + return result; + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/InfixToPostExpr.java b/group23/632678665/com/basic/week7/stack/expr/InfixToPostExpr.java new file mode 100644 index 0000000000..6296d160ef --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/InfixToPostExpr.java @@ -0,0 +1,41 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +import com.ralf.stack.MyStack; +import com.ralf.stack.StackUtil; + +public class InfixToPostExpr { + + public static List convert(String infixString){ + + TokenParser parser = new TokenParser(); + List tokens = parser.parse(infixString); + + MyStack S1 = new MyStack(); + MyStack S2 = new MyStack<>(); + + + for(Token token : tokens){ + if (token.isNumber()) { + S2.push(token); + } + else{ + while(!S1.isEmpty() && !token.hasHigherPriority(S1.peek())) { + S2.push(S1.pop()); + } + S1.push(token); + } + } + while(!S1.isEmpty()){ + S2.push(S1.pop()); + } + ArrayList list = new ArrayList<>(); + StackUtil.reverse(S2); + while(!S2.isEmpty()){ + list.add(S2.pop()); + } + return list; + } +} diff --git a/group23/632678665/com/basic/week7/stack/expr/InfixToPostExprTest.java b/group23/632678665/com/basic/week7/stack/expr/InfixToPostExprTest.java new file mode 100644 index 0000000000..d21344ea1e --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/InfixToPostExprTest.java @@ -0,0 +1,30 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixToPostExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + //10-2*3+50 + String string = "10-2*3+50"; + List tokens = InfixToPostExpr.convert(string); + + Assert.assertEquals(10, tokens.get(0).getValue()); + Assert.assertEquals(2, tokens.get(1).getValue()); + Assert.assertEquals(3, tokens.get(2).getValue()); + Assert.assertEquals("*", tokens.get(3).toString()); + Assert.assertEquals("-", tokens.get(4).toString()); + Assert.assertEquals(50, tokens.get(5).getValue()); + Assert.assertEquals("+", tokens.get(6).toString()); + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/PostfixExpr.java b/group23/632678665/com/basic/week7/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..6e40dbe72f --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/PostfixExpr.java @@ -0,0 +1,48 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class PostfixExpr { + + private String exprString; + + public PostfixExpr(String exprString){ + this.exprString = exprString; + } + + public float evaluate() { + MyStack myStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(exprString); + for(Token token : tokens){ + if (token.isNumber()) { + myStack.push(new Float(token.getValue())); + } + if (token.isOperator()) { + float f2 = myStack.pop(); + float f1 = myStack.pop(); + myStack.push(calculate(token.toString(), f1, f2)); + } + } + return myStack.pop().floatValue(); + } + + private Float calculate(String op, Float f1, Float f2){ + if(op.equals("+")){ + return f1+f2; + } + if(op.equals("-")){ + return f1-f2; + } + if(op.equals("*")){ + return f1*f2; + } + if(op.equals("/")){ + return f1/f2; + } + throw new RuntimeException(op + " is not supported"); + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/PostfixExprTest.java b/group23/632678665/com/basic/week7/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..d5ff875c0f --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/PostfixExprTest.java @@ -0,0 +1,34 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PostfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + { + 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/group23/632678665/com/basic/week7/stack/expr/PrefixExpr.java b/group23/632678665/com/basic/week7/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..651889259e --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/PrefixExpr.java @@ -0,0 +1,59 @@ +package com.ralf.stack.expr; + +import java.util.List; + +import com.ralf.stack.MyStack; + +public class PrefixExpr { + + private String exprString; + + public PrefixExpr(String exprString) { + this.exprString = exprString; + } + + public float evaluate() { + + MyStack myStack = new MyStack<>(); + MyStack exprStack = new MyStack<>(); + TokenParser parser = new TokenParser(); + List tokens = parser.parse(exprString); + + for(Token token : tokens){ + exprStack.push(token); + } + + while(!exprStack.isEmpty()){ + Token token = exprStack.pop(); + if (token.isNumber()) { + myStack.push(new Float(token.getValue())); + } + else { + Float f1 = myStack.pop(); + Float f2 = myStack.pop(); + myStack.push(calculate(token.toString(),f1,f2)); + } + } + return myStack.pop().floatValue(); + } + + private Float calculate(String operator, Float f1, Float f2) { + if ("+".equals(operator)) { + return f1 + f2; + } + if ("-".equals(operator)) { + return f1 - f2; + } + if ("*".equals(operator)) { + return f1 * f2; + } + if ("/".equals(operator)) { + return f1 / f2; + } + else { + throw new RuntimeException("this operator is not supported!"); + } + + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/PrefixExprTest.java b/group23/632678665/com/basic/week7/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..ff11cc2395 --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/PrefixExprTest.java @@ -0,0 +1,39 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PrefixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + { + // 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/group23/632678665/com/basic/week7/stack/expr/Token.java b/group23/632678665/com/basic/week7/stack/expr/Token.java new file mode 100644 index 0000000000..1696dafbef --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/Token.java @@ -0,0 +1,49 @@ +package com.ralf.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 NUMBER = 1; + static final int OPERATOR = 2; + String value; + int type; + + public Token(String value, int type){ + this.value = value; + this.type = type; + } + public int getValue() { + + return Integer.valueOf(value).intValue(); + } + public String toString(){ + return value; + } + public boolean isNumber(){ + return type == NUMBER; + } + public boolean isOperator(){ + return type == OPERATOR; + } + public boolean hasHigherPriority(Token token){ + + if (!this.isOperator() || !token.isOperator()) { + throw new RuntimeException("numbers can't compare priority"); + } + return priorities.get(this.value) - priorities.get(token.value) > 0; + + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/TokenParser.java b/group23/632678665/com/basic/week7/stack/expr/TokenParser.java new file mode 100644 index 0000000000..66206c9f11 --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/TokenParser.java @@ -0,0 +1,56 @@ +package com.ralf.stack.expr; + +import java.util.ArrayList; +import java.util.List; + +public class TokenParser { + + public TokenParser(){ + + } + public List parse(String string) { + List tokens = new ArrayList(); + int i = 0; + while(i < string.length()){ + + char ch = string.charAt(i); + if (isOperator(ch)) { + Token token = new Token(String.valueOf(ch), Token.OPERATOR); + tokens.add(token); + i++; + } + else if (Character.isDigit(ch)) { + int nextIndexOfChar = nextIndexOfOperator(i,string); + String value = string.substring(i, nextIndexOfChar); + Token token = new Token(value, Token.NUMBER); + tokens.add(token); + i = nextIndexOfChar; + } + else { + System.out.println("char:" + ch + " is not a number or operator,ignore!"); + i++; + } + + } + + + return tokens; + } + + private int nextIndexOfOperator(int i, String string) { + + while(Character.isDigit(string.charAt(i))){ + i++; + if (i == string.length()) { + break; + } + } + return i; + } + + private boolean isOperator(char ch) { + String string = String.valueOf(ch); + return Token.OPERATORS.contains(string); + } + +} diff --git a/group23/632678665/com/basic/week7/stack/expr/TokenParserTest.java b/group23/632678665/com/basic/week7/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..3066880551 --- /dev/null +++ b/group23/632678665/com/basic/week7/stack/expr/TokenParserTest.java @@ -0,0 +1,36 @@ +package com.ralf.stack.expr; + +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TokenParserTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + TokenParser tokenParser = new TokenParser(); + + List list = tokenParser.parse("300*20+12*5-20/4"); + Assert.assertEquals(300, list.get(0).getValue()); + Assert.assertEquals("*", list.get(1).toString()); + Assert.assertEquals(20, list.get(2).getValue()); + Assert.assertEquals("+", list.get(3).toString()); + Assert.assertEquals(12, list.get(4).getValue()); + Assert.assertEquals("*", list.get(5).toString()); + Assert.assertEquals(5, list.get(6).getValue()); + Assert.assertEquals("-", list.get(7).toString()); + Assert.assertEquals(20, list.get(8).getValue()); + Assert.assertEquals("/", list.get(9).toString()); + Assert.assertEquals(4, list.get(10).getValue()); + + } + +} diff --git a/group23/632678665/com/basic/week8/CircleQueue.java b/group23/632678665/com/basic/week8/CircleQueue.java new file mode 100644 index 0000000000..1a6f022a4e --- /dev/null +++ b/group23/632678665/com/basic/week8/CircleQueue.java @@ -0,0 +1,44 @@ +/** + * @author chk + */ +public class CircleQueue{ + + private int size; + private int first; + private int last; + Object[] queue; + + public CircleQueue(int size){ + queue = new Object[size]; + first = 0; + last = 0; + } + + public boolean isEmpty(){ + return first == last; + } + + public void enCircleQueue(Object o){ + if( (last+1) % size == first){ + System.out.println("Circle Queue is full"); + }else { + queue[last] = o; + last = (last+1) % queue.length; + } + } + + public int getSize(){ + return (last - first + queue.length) % queue.length; + } + + public Object deCircleQueue(){ + if(isEmpty()){ + return null; + }else{ + Object item = queue[first]; + first = (first+1)%queue.length; + return item; + } + + } +} diff --git a/group23/632678665/com/basic/week8/Josephus.java b/group23/632678665/com/basic/week8/Josephus.java new file mode 100644 index 0000000000..e3380c0ca6 --- /dev/null +++ b/group23/632678665/com/basic/week8/Josephus.java @@ -0,0 +1,44 @@ + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * @author chk + * + */ +public class Josephus { + + private static class Node { + int data; + Node next; + + public Node(int i) { + data = i; + } + } + + public static void execute(int n, int m) { + + Node header = new Node(0); + Node pointer = header; + for (int i = 1; i < n; i++) { + pointer.next = new Node(i); + pointer = pointer.next; + } + pointer.next = header; + while (pointer != pointer.next) { + for (int i = 1; i <= m; i++) { + pointer = pointer.next; + } + System.out.println(pointer.next.data); + pointer.next = pointer.next.next; + } + System.out.println(pointer.next.data); + + } + public static void main(String args[]){ + Josephus circle = new Josephus(); + circle.execute(8,4); + } +} diff --git a/group23/632678665/com/basic/week8/Queue.java b/group23/632678665/com/basic/week8/Queue.java new file mode 100644 index 0000000000..ea0e0cd621 --- /dev/null +++ b/group23/632678665/com/basic/week8/Queue.java @@ -0,0 +1,55 @@ +import javax.xml.soap.Node; +import java.util.NoSuchElementException; + +/** + * @author chk + */ +public class Queue { + + 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 is empty"); + }else{ + E item = first.item; + first = first.next; + size--; + if(isEmpty()){ + last = null; + } + return item; + } + } + + +} diff --git a/group23/632678665/com/basic/week8/QueueWithTwoStacks.java b/group23/632678665/com/basic/week8/QueueWithTwoStacks.java new file mode 100644 index 0000000000..af5d8a03df --- /dev/null +++ b/group23/632678665/com/basic/week8/QueueWithTwoStacks.java @@ -0,0 +1,47 @@ +import java.util.Stack; + +/** + * @author chk + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + public QueueWithTwoStacks(){ + stackk = new Stack(); + stackkk = new Stack(); + } + + public boolean isEmpty(){ + return stackk.isEmpty() && stackkk.isEmpty(); + } + + public int size() + { + return stackk.size() + stack2.size(); + } + + public void enQueue(E item){ + + stackk.push(item); + } + + public E deQueue(){ + if(stackkk.isEmpty()){ + while(!stackk.isEmpty()){ + stackkk.push(stackk.pop()); + } + } + return stackkk.pop(); + } + public static void main(String args[]){ + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + queue.enQueue(1); + queue.enQueue(5); + queue.enQueue(4); + queue.enQueue(0); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + System.out.println(queue.deQueue()); + } +} diff --git a/group23/632678665/com/basic/week9/QuickMinStack.java b/group23/632678665/com/basic/week9/QuickMinStack.java new file mode 100644 index 0000000000..bac723e3f1 --- /dev/null +++ b/group23/632678665/com/basic/week9/QuickMinStack.java @@ -0,0 +1,48 @@ + + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author chk + * + */ +public class QuickMinStack extends Stack { + + Stack sMin; + public QuickMinStack(){ + sMin = new Stack(); + } + public void push(int data){ + if(data <= findMin()){ + sMin.push(data); + } + super.push(data); + } + public Integer pop(){ + int value = super.pop(); + if(value == findMin()){ + sMin.pop(); + } + return value; + } + public int findMin(){ + if(sMin.isEmpty()){ + return Integer.MAX_VALUE; + } + return sMin.peek(); + } + + public static void main(String args[]){ + QuickMinStack stack = new QuickMinStack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(0); + System.out.println(stack.pop().intValue()); + System.out.println(stack.findMin()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + } +} diff --git a/group23/632678665/com/basic/week9/StackWithTwoQueues.java b/group23/632678665/com/basic/week9/StackWithTwoQueues.java new file mode 100644 index 0000000000..7fcf9162c9 --- /dev/null +++ b/group23/632678665/com/basic/week9/StackWithTwoQueues.java @@ -0,0 +1,53 @@ +package com.basic.week9; +import java.util.LinkedList; + + +/** + * @author chk + */ +public class StackWithTwoQueues { + + LinkedList queue1=new LinkedList(); + LinkedList queue2=new LinkedList(); + public void push(int data){ + queue1.addLast(data); + } + public int pop() { + if (sSize() > 0) { + if (!queue1.isEmpty()) { + while (queue1.size() > 1) { + queue2.addLast(queue1.removeFirst()); + } + return queue1.removeFirst(); + } else { + while (queue2.size() > 1) { + queue1.addLast(queue2.removeFirst()); + } + return queue2.removeFirst(); + } + } else { + System.out.println("栈空,不能出栈"); + return Integer.MAX_VALUE; + } + } + public int sSize(){ + return queue1.size() + queue2.size(); + } + public static void main(String[] args) + { + StackWithTwoQueues stack=new StackWithTwoQueues(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + stack.push(5); + stack.push(6); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + System.out.println(stack.pop()); + } +} diff --git a/group23/632678665/com/basic/week9/TwoStackInOneArray.java b/group23/632678665/com/basic/week9/TwoStackInOneArray.java new file mode 100644 index 0000000000..5443e6d6e4 --- /dev/null +++ b/group23/632678665/com/basic/week9/TwoStackInOneArray.java @@ -0,0 +1,82 @@ +package com.basic.week9; +import java.util.Stack; + +/** + * @author chk + */ +public class TwoStackInOneArray { + + + + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2 = data.length - 1; + + + private boolean isFull() { + if (index1 == index2) { + return true; + } else + return false; + } + + private void extendCapacity() { + + } + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + return null; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + return null; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + return null; + } + +} diff --git a/group23/729693763/First_Homework1/.classpath b/group23/729693763/First_Homework1/.classpath deleted file mode 100644 index 373dce4005..0000000000 --- a/group23/729693763/First_Homework1/.classpath +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/group23/729693763/First_Homework1/.project b/group23/729693763/First_Homework1/.project deleted file mode 100644 index 5022bfb83c..0000000000 --- a/group23/729693763/First_Homework1/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - First_Homework1 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/group23/729693763/First_Homework1/.settings/org.eclipse.core.resources.prefs b/group23/729693763/First_Homework1/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 99f26c0203..0000000000 --- a/group23/729693763/First_Homework1/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/group23/729693763/First_Homework1/.settings/org.eclipse.jdt.core.prefs b/group23/729693763/First_Homework1/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 3a21537071..0000000000 --- a/group23/729693763/First_Homework1/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,11 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/group23/729693763/Second_Homework2/.classpath b/group23/729693763/Second_Homework2/.classpath deleted file mode 100644 index aa7b00d27d..0000000000 --- a/group23/729693763/Second_Homework2/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/group23/729693763/Second_Homework2/.project b/group23/729693763/Second_Homework2/.project deleted file mode 100644 index fb7175dae6..0000000000 --- a/group23/729693763/Second_Homework2/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - Second_Homework2 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/group23/729693763/Second_Homework2/.settings/org.eclipse.jdt.core.prefs b/group23/729693763/Second_Homework2/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 3a21537071..0000000000 --- a/group23/729693763/Second_Homework2/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,11 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/group23/729693763/Second_Homework2/xmlFolder/struts.xml b/group23/729693763/Second_Homework2/xmlFolder/struts.xml deleted file mode 100644 index 8a788e9b1f..0000000000 --- a/group23/729693763/Second_Homework2/xmlFolder/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/729693763/Third_Homework3/DataStruct/Iterator.java b/group23/729693763/Third_Homework3/DataStruct/Iterator.java new file mode 100644 index 0000000000..2ca354f82a --- /dev/null +++ b/group23/729693763/Third_Homework3/DataStruct/Iterator.java @@ -0,0 +1,6 @@ +package com.zhous.DataStruct; + +public interface Iterator { + public boolean hasNext(); + public Object next(); +} diff --git a/group23/729693763/Third_Homework3/DataStruct/LinkedList.java b/group23/729693763/Third_Homework3/DataStruct/LinkedList.java new file mode 100644 index 0000000000..2a6663a3ba --- /dev/null +++ b/group23/729693763/Third_Homework3/DataStruct/LinkedList.java @@ -0,0 +1,327 @@ +package com.zhous.DataStruct; + +import javafx.beans.binding.ObjectExpression; + + + +public class LinkedList implements List { + + private Node head = null; + private int size = 0; + + public void add(Object o){ + addLast(o); + this.size++; + } + + //内部调用的方法: + //2 返回添加到哪个Node + private Node findBeforeInsertNode(int needInsertIndex){ + Node findGetNode = this.head; + for ( int i=0; i< needInsertIndex - 1; i++ ) { + findGetNode = findGetNode.next; + } + return findGetNode; + } + //3 + private void checkPositionIndex(int index) { + if ( !( index >= 0 && index <= size ) ) + throw new IndexOutOfBoundsException("Invalid Index:"+index); + } + + //4 + private void addBeforeNode(int index, Object o) { + Node newNode = new Node(); + newNode.data = o; + newNode.next = null; + + Node beforeInserNode = this.head; + + + beforeInserNode = findBeforeInsertNode(index); + + newNode.next = beforeInserNode.next; + beforeInserNode.next = newNode; + + } + //5 + private Node findIndexNode(int index){ + Node findGetNode = this.head; + for ( int i=0; i< index; i++ ) { + findGetNode = findGetNode.next; + } + return findGetNode; + } + + + public void add(int index , Object o){ + checkPositionIndex(index); + if( index == size()){ + addLast(o); + } else if ( index == 0 ) { + addFirst(o); + } else{ + addBeforeNode(index,o); + } + this.size++; + } + + + + + public Object get(int index){ + checkElementIndex(index); + return findIndexNode(index); + } + public Object remove(int index){ + checkElementIndex(index); + Object deleteData = null; + + if(index == 0){ + deleteData = removeFirst(); + } else if(index == (size() - 1) ){ + deleteData = removeLast(); + } else { + Node temp = findBeforeInsertNode(index); + Node tempNext = temp.next; + deleteData = tempNext.data; + + temp.next = tempNext.next; + tempNext = null; + } + + return deleteData; + } + + //6 + private void checkElementIndex(int index) { + if ( !( index >= 0 && index < size ) ) + throw new IndexOutOfBoundsException("Invalid Index:"+index); + } + + public int size(){ + return this.size; + } + + public void addFirst(Object o){ + Node newNode = new Node(); + newNode.data = o; + newNode.next = null; + if ( this.head == null ) { + this.head = newNode; + } else { + newNode.next = this.head; + this.head = newNode; + } + } + private void addLast(Object o){ + Node newNode = new Node(); + newNode.data = o; + newNode.next = null; + if ( head == null ) { + head = newNode; + } else{ + findBeforeInsertNode(this.size).next = newNode; + } + } + public Object removeFirst(){ + Object data; + Node newHead = new Node(); + newHead = this.head; + this.head = newHead.next; + + data = newHead.data; + newHead = null; + return data; + } + public Object removeLast(){ + Object data; + Node last = findIndexNode(this.size() -1); + data = last.data; + last = null; + + return data; + } + public Iterator iterator() + { + return new LinkedListIterator(); + } + + + private static class Node{ + Object data; + Node next; + + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node first ; + int currentIndex = 1; + this.head = findIndexNode(this.size - 1); + if(this.size() <= 1){ + return; + } + while(currentIndex < this.size() ){ + first = findIndexNode(this.size() - currentIndex); + first.next = findIndexNode(this.size - currentIndex - 1); + currentIndex++; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + checkElementIndex(this.size()); + + int mid = this.size / 2; + Node temp = this.head; + this.head = findIndexNode(mid); + for (int i = 0; i < mid; i++) { + Node T = temp.next; + temp = null; + temp = T; + } + + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param index + * @param length + */ + public void remove(int index, int length){ + checkElementIndex(length + index ); + + Node before = findBeforeInsertNode(index); + Node temp = findIndexNode(index); + for (int i= 0; i < length; i++) { + Node T = temp.next; + temp = null; + temp = T; + } + before.next = temp; + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + Node listNode = list.head; + Node myNode = this.head; + int[] data = new int[list.size()]; + for (int i = 0; i < this.size(); i++) { + if(i == (Integer) listNode.data){ + data[i] = (Integer)myNode.data; + } + myNode = myNode.next; + } + + return data; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + + int[] data = new int[list.size()]; + for (int i = 0,j = 0; i < this.size(); i++) { + for (; j < list.size(); j++) { + if(this.get(i).equals(list.get(j))){ + this.remove(i); + break; + } + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + * (选做) + */ + public void removeDuplicateValues(){ + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + * (选做) + */ + public void removeRange(int min, int max){ + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + LinkedList listC = new LinkedList(); + + for (int i = 0,j = 0; i < this.size(); i++) { + for (; j < list.size(); j++) { + if(this.get(i).equals(list.get(j))){ + listC.add(this.get(i)); + break; + } + } + } + + + + return listC; + } + + + + /************Iterator**************/ + private class LinkedListIterator implements Iterator{ + private Node currentNode; + private int currentIndex; + + public LinkedListIterator() { + // TODO Auto-generated constructor stub + this.currentIndex = 0; + this.currentNode = new Node(); + } + @Override + public boolean hasNext() { + // TODO Auto-generated method stub + return currentIndex < size(); + } + + @Override + public Object next() { + // TODO Auto-generated method stub + checkElementIndex(currentIndex); + if ( currentNode.data == null ) { + this.currentNode = findIndexNode(currentIndex); + } + Object value = currentNode.data; + currentNode = currentNode.next; + currentIndex++; + return value; + } + } +} diff --git a/group23/729693763/Third_Homework3/DataStruct/List.java b/group23/729693763/Third_Homework3/DataStruct/List.java new file mode 100644 index 0000000000..aa8b039453 --- /dev/null +++ b/group23/729693763/Third_Homework3/DataStruct/List.java @@ -0,0 +1,10 @@ +package com.zhous.DataStruct; + +public interface List { + void add(Object o); + void add(int index, Object o); + Object get(int index); + Object remove(int index); + int size(); + Iterator iterator(); +} diff --git a/group23/729693763/Third_Homework3/download/DownloadThread.java b/group23/729693763/Third_Homework3/download/DownloadThread.java new file mode 100644 index 0000000000..3ab337e352 --- /dev/null +++ b/group23/729693763/Third_Homework3/download/DownloadThread.java @@ -0,0 +1,49 @@ +package com.zhous.download; + +import com.zhous.download.api.Connection; +import com.zhous.download.api.DownloadListener; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + File targetFile; + DownloadListener downloadListener; + + public DownloadThread( Connection conn, int startPos, int endPos,File targetFile,DownloadListener downloadListener){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.targetFile = targetFile; + this.downloadListener = downloadListener; + } + public void run(){ + try { + //读取到指定长度的二进制数据 + System.out.println(this.getName()+"开始下载"); + byte[] data = conn.read(startPos,endPos); + + //插入的file中去 + RandomAccessFile raFile = new RandomAccessFile(this.targetFile,"rw"); + raFile.seek(startPos); + raFile.write(data,0,endPos-startPos ); + + raFile.close(); + //做完了 + if(FileDownloader.isDownloadFinish() ){ + downloadListener.notifyFinished(); + System.out.println(this.getName()+"完成最后的下载,并写入文件"); + } + + + }catch (IOException e){ + + } + } +} diff --git a/group23/729693763/Third_Homework3/download/FileDownloader.java b/group23/729693763/Third_Homework3/download/FileDownloader.java new file mode 100644 index 0000000000..098f9408f0 --- /dev/null +++ b/group23/729693763/Third_Homework3/download/FileDownloader.java @@ -0,0 +1,96 @@ +package com.zhous.download; + +import com.zhous.download.api.Connection; +import com.zhous.download.api.ConnectionException; +import com.zhous.download.api.ConnectionManager; +import com.zhous.download.api.DownloadListener; + +import java.io.File; +import java.util.Set; + + +public class FileDownloader { + + String url="https://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=https%3A%2F%2Ftimgsa.baidu.com%2Ftimg%3Fimage%26quality%3D80%26size%3Db9999_10000%26sec%3D1490203615530%26di%3D2b1827956a01011d3634f3e04b01b15c%26imgtype%3D0%26src%3Dhttp%253A%252F%252Fimg15.3lian.com%252F2015%252Fh1%252F338%252Fd%252F157.jpg&thumburl=https%3A%2F%2Fss1.bdstatic.com%2F70cFvXSh_Q1YnxGkpoWK1HF6hhy%2Fit%2Fu%3D2613489365%2C2336631324%26fm%3D23%26gp%3D0.jpg"; + private static int threadNum = 5; + private static int threadCount = 0; + int avgBytes = 0; + + DownloadListener listener; + ConnectionManager cm; + File file = null; + + public FileDownloader(String _url,String fileName) { + this.url = _url; + this.file = new File(fileName); + } + + public void execute(){ + // 在这里实现你的代码, 注意: 需要用多线程实现下载 + // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + // (1) ConnectionManager , 可以打开一个连接,通过Connection可以读取其中的一段(用startPos, endPos来指定) + // (2) DownloadListener, 由于是多线程下载, 调用这个类的客户端不知道什么时候结束,所以你需要实现当所有 + // 线程都执行完以后, 调用listener的notifiedFinished方法, 这样客户端就能收到通知。 + // 具体的实现思路: + // 1. 需要调用ConnectionManager的open方法打开连接, 然后通过Connection.getContentLength方法获得文件的长度 + // 2. 至少启动3个线程下载, 注意每个线程需要先调用ConnectionManager的open方法 + // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 + // 3. 把byte数组写入到文件中 + // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + Connection conn = null; + try { + + conn = cm.open(this.url); + int length = conn.getContentLength(); + avgBytes = length / threadNum; + //使用5个线程去下载; + for (int i = 0; i < threadNum; i++) { + int startPos = i*avgBytes; + int endPos = startPos + avgBytes - 1; + if(i == threadNum -1) { + endPos = length; + } + + Connection c = cm.open(this.url); + DownloadThread thread = new DownloadThread(c,startPos,endPos,file,this.getListener()); + thread.setName("Thread"+(i+1) ); + thread.start(); + } + + } catch (ConnectionException e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + + + + } + + + + public void setListener (DownloadListener listener){ + this.listener = listener; + } + + public synchronized static boolean isDownloadFinish(){ + threadCount++; + return threadCount == threadNum; + } + + + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + +} diff --git a/group23/729693763/Third_Homework3/download/FileDownloaderTest.java b/group23/729693763/Third_Homework3/download/FileDownloaderTest.java new file mode 100644 index 0000000000..ca8817ba88 --- /dev/null +++ b/group23/729693763/Third_Homework3/download/FileDownloaderTest.java @@ -0,0 +1,58 @@ +package com.zhous.download; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.zhous.download.api.ConnectionManager; +import com.zhous.download.api.DownloadListener; +import com.zhous.download.impl.ConnectionManagerImpl; + +public class FileDownloaderTest { + boolean downloadFinished = false; + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + String url="http://www.mydeskcity.com//upload/pc/112/960x600/1351650816239.jpg"; + String github = "https://github.com/em14Vito/coding2017/archive/master.zip"; + +// FileDownloader downloader = new FileDownloader(url,"Data23.jpg"); + FileDownloader downloader = new FileDownloader(github,"github.zip"); + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + downloader.execute(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + + + + } + +} diff --git a/group23/729693763/Third_Homework3/download/api/Connection.java b/group23/729693763/Third_Homework3/download/api/Connection.java new file mode 100644 index 0000000000..170791e8ba --- /dev/null +++ b/group23/729693763/Third_Homework3/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.zhous.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + public byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + public int getContentLength(); + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group23/729693763/Third_Homework3/download/api/ConnectionException.java b/group23/729693763/Third_Homework3/download/api/ConnectionException.java new file mode 100644 index 0000000000..925368135d --- /dev/null +++ b/group23/729693763/Third_Homework3/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.zhous.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group23/729693763/Third_Homework3/download/api/ConnectionManager.java b/group23/729693763/Third_Homework3/download/api/ConnectionManager.java new file mode 100644 index 0000000000..b331ee7f1f --- /dev/null +++ b/group23/729693763/Third_Homework3/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.zhous.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group23/729693763/Third_Homework3/download/api/DownloadListener.java b/group23/729693763/Third_Homework3/download/api/DownloadListener.java new file mode 100644 index 0000000000..07b1a950ce --- /dev/null +++ b/group23/729693763/Third_Homework3/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.zhous.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group23/729693763/Third_Homework3/download/impl/ConnectionImpl.java b/group23/729693763/Third_Homework3/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..6a4b98fe06 --- /dev/null +++ b/group23/729693763/Third_Homework3/download/impl/ConnectionImpl.java @@ -0,0 +1,80 @@ +package com.zhous.download.impl; + +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + +import com.zhous.download.api.*; + +public class ConnectionImpl implements Connection{ + + + InputStream is = null; + URL url = null; + HttpURLConnection http = null; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + //构造方法: + public ConnectionImpl() { + } + + //打开url并且创建连接 + public ConnectionImpl(String url) { + try { + this.url = new URL(url); + http = (HttpURLConnection) this.url.openConnection(); + //设置超时 + http.setConnectTimeout(5000); + http.setReadTimeout(5000); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + //指定http中读取一定长度的byte + http.setRequestProperty("Range","bytes= "+Integer.toString(startPos)+"-"+Integer.toString(endPos)); + http.connect(); + + //读取输入流到其中 + is = http.getInputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while( (len = is.read(buffer) ) != -1) { + + bos.write(buffer, 0, len); + } + + //关闭所有流,每次read的时候自动关闭。 + close(); + return bos.toByteArray(); + } + + @Override + public int getContentLength() { + return http.getContentLength(); + } + + @Override + public void close() { + try { + bos.close(); + if(is != null) { + is.close(); + } + http.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + System.out.println(e.getMessage()); + } + } + +} diff --git a/group23/729693763/Third_Homework3/download/impl/ConnectionManagerImpl.java b/group23/729693763/Third_Homework3/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..28af08a0cd --- /dev/null +++ b/group23/729693763/Third_Homework3/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,27 @@ +package com.zhous.download.impl; + +import com.zhous.download.api.*; + +import java.net.MalformedURLException; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + + + @Override + public Connection open(String url) throws ConnectionException { + Connection ct = null; + URL u = null; + try { + u = new URL(url); + ct = new ConnectionImpl(url); + } catch (MalformedURLException e) { + e.printStackTrace(); + } finally { + //URL类不需要关闭 + } + return ct; + } + +} diff --git a/group23/729693763/readme.md b/group23/729693763/readme.md index 7e7fac06ae..89b8633e07 100644 --- a/group23/729693763/readme.md +++ b/group23/729693763/readme.md @@ -8,4 +8,5 @@ http://www.cnblogs.com/CodeSaveMe/p/6523745.html Add Blog link: http://www.cnblogs.com/CodeSaveMe/p/6523745.html Add week2 Blog link:http://www.cnblogs.com/CodeSaveMe/p/6571621.html ->>>>>>> my + +Add week3 Blog link:http://www.cnblogs.com/CodeSaveMe/p/6624431.html diff --git a/group23/769232552/coding/pom.xml b/group23/769232552/coding/pom.xml deleted file mode 100644 index 5b9701ed4d..0000000000 --- a/group23/769232552/coding/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - - com.coding - coding2017 - 1.0-SNAPSHOT - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - - - - - - - - ch.qos.logback - logback-classic - 1.1.1 - - - dom4j - dom4j - 1.6.1 - - - junit - junit - 4.12 - test - - - commons-lang - commons-lang - 2.6 - - - - \ No newline at end of file diff --git a/group23/769232552/coding/src/main/java/code03/impl/ConnectionImpl.java b/group23/769232552/coding/src/main/java/code03/impl/ConnectionImpl.java index 069f21625b..ce69eceb99 100644 --- a/group23/769232552/coding/src/main/java/code03/impl/ConnectionImpl.java +++ b/group23/769232552/coding/src/main/java/code03/impl/ConnectionImpl.java @@ -36,7 +36,6 @@ public byte[] read(int startPos, int endPos) throws IOException { InputStream raw = null; BufferedInputStream in = null; int size = endPos - startPos + 1; - byte[] data = new byte[size]; try{ raw = urlConnection.getInputStream(); diff --git a/group23/769232552/coding/src/main/java/code04/LRUPageFrame.java b/group23/769232552/coding/src/main/java/code04/LRUPageFrame.java new file mode 100644 index 0000000000..0ffce58b83 --- /dev/null +++ b/group23/769232552/coding/src/main/java/code04/LRUPageFrame.java @@ -0,0 +1,162 @@ +package code04; + +/** + * 用双向链表实现LRU算法 + */ +public class LRUPageFrame { + + private class Node { + + Node prev; + Node next; + int pageNum; + Node() { + } + } + + private int size; + private int capacity; + + private Node first;// 链表头 + private Node last;// 链表尾 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + this.size = 0; + } + + /** + * 获取缓存中对象 + * 1、如果缓存中不存在,则直接加入表头 + * 2、如果缓存中存在,则把该对象移动到表头 + * @param pageNum + * @return + */ + public void access(int pageNum) { + Node node = hasContains(pageNum); + if(node != null){ + moveToHead(node); + }else { + addToHead(pageNum); + } + + } + + /** + * 对象是否存在缓存中,如存在则返回该对象在链表中的位置,否则返回null + * @return + */ + private Node hasContains(int key){ + Node node = this.first; + while (node != null){ + if(node.pageNum == key){ + return node; + } + node = node.next; + } + return node; + } + + /** + * 对象加入表头,先先判断缓存是否已经满了 + * @return + */ + private void addToHead(int key){ + Node node = new Node(); + node.pageNum = key; + if(size < capacity){ + addFirst(node); + }else { + removeLast(); + addFirst(node); + } + + } + + + /** + * 对象移动到表头 + * @return + */ + private void moveToHead(Node node){ + if(node == first){ + return; + } + if(node == last){ + node.next = first; + first.prev = node; + first = node; + last = node.prev; + last.next = null; + node.prev = null; + return; + } + node.prev.next = node.next; + node.next.prev = node.prev; + node.next = first; + node.prev = null; + first.prev = node; + first = node; + } + + /** + * 删除表尾 + * @return + */ + private void removeLast(){ + if(last != null){ + Node newLast = last.prev; + last.prev = null; + last = newLast; + last.next = null; + size --; + } + } + /** + * 添加元素到表头 + * @return + */ + private void addFirst(Node node){ + //0个节点 + if(first == null){ + first = node; + last = node; + size ++; + return; + } + //一个节点 + else if(first == last){ + first = node; + first.next = last; + last.prev = first; + size ++; + return; + }else { + node.next = first; + first.prev = node; + first = node; + size ++; + } + } + /** + * 当前链表空间 + * @return + */ + public int getSize() { + return size; + } + + 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/group23/769232552/coding/src/main/java/mini_jvm/loader/ClassFileLoader.java b/group23/769232552/coding/src/main/java/mini_jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..81e6973856 --- /dev/null +++ b/group23/769232552/coding/src/main/java/mini_jvm/loader/ClassFileLoader.java @@ -0,0 +1,108 @@ +package mini_jvm.loader; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + /** + * 读取class文件的二进制代码 + * @param className + * @return + */ + public byte[] readBinaryCode(String className) { + String clazzPath = getClassPath(className); + BufferedInputStream bins = null; + ByteArrayOutputStream bouts = new ByteArrayOutputStream(); + try { + bins = new BufferedInputStream(new FileInputStream(new File(clazzPath))); + byte[] buffer = new byte[1024]; + int length = -1; + while((length = bins.read(buffer)) != -1){ + bouts.write(buffer, 0, length); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + byte[] codes = bouts.toByteArray(); + //关闭流 + try { + if(bins != null){ + //调用外层流的close方法就关闭其装饰的内层流 + bins.close(); + } + if(bouts != null){ + bouts.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return codes; + } + + /** + * 从扫描根目录,获取指定类的绝对路径 + * @param className + * @return + */ + private String getClassPath(String className){ + String clazzPath = null; + //遍历clzPaths中所有路径 + for (String path : this.clzPaths){ + File file = new File(path); + clazzPath = getClassPath(className,file); + if(clazzPath!=null) break; + } + return clazzPath; + } + + private String getClassPath(String className, File file){ + String clazzPath = null; + if(file.exists()){ + //如果是目录,则遍历所有目录下的文件 + if(file.isDirectory()){ + File[] fs = file.listFiles(); + for (File f : fs){ + clazzPath = getClassPath(className,f); + } + }else { + //检查是否是该类对应的class文件 + if(isClazzFile(file.getName(),className)){ + clazzPath = file.getAbsolutePath(); + } + } + } + return clazzPath; + } + + private boolean isClazzFile(String filename , String className){ + String fileClazzName = null; + String [] names = filename.split("\\."); + if(names.length > 0){ + fileClazzName = names[0]; + } + return className.endsWith(fileClazzName); + } + + public void addClassPath(String path) { + clzPaths.add(path); + } + + public String getClassPath(){ + StringBuilder sb = new StringBuilder(); + int i = 0; + for (; i < clzPaths.size() - 1; i++) { + sb.append(clzPaths.get(i)); + sb.append(";"); + } + sb.append(clzPaths.get(i)); + return sb.toString(); + } +} diff --git a/group23/769232552/coding/src/main/resources/struts.xml b/group23/769232552/coding/src/main/resources/struts.xml deleted file mode 100644 index fd71dc16ff..0000000000 --- a/group23/769232552/coding/src/main/resources/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - \ No newline at end of file diff --git a/group23/769232552/coding/src/test/java/code04/LRUPageFrameTest.java b/group23/769232552/coding/src/test/java/code04/LRUPageFrameTest.java new file mode 100644 index 0000000000..7448e3ee56 --- /dev/null +++ b/group23/769232552/coding/src/test/java/code04/LRUPageFrameTest.java @@ -0,0 +1,38 @@ +package code04; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + //1,0,7 + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + //2,1,0 + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + //0,2,1 + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + //0,2,1 + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + //3,0,2 + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + //0,3,2 + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + //4,0,3 + Assert.assertEquals("4,0,3", frame.toString()); + } + +} diff --git a/group23/769232552/coding/src/test/java/mini_jvm/ClassFileloaderTest.java b/group23/769232552/coding/src/test/java/mini_jvm/ClassFileloaderTest.java new file mode 100644 index 0000000000..9602743b02 --- /dev/null +++ b/group23/769232552/coding/src/test/java/mini_jvm/ClassFileloaderTest.java @@ -0,0 +1,71 @@ +package mini_jvm; + +import mini_jvm.loader.ClassFileLoader; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ClassFileloaderTest { + + + static String path1 = "D:\\worksapce\\gitRepo\\java_coding2017\\coding2017\\group23\\769232552\\coding\\target\\classes"; + static String path2 = "D:\\worksapce\\gitRepo\\java_coding2017\\coding2017\\group23\\769232552\\coding\\target\\test-classes"; + + + ClassFileLoader loader = new ClassFileLoader(); + + @Before + public void setUp() throws Exception { + loader.addClassPath(path1); + loader.addClassPath(path2); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + String clzPath = loader.getClassPath(); + Assert.assertEquals(path1+";"+path2,clzPath); + } + + @Test + public void testClassFileLength() { + String className = "mini_jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + Assert.assertEquals(1026, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + String className = "mini_jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + 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 - - - - - diff --git a/group23/810181789/.gitignore b/group23/810181789/.gitignore deleted file mode 100644 index ae3c172604..0000000000 --- a/group23/810181789/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/group23/810181789/.project b/group23/810181789/.project deleted file mode 100644 index d78dba00af..0000000000 --- a/group23/810181789/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - basicstructure - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/group24/1148285693/.gitignore b/group24/1148285693/.gitignore deleted file mode 100644 index f41f37aecb..0000000000 --- a/group24/1148285693/.gitignore +++ /dev/null @@ -1,40 +0,0 @@ -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files -*.war -*.ear -*.bk -.gradle -target -*.class -*.real - -# virtual machine crash logs -# see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -# Eclipse Files # -.project -.classpath -.settings - -# Idea -*.iml -*.ipr -*.iws -.idea - -# log -*_IS_UNDEFINED -logs -*.log - -# other -*.bak -.directory -.DS_Store - - -Test.java -example \ No newline at end of file diff --git a/group24/1148285693/learning2017/.editorconfig b/group24/1148285693/learning2017/.editorconfig index 29c9408cf8..34072e9c8c 100644 --- a/group24/1148285693/learning2017/.editorconfig +++ b/group24/1148285693/learning2017/.editorconfig @@ -7,6 +7,8 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true indent_size = 4 +end_of_line = crlf +insert_final_newline = false [*.html] indent_size = 4 diff --git a/group24/1148285693/learning2017/.gitignore b/group24/1148285693/learning2017/.gitignore new file mode 100644 index 0000000000..556caf3bbd --- /dev/null +++ b/group24/1148285693/learning2017/.gitignore @@ -0,0 +1,39 @@ +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files +*.war +*.ear +*.bk +.gradle +target +*.class +*.real + +# virtual machine crash logs +# see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# Eclipse Files # +.project +.classpath +.settings + +# Idea +*.iml +*.ipr +*.iws +.idea + +# log +*_IS_UNDEFINED +logs +*.log + +# other +*.bak +.directory +.DS_Store + + +Test.java diff --git a/group24/1148285693/learning2017/common/pom.xml b/group24/1148285693/learning2017/common/pom.xml new file mode 100644 index 0000000000..61d8e45905 --- /dev/null +++ b/group24/1148285693/learning2017/common/pom.xml @@ -0,0 +1,16 @@ + + + + learning2017 + me.lzb + 1.0 + + 4.0.0 + + common + 1.0 + common + + \ No newline at end of file diff --git a/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/AppUtils.java b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/AppUtils.java new file mode 100644 index 0000000000..906c88e747 --- /dev/null +++ b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/AppUtils.java @@ -0,0 +1,22 @@ +package me.lzb.common.utils; + +/** + * Created by lzbfe on 2017/4/29. + */ +public class AppUtils { + + /** + * 获取一个数的位数 + * @param i + * @return + */ + public static int getDigit(int i) { + int a = i; + int c = 0; + while (a > 0) { + a = a / 10; + c++; + } + return c; + } +} diff --git a/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/StringUtils.java b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/StringUtils.java index 66f70d49f7..76e60a49b8 100644 --- a/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/StringUtils.java +++ b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/StringUtils.java @@ -5,4 +5,14 @@ */ public class StringUtils extends org.apache.commons.lang3.StringUtils { + + public static String appendSpace(int length, String str) { + int spaceCount = length - str.length(); + + StringBuffer spaceBuffer = new StringBuffer(); + for (int i = 0; i < spaceCount; i++) { + spaceBuffer.append(" "); + } + return str + spaceBuffer.toString(); + } } diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayList.java deleted file mode 100644 index af897cd58f..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayList.java +++ /dev/null @@ -1,97 +0,0 @@ -package me.lzb.basic; - -/** - * 简易ArrayList - * Created by LZB on 2017/3/11. - */ -public class ArrayList implements List { - - private int size = 0; - - private Object[] elementData = {}; - - - public void add(Object o) { -// if (elementData.length < size + 1) { -// Object[] target = new Object[size + 1]; -// System.arraycopy(elementData, 0, target, 0, elementData.length); -// elementData = target; -// } -// elementData[size] = o; -// size = size + 1; - add(size, o); - } - - - public void add(int index, Object o) throws IndexOutOfBoundsException { - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException("index boom"); - } - - int leftSize = index; - int rightSize = size - index; - Object[] target = new Object[size + 1]; - System.arraycopy(elementData, 0, target, 0, leftSize); - target[index] = o; - System.arraycopy(elementData, index, target, index + 1, rightSize); - elementData = target; - size = size + 1; - } - - public Object get(int index) throws IndexOutOfBoundsException { - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException("index boom"); - } - return elementData[index]; - } - - public Object remove(int index) throws IndexOutOfBoundsException { - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException("index boom"); - } - Object removeObject = elementData[index]; - int leftSize = index; - int rightSize = size - index - 1; - Object[] target = new Object[elementData.length - 1]; - System.arraycopy(elementData, 0, target, 0, leftSize); - System.arraycopy(elementData, index + 1, target, index, rightSize); - elementData = target; - size = size - 1; - return removeObject; - } - - public int size() { - return size; - } - - - public Iterator iterator() { - return new ArrayListIterator(this); - } - - private class ArrayListIterator implements Iterator { - private ArrayList arrayList; - - int pos = 0; - - private ArrayListIterator(ArrayList arrayList) { - this.arrayList = arrayList; - } - - @Override - public boolean hasNext() { - if (pos >= arrayList.size) { - return false; - } - - return true; - } - - @Override - public Object next() { - Object result = arrayList.get(pos); - pos = pos + 1; - return result; - } - } -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayUtil.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayUtil.java deleted file mode 100644 index eab32c80cc..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayUtil.java +++ /dev/null @@ -1,337 +0,0 @@ -package me.lzb.basic; - -public class ArrayUtil { - - /** - * 给定一个整形数组a , 对该数组的值进行置换 - * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] - * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * - * @param origin - * @return - */ - public void reverseArray(int[] origin) { - int[] target = new int[origin.length]; - for (int i = 0; i < origin.length; i++) { - target[i] = origin[origin.length - 1 - i]; - } - origin = target; - } - - /** - * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: - * {1,3,4,5,6,6,5,4,7,6,7,5} - * - * @param oldArray - * @return - */ - - public int[] removeZero(int[] oldArray) { - int l = 0; - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] != 0) { - l = l + 1; - } - } - - int[] target = new int[l]; - - int a = 0; - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] != 0) { - target[a] = oldArray[i]; - a = a + 1; - } - } - - return target; - } - - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 - * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - * - * @param array1 - * @param array2 - * @return - */ - - //一个一个放进去,循环次数有点多 - public int[] merge(int[] array1, int[] array2) { - - - int[] tmp = new int[array1.length + array2.length]; - - - int mini = 0; - int a1 = array1[0]; - int a2 = array2[0]; - - if(a1 < a2){ - mini = a1; - }else { - mini = a2; - } - - tmp[0] = mini; - - int l3 = 0; - - for (int i = 1; i < array1.length + array2.length; i++) { - -// if(mini >= array1[l1 - 1] && mini >= array2[l2 - 1]){ -// l3 = i; -// break; -// } - - int oldMin = mini; - - - - int aa1 = mini; - if(mini < array1[array1.length - 1] ){ - for (int j = 0; j < array1.length; j++) { - if(array1[j] > mini){ - aa1 = array1[j]; - break; - } - } - - } - - int aa2 = mini; - if(mini < array2[array2.length - 1] ){ - for (int j = 0; j < array2.length; j++) { - if(array2[j] > mini){ - aa2 = array2[j]; - break; - } - } - } - - - if(aa1 != oldMin && aa2 != oldMin){ - if(aa1 < aa2){ - mini = aa1; - }else { - mini = aa2; - } - }else if(aa1 != oldMin){ - mini = aa1; - }else { - mini = aa2; - } - - - if(oldMin == mini){ - l3 = i; - break; - } - - tmp[i] = mini; - } - - int[] result = new int[l3]; - - System.arraycopy(tmp, 0, result, 0, l3); - - - - return result; - } - - - - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * - * @param oldArray - * @param size - * @return - */ - public int[] grow(int[] oldArray, int size) { - int newArray[] = new int[oldArray.length + size]; - - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); - return newArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - * - * @param max - * @return - */ - public int[] fibonacci(int max) { - if (max <= 1){ - return new int[0]; - } - - int[] result = {1, 1}; - - - int i = 2; - - int n = 0; - - while (n < max){ - int[] t = new int[result.length + 1]; - System.arraycopy(result, 0, t, 0, result.length); - n = t[i-1] + t[i - 2]; - - if(n >= max){ - return result; - } - - t[i] = n; - - result = t; - i = i + 1; - } - - return null; - } - - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public int[] getPrimes(int max) { - if (max <= 2){ - return new int[0]; - } - - if (max == 3){ - return new int[]{2}; - } - - - int[] primes = new int[max+1]; - primes[0] = 2; - int count = 1; - for (int i = 3; i < max; i = i + 2) { - - boolean isPrime = true; - for (int j = 3; j < i; j++) { - if(i % j == 0){ - isPrime = false; - break; - } - } - - if(isPrime){ - primes[count] = i; - count = count + 1; - } - } - - int[] result = new int[count]; - System.arraycopy(primes, 0, result, 0, count); - - return result; - - } - - private boolean isPrime(int a){ - if (a < 2) { - return false; - } - - if (a == 2) { - return true; - } - - if(a % 2 == 0){ - return false; - } - - - for (int i = 3; i < a; i = i + 2) { - if(a % i == 0){ - return false; - } - } - - return true; - } - - - - /** - * 所谓“完数”, 是指这个数恰好等于它的真因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * - * @param max - * @return - */ - public int[] getPerfectNumbers(int max) { - if (max < 6){ - return new int[0]; - } - - - int[] pns = new int[max]; - - int count = 0; - for (int i = 6; i < max; i++) { - if (isPerfectNumber(i)){ - pns[count] = i; - count = count + 1; - } - } - - - - int[] result = new int[count]; - System.arraycopy(pns, 0, result, 0, count); - return result; - } - - - private boolean isPerfectNumber(int a){ - if(a < 6){ - return false; - } - - int sum = 0; - for (int i = 1; i < a; i++) { - if(a % i == 0){ - sum = sum + i; - } - } - - return sum == a; - } - - - - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" - * - * @param array - * @return - */ - public static String join(int[] array, String seperator) { - String result = ""; - for (int i = 0; i < array.length; i++) { - result = result + array[i] + seperator ; - } - - result = result.substring(0, result.length() - 1); - return result; - } - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/BinaryTreeNode.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/BinaryTreeNode.java deleted file mode 100644 index 88395e3010..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/BinaryTreeNode.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.lzb.basic; - -/** - * 左边比父节点小,右边比父节点大 - * Created by LZB on 2017/3/11. - */ -public class BinaryTreeNode { - - private int data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public BinaryTreeNode(int data){ - this.data = data; - } - - public int getData() { - return data; - } - - - //这层满了就下一层继续add,直到找到空位 - public void add(int d){ - BinaryTreeNode b = new BinaryTreeNode(d); - if(compareTo(b)){ - //比父节点小,左边 - if(this.left == null){ - this.left = b; - }else { - this.left.add(d); - } - - }else {//相等不考虑 - //比父节点大,右边 - if(this.right == null){ - this.right = b; - }else { - this.right.add(d); - } - - } - } - - - public boolean compareTo(BinaryTreeNode node){ - if(this.data > node.getData()){ - return true; - } - return false; - } - - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/FileList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/FileList.java new file mode 100644 index 0000000000..ce0d19e330 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/FileList.java @@ -0,0 +1,54 @@ +package me.lzb.basic; + +import java.io.File; + +/** + * 给定一个目录,递归的列出下面所有的子目录和文件 + * + * @author LZB + */ +public class FileList { + + public void list(File f) { + System.out.println(f.getPath()); + + list(f, 0); + } + + + private void list(File file, int level) { + if (file.isDirectory()) { + print(file, level); + } + level++; + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].isDirectory()) { + list(files[i], level); + } else { + print(files[i], level); + } + } + } + + private void print(File f, int level) { + System.out.println(getFileFormat(level) + f.getName()); + + } + + + private String getFileFormat(int level) { + StringBuffer sb = new StringBuffer(); + if (level > 1) { + sb.append("|"); + } + + for (int i = 0; i < level - 1; i++) { + sb.append(" "); + } + if (level > 0) { + sb.append("|--"); + } + return sb.toString(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java deleted file mode 100644 index 86e8cae942..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java +++ /dev/null @@ -1,10 +0,0 @@ -package me.lzb.basic; - -/** - * Created by LZB on 2017/3/11. - */ -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LinkedList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LinkedList.java deleted file mode 100644 index 268b69bf50..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LinkedList.java +++ /dev/null @@ -1,510 +0,0 @@ -package me.lzb.basic; - - -/** - * 简易LinkedList - * Created by LZB on 2017/3/11. - */ -public class LinkedList implements List { - - private int size = 0; - - - private Node first; - - private Node last; - - - private static class Node { - Object data; - Node next; -// int intData; - - public Node(Object data, Node next) { - this.data = data; - this.next = next; - } -// public Node(Object data, Node next, int i) { -// this.data = data; -// this.next = next; -// this.intData = i; -// } - } - - -// public void add(int i) { -// if (first == null) { -// first = new Node(null, null, i); -// last = first; -// } else { -// Node n = new Node(null, null, i); -// last.next = n; -// last = n; -// } -// size = size + 1; -// } - public void add(Object o) { - if (first == null) { - first = new Node(o, null); - last = first; - } else { - Node n = new Node(o, null); - last.next = n; - last = n; - } - size = size + 1; - } -// -// public void addInt(int i) { -// if (first == null) { -// first = new Node(null, null, i); -// last = first; -// } else { -// Node n = new Node(null, null, i); -// last.next = n; -// last = n; -// } -// size = size + 1; -// } - - - public void add(int index, Object o) throws IndexOutOfBoundsException { - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException("index boom"); - } - - if (index == size) { - add(o); - return; - } - - if (index == 0) { - Node n = new Node(0, first); - first = n; - size = size + 1; - return; - } - - Node before = first; - for (int i = 0; i < index - 1; i++) { - before = before.next; - } - - Node after = before.next; - - Node n = new Node(o, after); - - before.next = n; - - size = size + 1; - - } - - private Node getNode(int index){ - if (size == 0 || index < 0 || index >= size) { - throw new IndexOutOfBoundsException("index boom"); - } - Node result = first; - for (int i = 0; i < index; i++) { - result = result.next; - } - return result; - } - - - public Object get(int index) { - return getNode(index).data; - } - - - public Object remove(int index) { - if (index < 0 || index >= size) { - throw new IndexOutOfBoundsException("index boom"); - } - - if (size == 1) { - Node result = last; - last = null; - first = null; - size = size - 1; - return result.data; - } - - if (index == size - 1) { - Node result = last; - last = null; - size = size - 1; - return result.data; - } - - - if (index == 0) { - Node result = first; - Node second = first.next; - first = second; - size = size - 1; - return result.data; - } - - - Node before = first; - for (int i = 0; i < index - 1; i++) { - before = before.next; - } - Node result = before.next; - Node after = before.next.next; - before.next = after; - size = size - 1; - return result.data; - } - - - - - - - - - public int size() { - return size; - } - - public void addFirst(Object o) { - add(0, o); - } - - - public void addLast(Object o) { - add(o); - } - - - public Object removeFirst() { - return remove(0); - } - - - public Object removeLast() { - return remove(size); - } - - - public Iterator iterator() { - return new LinkedListIterator(this); - } - - - private class LinkedListIterator implements Iterator { - private LinkedList linkedList; - - int pos = 0; - - private LinkedListIterator(LinkedList linkedList) { - this.linkedList = linkedList; - } - - @Override - public boolean hasNext() { - - if (pos >= linkedList.size) { - return false; - } - return true; - } - - @Override - public Object next() { - Object result = linkedList.get(pos); - pos = pos + 1; - return result; - } - } - - - //后面的方法先不用写的说 - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse() { - - //还可以用堆栈 先进后出 - - if(size() <= 1){ - return; - } - Object[] array = new Object[size]; - Node tmp = first; - for (int i = 0; i < size; i++) { - array[i] = tmp.data; - tmp = tmp.next; - } - this.first = null; - this.last = null; - for (int i = array.length - 1; i >= 0 ; i--) { - add(array[i]); - } - - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - */ - public void removeFirstHalf() { - - if (size <= 1){ - return; - } - int b = size/ 2; - Node n = getNode(b); - this.first = n; - size = (size % 2) + b; - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * - * @param i - * @param length - */ - public void remove(int i, int length) { - if (size == 0 || i < 0 || i >= size){ - return; - } - - length = size - i >= length ? length : size - i; - - - if(i + length == size){ - this.first = null; - this.last = null; - size = 0; - return; - } - - if(i == 0){ - Node n = getNode(length); - first = n; - size = size - length; - return; - } - - - Node a = getNode(i - 1); - Node b = getNode(i + length); - a.next = b; - size = size - length; - } - - /** - * 假定当前链表和list均包含已升序排列的整数 - * 从当前链表中取出那些list所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * - * @param list - */ - public int[] getElements(LinkedList list) { - - if(size <= 0 || list.size() <= 0){ - return new int[0]; - } - - - - int[] result = new int[list.size()]; - - Node tmp = list.first; - int index = 0; - Node tmp2 = first; - for (int i = 0; i < list.size(); i++) { - int newIndex = (int)tmp.data; - int maxJ = newIndex - index; - for (int j = 0; j <= maxJ; j++) { - - if(j == maxJ){ - result[i] = (int)tmp2.data; - break; - } - tmp2 = tmp2.next; - } - index = newIndex; - tmp = tmp.next; - } - - size = size - list.size(); - - return result; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在list中出现的元素 - * - * @param list - */ - - public void subtract(LinkedList list) { - for (int i = 0; i < list.size(); i++) { - this.remove(list.get(i)); - } - - } - - - public void remove(Object obj){ - if(size <= 0){ - return; - } - if(first.data.equals(obj)){ - first=first.next; - size = size - 1; - return; - } - Node tmp = first; - Node tmp2 = first.next; - for (int i = 1; i < size; i++) { - if(tmp2.data.equals(obj)){ - tmp.next = tmp2.next; - size = size - 1; - return; - } - tmp = tmp.next; - tmp2 = tmp2.next; - } - - } - - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues() { - if(size <= 1){ - return; - } - - Node tmp = first; - for (int i = 1; i < size; i++) { - if(tmp.next == null){ - break; - } - if (tmp.data.equals(tmp.next.data)){ - tmp.next = tmp.next.next; - } - tmp = tmp.next; - } - - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * - * @param min - * @param max - */ - public void removeRange(int min, int max) { - if(size <= 0){ - return; - } - - Node tmp = first; - int a = -1; - int b = -1; - for (int i = 0; i < size; i++) { - if((int)tmp.data > min && a == -1){ - a = i; - } - - if((int)tmp.data >= max && b == -1){ - b = i; - } - - tmp = tmp.next; - } - - - if(min < max){ - remove(a, b - a); - return; - - } - - - if(min == max){ - - } - - - if(min > max){ - - } - - - - return; - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * - * @param list - */ - public LinkedList intersection(LinkedList list) { - LinkedList result = new LinkedList(); - - if(list == null || list.size <= 0 || size <= 0){ - return result; - } - - int i1 = 0; - int i2 = 0; - - while( i1 < this.size && i2 s) { - - - } - - /** - * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 - * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - */ - public static void reverse(Stack s) { - Stack t = new Stack<>(); - for (Integer i : s) { - t.push(i); - } - - s.clear(); - - int size = t.size(); - for (int i = 0; i < size; i++) { - s.push(t.pop()); - } - - } - - public static void addToBottom(Stack s, Integer value) { - Stack t = new Stack<>(); - int size = s.size(); - for (int i = 0; i < size; i++) { - t.push(s.pop()); - } - - s.clear(); - - s.push(value); - - for (int i = 0; i < size; i++) { - s.push(t.pop()); - } - - } - - /** - * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - * - * @param o - */ - public static void remove(Stack s, Object o) { - Stack t = new Stack(); - int size = s.size(); - for (int i = 0; i < size; i++) { - Object ro = s.pop(); - if (!ro.equals(o)) { - t.push(ro); - } - } - - s.clear(); - - int sizet = t.size(); - for (int i = 0; i < sizet; i++) { - s.push(t.pop()); - } - - } - - /** - * 从栈顶取得len个元素, 原来的栈中元素保持不变 - * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 - * - * @param len - * @return - */ - public static Object[] getTop(Stack s, int len) { - Object[] array = new Object[len]; - for (int i = 0; i < len; i++) { - array[i] = s.pop(); - } - - for (int i = len - 1; i >= 0; i--) { - s.push(array[i]); - } - return array; - } - - /** - * 字符串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) { - char[] array = s.toCharArray(); - Stack stack = new Stack<>(); - for (int i = 0; i < array.length; i++) { - stack.push(String.valueOf(array[i])); - } - - - int a = -1; - int b = -1; - int c = -1; - - - for (int i = 0; i < array.length; i++) { - String cc = stack.pop(); - - if ("{}".indexOf(cc) >= 0) { - if (a == -1) { - a = i; - } else { - if (stack.size() != a) { - return false; - } - } - } - - if ("[]".indexOf(cc) >= 0) { - - if (b == -1) { - b = i; - } else { - if (stack.size() != b) { - return false; - } - } - - } - - if ("()".indexOf(cc) >= 0) { - - if (c == -1) { - c = i; - } else { - if (stack.size() != c) { - return false; - } - } - - } - - } - return true; - } - - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayList.java new file mode 100644 index 0000000000..a999b662f1 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayList.java @@ -0,0 +1,97 @@ +package me.lzb.basic.list; + +/** + * 简易ArrayList + * Created by LZB on 2017/3/11. + */ +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = {}; + + + public void add(Object o) { +// if (elementData.length < size + 1) { +// Object[] target = new Object[size + 1]; +// System.arraycopy(elementData, 0, target, 0, elementData.length); +// elementData = target; +// } +// elementData[size] = o; +// size = size + 1; + add(size, o); + } + + + public void add(int index, Object o) throws IndexOutOfBoundsException { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("index boom"); + } + + int leftSize = index; + int rightSize = size - index; + Object[] target = new Object[size + 1]; + System.arraycopy(elementData, 0, target, 0, leftSize); + target[index] = o; + System.arraycopy(elementData, index, target, index + 1, rightSize); + elementData = target; + size = size + 1; + } + + public Object get(int index) throws IndexOutOfBoundsException { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException("index boom"); + } + return elementData[index]; + } + + public Object remove(int index) throws IndexOutOfBoundsException { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException("index boom"); + } + Object removeObject = elementData[index]; + int leftSize = index; + int rightSize = size - index - 1; + Object[] target = new Object[elementData.length - 1]; + System.arraycopy(elementData, 0, target, 0, leftSize); + System.arraycopy(elementData, index + 1, target, index, rightSize); + elementData = target; + size = size - 1; + return removeObject; + } + + public int size() { + return size; + } + + + public Iterator iterator() { + return new ArrayListIterator(this); + } + + private class ArrayListIterator implements Iterator { + private ArrayList arrayList; + + int pos = 0; + + private ArrayListIterator(ArrayList arrayList) { + this.arrayList = arrayList; + } + + @Override + public boolean hasNext() { + if (pos >= arrayList.size) { + return false; + } + + return true; + } + + @Override + public Object next() { + Object result = arrayList.get(pos); + pos = pos + 1; + return result; + } + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayUtil.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayUtil.java new file mode 100644 index 0000000000..dcfa9c39f6 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/ArrayUtil.java @@ -0,0 +1,337 @@ +package me.lzb.basic.list; + +public class ArrayUtil { + + /** + * 给定一个整形数组a , 对该数组的值进行置换 + * 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] + * 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] + * + * @param origin + * @return + */ + public void reverseArray(int[] origin) { + int[] target = new int[origin.length]; + for (int i = 0; i < origin.length; i++) { + target[i] = origin[origin.length - 1 - i]; + } + origin = target; + } + + /** + * 现在有如下的一个数组: int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * 要求将以上数组中值为0的项去掉,将不为0的值存入一个新的数组,生成的新数组为: + * {1,3,4,5,6,6,5,4,7,6,7,5} + * + * @param oldArray + * @return + */ + + public int[] removeZero(int[] oldArray) { + int l = 0; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + l = l + 1; + } + } + + int[] target = new int[l]; + + int a = 0; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + target[a] = oldArray[i]; + a = a + 1; + } + } + + return target; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * + * @param array1 + * @param array2 + * @return + */ + + //一个一个放进去,循环次数有点多 + public int[] merge(int[] array1, int[] array2) { + + + int[] tmp = new int[array1.length + array2.length]; + + + int mini = 0; + int a1 = array1[0]; + int a2 = array2[0]; + + if(a1 < a2){ + mini = a1; + }else { + mini = a2; + } + + tmp[0] = mini; + + int l3 = 0; + + for (int i = 1; i < array1.length + array2.length; i++) { + +// if(mini >= array1[l1 - 1] && mini >= array2[l2 - 1]){ +// l3 = i; +// break; +// } + + int oldMin = mini; + + + + int aa1 = mini; + if(mini < array1[array1.length - 1] ){ + for (int j = 0; j < array1.length; j++) { + if(array1[j] > mini){ + aa1 = array1[j]; + break; + } + } + + } + + int aa2 = mini; + if(mini < array2[array2.length - 1] ){ + for (int j = 0; j < array2.length; j++) { + if(array2[j] > mini){ + aa2 = array2[j]; + break; + } + } + } + + + if(aa1 != oldMin && aa2 != oldMin){ + if(aa1 < aa2){ + mini = aa1; + }else { + mini = aa2; + } + }else if(aa1 != oldMin){ + mini = aa1; + }else { + mini = aa2; + } + + + if(oldMin == mini){ + l3 = i; + break; + } + + tmp[i] = mini; + } + + int[] result = new int[l3]; + + System.arraycopy(tmp, 0, result, 0, l3); + + + + return result; + } + + + + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * + * @param oldArray + * @param size + * @return + */ + public int[] grow(int[] oldArray, int size) { + int newArray[] = new int[oldArray.length + size]; + + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); + return newArray; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + * + * @param max + * @return + */ + public int[] fibonacci(int max) { + if (max <= 1){ + return new int[0]; + } + + int[] result = {1, 1}; + + + int i = 2; + + int n = 0; + + while (n < max){ + int[] t = new int[result.length + 1]; + System.arraycopy(result, 0, t, 0, result.length); + n = t[i-1] + t[i - 2]; + + if(n >= max){ + return result; + } + + t[i] = n; + + result = t; + i = i + 1; + } + + return null; + } + + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public int[] getPrimes(int max) { + if (max <= 2){ + return new int[0]; + } + + if (max == 3){ + return new int[]{2}; + } + + + int[] primes = new int[max+1]; + primes[0] = 2; + int count = 1; + for (int i = 3; i < max; i = i + 2) { + + boolean isPrime = true; + for (int j = 3; j < i; j++) { + if(i % j == 0){ + isPrime = false; + break; + } + } + + if(isPrime){ + primes[count] = i; + count = count + 1; + } + } + + int[] result = new int[count]; + System.arraycopy(primes, 0, result, 0, count); + + return result; + + } + + private boolean isPrime(int a){ + if (a < 2) { + return false; + } + + if (a == 2) { + return true; + } + + if(a % 2 == 0){ + return false; + } + + + for (int i = 3; i < a; i = i + 2) { + if(a % i == 0){ + return false; + } + } + + return true; + } + + + + /** + * 所谓“完数”, 是指这个数恰好等于它的真因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public int[] getPerfectNumbers(int max) { + if (max < 6){ + return new int[0]; + } + + + int[] pns = new int[max]; + + int count = 0; + for (int i = 6; i < max; i++) { + if (isPerfectNumber(i)){ + pns[count] = i; + count = count + 1; + } + } + + + + int[] result = new int[count]; + System.arraycopy(pns, 0, result, 0, count); + return result; + } + + + private boolean isPerfectNumber(int a){ + if(a < 6){ + return false; + } + + int sum = 0; + for (int i = 1; i < a; i++) { + if(a % i == 0){ + sum = sum + i; + } + } + + return sum == a; + } + + + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * + * @param array + * @return + */ + public static String join(int[] array, String seperator) { + String result = ""; + for (int i = 0; i < array.length; i++) { + result = result + array[i] + seperator ; + } + + result = result.substring(0, result.length() - 1); + return result; + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/Iterator.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/Iterator.java new file mode 100644 index 0000000000..d6122132cc --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/Iterator.java @@ -0,0 +1,10 @@ +package me.lzb.basic.list; + +/** + * Created by LZB on 2017/3/11. + */ +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/LinkedList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/LinkedList.java new file mode 100644 index 0000000000..f55c92cdc6 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/list/LinkedList.java @@ -0,0 +1,510 @@ +package me.lzb.basic.list; + + +/** + * 简易LinkedList + * Created by LZB on 2017/3/11. + */ +public class LinkedList implements List { + + private int size = 0; + + + private Node first; + + private Node last; + + + private static class Node { + Object data; + Node next; +// int intData; + + public Node(Object data, Node next) { + this.data = data; + this.next = next; + } +// public Node(Object data, Node next, int i) { +// this.data = data; +// this.next = next; +// this.intData = i; +// } + } + + +// public void add(int i) { +// if (first == null) { +// first = new Node(null, null, i); +// last = first; +// } else { +// Node n = new Node(null, null, i); +// last.next = n; +// last = n; +// } +// size = size + 1; +// } + public void add(Object o) { + if (first == null) { + first = new Node(o, null); + last = first; + } else { + Node n = new Node(o, null); + last.next = n; + last = n; + } + size = size + 1; + } +// +// public void addInt(int i) { +// if (first == null) { +// first = new Node(null, null, i); +// last = first; +// } else { +// Node n = new Node(null, null, i); +// last.next = n; +// last = n; +// } +// size = size + 1; +// } + + + public void add(int index, Object o) throws IndexOutOfBoundsException { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("index boom"); + } + + if (index == size) { + add(o); + return; + } + + if (index == 0) { + Node n = new Node(0, first); + first = n; + size = size + 1; + return; + } + + Node before = first; + for (int i = 0; i < index - 1; i++) { + before = before.next; + } + + Node after = before.next; + + Node n = new Node(o, after); + + before.next = n; + + size = size + 1; + + } + + private Node getNode(int index){ + if (size == 0 || index < 0 || index >= size) { + throw new IndexOutOfBoundsException("index boom"); + } + Node result = first; + for (int i = 0; i < index; i++) { + result = result.next; + } + return result; + } + + + public Object get(int index) { + return getNode(index).data; + } + + + public Object remove(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException("index boom"); + } + + if (size == 1) { + Node result = last; + last = null; + first = null; + size = size - 1; + return result.data; + } + + if (index == size - 1) { + Node result = last; + last = null; + size = size - 1; + return result.data; + } + + + if (index == 0) { + Node result = first; + Node second = first.next; + first = second; + size = size - 1; + return result.data; + } + + + Node before = first; + for (int i = 0; i < index - 1; i++) { + before = before.next; + } + Node result = before.next; + Node after = before.next.next; + before.next = after; + size = size - 1; + return result.data; + } + + + + + + + + + public int size() { + return size; + } + + public void addFirst(Object o) { + add(0, o); + } + + + public void addLast(Object o) { + add(o); + } + + + public Object removeFirst() { + return remove(0); + } + + + public Object removeLast() { + return remove(size); + } + + + public Iterator iterator() { + return new LinkedListIterator(this); + } + + + private class LinkedListIterator implements Iterator { + private LinkedList linkedList; + + int pos = 0; + + private LinkedListIterator(LinkedList linkedList) { + this.linkedList = linkedList; + } + + @Override + public boolean hasNext() { + + if (pos >= linkedList.size) { + return false; + } + return true; + } + + @Override + public Object next() { + Object result = linkedList.get(pos); + pos = pos + 1; + return result; + } + } + + + //后面的方法先不用写的说 + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + + //还可以用堆栈 先进后出 + + if(size() <= 1){ + return; + } + Object[] array = new Object[size]; + Node tmp = first; + for (int i = 0; i < size; i++) { + array[i] = tmp.data; + tmp = tmp.next; + } + this.first = null; + this.last = null; + for (int i = array.length - 1; i >= 0 ; i--) { + add(array[i]); + } + + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + + if (size <= 1){ + return; + } + int b = size/ 2; + Node n = getNode(b); + this.first = n; + size = (size % 2) + b; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (size == 0 || i < 0 || i >= size){ + return; + } + + length = size - i >= length ? length : size - i; + + + if(i + length == size){ + this.first = null; + this.last = null; + size = 0; + return; + } + + if(i == 0){ + Node n = getNode(length); + first = n; + size = size - length; + return; + } + + + Node a = getNode(i - 1); + Node b = getNode(i + length); + a.next = b; + size = size - length; + } + + /** + * 假定当前链表和list均包含已升序排列的整数 + * 从当前链表中取出那些list所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * + * @param list + */ + public int[] getElements(LinkedList list) { + + if(size <= 0 || list.size() <= 0){ + return new int[0]; + } + + + + int[] result = new int[list.size()]; + + Node tmp = list.first; + int index = 0; + Node tmp2 = first; + for (int i = 0; i < list.size(); i++) { + int newIndex = (int)tmp.data; + int maxJ = newIndex - index; + for (int j = 0; j <= maxJ; j++) { + + if(j == maxJ){ + result[i] = (int)tmp2.data; + break; + } + tmp2 = tmp2.next; + } + index = newIndex; + tmp = tmp.next; + } + + size = size - list.size(); + + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + for (int i = 0; i < list.size(); i++) { + this.remove(list.get(i)); + } + + } + + + public void remove(Object obj){ + if(size <= 0){ + return; + } + if(first.data.equals(obj)){ + first=first.next; + size = size - 1; + return; + } + Node tmp = first; + Node tmp2 = first.next; + for (int i = 1; i < size; i++) { + if(tmp2.data.equals(obj)){ + tmp.next = tmp2.next; + size = size - 1; + return; + } + tmp = tmp.next; + tmp2 = tmp2.next; + } + + } + + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + if(size <= 1){ + return; + } + + Node tmp = first; + for (int i = 1; i < size; i++) { + if(tmp.next == null){ + break; + } + if (tmp.data.equals(tmp.next.data)){ + tmp.next = tmp.next.next; + } + tmp = tmp.next; + } + + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if(size <= 0){ + return; + } + + Node tmp = first; + int a = -1; + int b = -1; + for (int i = 0; i < size; i++) { + if((int)tmp.data > min && a == -1){ + a = i; + } + + if((int)tmp.data >= max && b == -1){ + b = i; + } + + tmp = tmp.next; + } + + + if(min < max){ + remove(a, b - a); + return; + + } + + + if(min == max){ + + } + + + if(min > max){ + + } + + + + return; + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList result = new LinkedList(); + + if(list == null || list.size <= 0 || size <= 0){ + return result; + } + + int i1 = 0; + int i2 = 0; + + while( i1 < this.size && i2 + * Created by LZB on 2017/4/27. + */ +public class CircleQueue { + + + public CircleQueue(){ + DEFAULT_SIZE = 10; + } + + public CircleQueue(int size){ + if(size <= 0){ + size = 10; + } + DEFAULT_SIZE = size; + } + + + private int DEFAULT_SIZE; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + private int size; + + public boolean isEmpty() { + return size() <= 0; + + } + + public int size() { + return size; + } + + + public void enQueue(E data) { + nextRear(); + elementData[rear] = data; + if (isFull()) { + nextFront(); + } else { + size++; + } + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("empty"); + } + Object result = elementData[front]; + elementData[front] = null; + nextFront(); + size--; + return (E) result; + } + + private void nextRear() { + if (rear == (elementData.length - 1)) { + rear = 0; + } else { + rear = rear + 1; + } + + } + + private void nextFront() { + if (front == (elementData.length - 1)) { + front = 0; + } else { + front = front + 1; + } + } + + + private boolean isFull() { + if (size() == elementData.length) { + return true; + } + return false; + } + + @Override + public String toString() { + if (isEmpty()) { + return "[]"; + } + StringBuffer sb = new StringBuffer(); + sb.append("["); + + + for (int i = 0; i < elementData.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(elementData[i].toString()); + } + + + sb.append("]"); + return sb.toString(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Josephus.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Josephus.java new file mode 100644 index 0000000000..8fcddcfb2c --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Josephus.java @@ -0,0 +1,64 @@ +package me.lzb.basic.queue; + +import java.util.*; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * Created by LZB on 2017/4/27. + */ +public class Josephus { + + public static List execute(int n, int m) { + List result = new ArrayList<>(); + + java.util.Queue queue = new LinkedList<>(); + for (int i = 0; i < n; i++) { + queue.add(i); + } + + while (!(queue.size() < m)) { + result.add(killOne(queue, m)); + } + + return result; + } + + + private static Integer killOne(java.util.Queue queue, int m) { + if (queue.isEmpty()) { + return null; + } + + if (queue.size() < m) { + return null; + } + + + java.util.Queue tmp = new LinkedList<>(); + int i = 1; + while (!queue.isEmpty()) { + if (i == m) { + Integer re = queue.poll(); + + move(queue, tmp); + return re; + + } else { + tmp.add(queue.poll()); + i++; + } + } + + return null; + } + + private static void move(java.util.Queue queue, java.util.Queue queue2) { + while (!queue2.isEmpty()) { + queue.add(queue2.poll()); + } + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Queue.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Queue.java new file mode 100644 index 0000000000..b1ef522855 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/Queue.java @@ -0,0 +1,33 @@ +package me.lzb.basic.queue; + +import me.lzb.basic.list.LinkedList; + +/** + * 先进先出 + * Created by LZB on 2017/3/11. + */ +public class Queue { + LinkedList elementData = new LinkedList(); + + public void enQueue(Object o){ + elementData.add(o); + } + + public Object deQueue() throws IndexOutOfBoundsException{ + if(isEmpty()){ + throw new IndexOutOfBoundsException("index boom"); + } + return elementData.remove(elementData.size() - 1); + } + + public boolean isEmpty(){ + if(elementData.size() <= 0){ + return true; + } + return false; + } + + public int size(){ + return elementData.size(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/QueueWithTwoStacks.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..65c3b45fae --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,101 @@ +package me.lzb.basic.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * Created by LZB on 2017/4/27. + */ +public class QueueWithTwoStacks { + private Stack stack1;//ASC + private Stack stack2;//DESC + + private boolean isASC; + + + public QueueWithTwoStacks() { + stack1 = new Stack<>(); + stack2 = new Stack<>(); + isASC = false; + } + + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + + public int size() { + return stack1.isEmpty() ? stack2.size() : stack1.size(); + } + + + public void enQueue(E item) { + + if (isASC) { + while (!stack2.isEmpty()) { + stack1.push(stack2.pop()); + } + isASC = false; + + + } + + stack1.push(item); + } + + public E deQueue() { + + if (isEmpty()) { + throw new RuntimeException("empty"); + } + + if (!isASC) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + isASC = true; + } + + return stack2.pop(); + + } + + @Override + public String toString() { + if (isEmpty()) { + return "[]"; + } + StringBuffer sb = new StringBuffer(); + sb.append("["); + + + Object[] array = new Object[size()]; + + if (isASC) { + int i = size() - 1; + for (E e : stack2) { + array[i] = e; + i--; + } + } else { + int i = 0; + for (E e : stack1) { + array[i] = e; + i++; + } + } + + for (int i = 0; i < array.length; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(array[i].toString()); + } + + + sb.append("]"); + return sb.toString(); + } +} + diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/QuickMinStack.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..d6250bae89 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/QuickMinStack.java @@ -0,0 +1,60 @@ +package me.lzb.basic.stack; + +import java.util.Stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + */ +public class QuickMinStack { + private int mini; + private java.util.Stack stack = new Stack(); + + + public void push(int data) { + if (stack.size() <= 0) { + mini = data; + } else if (mini > data) { + mini = data; + } + stack.push(data); + } + + public int pop() { + if (stack.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + + + int a = stack.pop(); + if (a <= mini) { + newMin(); + } + + return a; + } + + public int findMin() { + if (stack.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + return mini; + } + + + private void newMin() { + if (stack.isEmpty()) { + return; + } + + int a = stack.peek(); + for (int i : stack) { + if (i < a) { + a = i; + } + } + + this.mini = a; + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/Stack.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/Stack.java new file mode 100644 index 0000000000..a5469ff8ce --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/Stack.java @@ -0,0 +1,51 @@ +package me.lzb.basic.stack; + +import me.lzb.basic.list.ArrayList; + +/** + * 先进后出 + * Created by LZB on 2017/3/11. + */ +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o) { + elementData.add(o); + } + + /** + * 获取最后进的那个,并删除 + * + * @return + */ + public Object pop() throws IndexOutOfBoundsException { + if (isEmpty()) { + throw new IndexOutOfBoundsException("index boom"); + } + + return elementData.remove(elementData.size() - 1); + } + + /** + * 返回最后进去的元素 + * + * @return + */ + public Object peek() throws IndexOutOfBoundsException { + if (isEmpty()) { + throw new IndexOutOfBoundsException("index boom"); + } + return elementData.get(elementData.size() - 1); + } + + public boolean isEmpty() { + if (elementData.size() <= 0) { + return true; + } + return false; + } + + public int size() { + return elementData.size(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackUtil.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackUtil.java new file mode 100644 index 0000000000..f728f54630 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackUtil.java @@ -0,0 +1,155 @@ +package me.lzb.basic.stack; + +import java.util.Stack; + +public class StackUtil { + + public static void bad_reverse(Stack s) { + + + } + + /** + * 假设栈中的元素是Integer, 从栈顶到栈底是 : 5,4,3,2,1 调用该方法后, 元素次序变为: 1,2,3,4,5 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void reverse(Stack s) { + Stack t = new Stack<>(); + for (Integer i : s) { + t.push(i); + } + + s.clear(); + + int size = t.size(); + for (int i = 0; i < size; i++) { + s.push(t.pop()); + } + + } + + public static void addToBottom(Stack s, Integer value) { + Stack t = new Stack<>(); + int size = s.size(); + for (int i = 0; i < size; i++) { + t.push(s.pop()); + } + + s.clear(); + + s.push(value); + + for (int i = 0; i < size; i++) { + s.push(t.pop()); + } + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack t = new Stack(); + int size = s.size(); + for (int i = 0; i < size; i++) { + Object ro = s.pop(); + if (!ro.equals(o)) { + t.push(ro); + } + } + + s.clear(); + + int sizet = t.size(); + for (int i = 0; i < sizet; i++) { + s.push(t.pop()); + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + Object[] array = new Object[len]; + for (int i = 0; i < len; i++) { + array[i] = s.pop(); + } + + for (int i = len - 1; i >= 0; i--) { + s.push(array[i]); + } + return array; + } + + /** + * 字符串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) { + char[] array = s.toCharArray(); + Stack stack = new Stack<>(); + for (int i = 0; i < array.length; i++) { + stack.push(String.valueOf(array[i])); + } + + + int a = -1; + int b = -1; + int c = -1; + + + for (int i = 0; i < array.length; i++) { + String cc = stack.pop(); + + if ("{}".indexOf(cc) >= 0) { + if (a == -1) { + a = i; + } else { + if (stack.size() != a) { + return false; + } + } + } + + if ("[]".indexOf(cc) >= 0) { + + if (b == -1) { + b = i; + } else { + if (stack.size() != b) { + return false; + } + } + + } + + if ("()".indexOf(cc) >= 0) { + + if (c == -1) { + c = i; + } else { + if (stack.size() != c) { + return false; + } + } + + } + + } + return true; + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackWithTwoQueues.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..38d09d8e2d --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,98 @@ +package me.lzb.basic.stack; + + +import java.util.LinkedList; + +public class StackWithTwoQueues { + + private java.util.Queue queue1; + private java.util.Queue queue2; + private boolean isOne; + + + public StackWithTwoQueues() { + queue1 = new LinkedList(); + queue2 = new LinkedList(); + isOne = true; + } + + + public boolean isEmpty() { + return queue1.isEmpty() && queue2.isEmpty(); + } + + + public int size() { + return queue1.isEmpty() ? queue2.size() : queue1.size(); + } + + + public void push(int data) { + + if (isOne) { + queue1.add(data); + } else { + queue2.add(data); + } + } + + public int pop() { + if (isEmpty()) { + throw new RuntimeException(" Stack is empty now"); + } + + int r; + if (isOne) { + + while (queue1.size() > 1) { + queue2.add(queue1.poll()); + } + r = queue1.poll(); + isOne = false; + } else { + + while (queue2.size() > 1) { + queue1.add(queue2.poll()); + } + r = queue2.poll(); + isOne = true; + } + + return r; + } + + + @Override + public String toString() { + if (isEmpty()) { + return "[]"; + } + StringBuffer sb = new StringBuffer(); + sb.append("["); + + + int a = 1; + if (isOne) { + for (int i : queue1) { + sb.append(i); + if (a < queue1.size()) { + sb.append(","); + } + a++; + } + + + } else { + for (int i : queue2) { + sb.append(i); + if (a < queue2.size()) { + sb.append(","); + } + a++; + } + } + + sb.append("]"); + return sb.toString(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/TwoStackInOneArray.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..4e76b55a7b --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,155 @@ +package me.lzb.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + */ +public class TwoStackInOneArray { + private final int growsize = 10; + + private Object[] data = new Object[growsize]; + + private int point1 = 0; + + private int point2 = data.length - 1; + + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + grow(); + data[point1] = o; + point1 = point1 + 1; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + if (isEmpty1()) { + throw new RuntimeException("stack1 is empty"); + } + + Object o = data[point1 - 1]; + point1 = point1 - 1; + + return o; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + if (isEmpty1()) { + throw new RuntimeException("stack1 is empty"); + } + return data[point1 - 1]; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + grow(); + data[point2] = o; + point2 = point2 - 1; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (isEmpty2()) { + throw new RuntimeException("stack2 is empty"); + } + Object o = data[point2 + 1]; + point2 = point2 + 1; + return o; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + if (isEmpty2()) { + throw new RuntimeException("stack2 is empty"); + } + return data[point2 + 1]; + } + + + public boolean isEmpty1() { + return size1() <= 0; + } + + public boolean isEmpty2() { + return size2() <= 0; + } + + public int size1() { + return point1; + } + + public int size2() { + return data.length - 1 - point2; + } + + + private void grow() { + + if (point2 - point1 > 0) { + return; + } + + Object[] d = new Object[data.length + growsize]; + + System.arraycopy(data, 0, d, 0, size1()); + + System.arraycopy(data, point2 + 1, d, d.length - size2(), size2()); + point2 = d.length - 1 - size2(); + data = d; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("["); + if (!isEmpty1()) { + for (int i = 0; i < point1; i++) { + if (i > 0) { + sb.append(","); + } + sb.append(data[i].toString()); + } + } + sb.append("]"); + + sb.append("|"); + + sb.append("["); + if (!isEmpty2()) { + for (int i = data.length - 1; i > point2; i--) { + if (i < data.length - 1) { + sb.append(","); + } + + sb.append(data[i].toString()); + } + } + sb.append("]"); + return sb.toString(); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BTNode.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BTNode.java new file mode 100644 index 0000000000..ee0b9d6e33 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BTNode.java @@ -0,0 +1,53 @@ +package me.lzb.basic.tree; + +/** + * 左边比父节点小,右边比父节点大 + * Created by LZB on 2017/3/11. + */ +public class BTNode { + + private int data; + private BTNode left; + private BTNode right; + + public BTNode(int data){ + this.data = data; + } + + public int getData() { + return data; + } + + + //这层满了就下一层继续add,直到找到空位 + public void add(int d){ + BTNode b = new BTNode(d); + if(compareTo(b)){ + //比父节点小,左边 + if(this.left == null){ + this.left = b; + }else { + this.left.add(d); + } + + }else {//相等不考虑 + //比父节点大,右边 + if(this.right == null){ + this.right = b; + }else { + this.right.add(d); + } + + } + } + + + public boolean compareTo(BTNode node){ + if(this.data > node.getData()){ + return true; + } + return false; + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..fc56ca100f --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeNode.java @@ -0,0 +1,43 @@ +package me.lzb.basic.tree; + +/** + * @author LZB + */ +public class BinaryTreeNode { + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(T data) { + this.data = data; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public BinaryTreeNode getLeft() { + return left; + } + + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + + public BinaryTreeNode getRight() { + return right; + } + + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o) { + return null; + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeUtil.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeUtil.java new file mode 100644 index 0000000000..c5543271ad --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/tree/BinaryTreeUtil.java @@ -0,0 +1,177 @@ +package me.lzb.basic.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * 前序遍历:根节点->左子树->右子树 + * 中序遍历:左子树->根节点->右子树 + * 后序遍历:左子树->右子树->根节点 + * + * @author LZB + */ +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList<>(); + preOrderVisit(root, result); + return result; + } + + + private static void preOrderVisit(BinaryTreeNode root, List result) { + result.add(root.getData()); + + if (root.getLeft() != null) { + preOrderVisit(root.getLeft(), result); + } + if (root.getRight() != null) { + preOrderVisit(root.getRight(), result); + } + } + + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList<>(); + inOrderVisit(root, result); + return result; + } + + private static void inOrderVisit(BinaryTreeNode root, List result) { + if (root.getLeft() != null) { + inOrderVisit(root.getLeft(), result); + } + + result.add(root.getData()); + + if (root.getRight() != null) { + inOrderVisit(root.getRight(), result); + } + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList<>(); + postOrderVisit(root, result); + return result; + } + + private static void postOrderVisit(BinaryTreeNode root, List result) { + if (root.getLeft() != null) { + postOrderVisit(root.getLeft(), result); + } + if (root.getRight() != null) { + postOrderVisit(root.getRight(), result); + } + result.add(root.getData()); + } + + + /** + * 用非递归的方式实现对二叉树的前序遍历 + * + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList<>(); + Stack> stack = new Stack<>(); + BinaryTreeNode node = root; + //先把左侧节点全部入栈,然后一个个pop出来检查右侧节点 + while (node != null || stack.size() > 0) { + while (node != null) { + result.add(node.getData()); + stack.push(node); + node = node.getLeft(); + } + if (stack.size() > 0) { + node = stack.pop(); + node = node.getRight(); + } + } + + + return result; + } + + /** + * 用非递归的方式实现对二叉树的中序遍历 + * + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList<>(); + Stack> stack = new Stack<>(); + BinaryTreeNode node = root; + while (node != null || stack.size() > 0) { + while (node != null) { + stack.push(node); + node = node.getLeft(); + } + if (stack.size() > 0) { + node = stack.pop(); + result.add(node.getData()); + node = node.getRight(); + } + } + return result; + } + + /** + * 用非递归的方式实现对二叉树的后序遍历 + * + * @param root + * @return + */ + public static List postOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList<>(); + Stack> stack = new Stack<>(); + + Stack> s2 = new Stack<>(); + + BinaryTreeNode node = root; + + BinaryTreeNode r = root; + while (node != null || stack.size() > 0) { + //s2先入根节点,在入右边节点 + while (node != null) { + stack.push(node); + s2.push(node); + node = node.getRight(); + } + + //最底层节点出栈,左节点继续循环 + if (stack.size() > 0) { + node = stack.pop(); + node = node.getLeft(); + } + } + while (s2.size() > 0) { + result.add(s2.pop().getData()); + } + return result; + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/LoginAction.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/LoginAction.java index 5ea923c5b4..4f89670db2 100644 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/LoginAction.java +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/LoginAction.java @@ -1,8 +1,7 @@ package me.lzb.litestruts; /** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * @author liuxin + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码 * */ public class LoginAction{ diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/ArrayListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/ArrayListTest.java deleted file mode 100644 index efcfdbae1d..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/ArrayListTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package me.lzb.basic; - -import me.lzb.basic.ArrayList; -import me.lzb.basic.Iterator; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -/** - * ArrayList测试 - * Created by LZB on 2017/3/11. - */ - -public class ArrayListTest { - - private ArrayList arrayList; - - private String[] strArray; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void instantiate() throws Exception { - arrayList = new ArrayList(); - arrayList.add("a"); - arrayList.add("b"); - arrayList.add("c"); - arrayList.add("d"); - - strArray = new String[]{"a", "b", "c", "d"}; - } - - - @Test - public void sizeTest() { - Assert.assertEquals(4, arrayList.size(), 0); - } - - @Test - public void getTest() throws IndexOutOfBoundsException { - Assert.assertEquals("a", arrayList.get(0).toString()); - Assert.assertEquals("c", arrayList.get(2).toString()); - Assert.assertEquals("d", arrayList.get(3).toString()); - - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - arrayList.get(100); - arrayList.get(-1); - } - - @Test - public void iteratoreTest(){ - Iterator iterator = arrayList.iterator(); - int a = 0; - while (iterator.hasNext()){ - Assert.assertEquals(strArray[a], iterator.next().toString()); - a = a + 1; - } - } - - - @Test - public void addTest() { - arrayList.add("f"); - Assert.assertEquals("f", arrayList.get(4).toString()); - } - - @Test - public void removeTest() throws IndexOutOfBoundsException { - String r1 = arrayList.remove(1).toString(); - Assert.assertEquals("b", r1); - Assert.assertEquals(3, arrayList.size()); - - String r0 = arrayList.remove(0).toString(); - Assert.assertEquals("a", r0); - Assert.assertEquals(2, arrayList.size()); - - String rs = arrayList.remove(arrayList.size() - 1).toString(); - Assert.assertEquals("d", rs); - Assert.assertEquals(1, arrayList.size()); - - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - arrayList.remove(100); - - } - - - @Test - public void addIndexTest() throws IndexOutOfBoundsException { - arrayList.add(0, "0"); - Assert.assertEquals("0", arrayList.get(0).toString()); - arrayList.add(arrayList.size(), "s"); - Assert.assertEquals("s", arrayList.get(arrayList.size() - 1).toString()); - arrayList.add(2, "2a"); - Assert.assertEquals("2a", arrayList.get(2).toString()); - - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - arrayList.add(10, "10a"); - } - - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/FileListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/FileListTest.java new file mode 100644 index 0000000000..c9f6cd2429 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/FileListTest.java @@ -0,0 +1,23 @@ +package me.lzb.basic; + +import org.junit.Test; + +import java.io.File; + +/** + * @author LZB + * @date 2017/5/10 + */ +public class FileListTest { + + @Test + public void listTest(){ + File file = new File("D:\\code\\learning\\tmp"); + + + FileList list = new FileList(); + list.list(file); + + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LinkedListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LinkedListTest.java deleted file mode 100644 index 6f02328060..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LinkedListTest.java +++ /dev/null @@ -1,260 +0,0 @@ -package me.lzb.basic; - -import me.lzb.basic.Iterator; -import me.lzb.basic.LinkedList; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - - -/** - * linkedliksTest - * Created by LZB on 2017/3/11. - */ -public class LinkedListTest { - - private LinkedList linkedList; - - private LinkedList intList; - - private String[] strArray; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void instantiate() throws Exception { - linkedList = new LinkedList(); - linkedList.add("a"); - linkedList.add("b"); - linkedList.add("c"); - linkedList.add("d"); - - strArray = new String[]{"a", "b", "c", "d"}; - - intList = new LinkedList(); - intList.add(0); - intList.add(1); - intList.add(2); - intList.add(3); - intList.add(4); - intList.add(5); - intList.add(6); - intList.add(7); - intList.add(8); - - } - - - @Test - public void iteratoreTest() { - Iterator iterator = linkedList.iterator(); - int a = 0; - while (iterator.hasNext()) { - Assert.assertEquals(strArray[a], iterator.next().toString()); - a = a + 1; - } - } - - - @Test - public void sizeTest() { - Assert.assertEquals(4, linkedList.size(), 0); - } - - @Test - public void getTest() throws IndexOutOfBoundsException { - Assert.assertEquals("a", linkedList.get(0).toString()); - Assert.assertEquals("b", linkedList.get(1).toString()); - Assert.assertEquals("d", linkedList.get(3).toString()); - - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - linkedList.get(100); - linkedList.get(-1); - } - - - @Test - public void addTest() { - linkedList.add("f"); - Assert.assertEquals("f", linkedList.get(4).toString()); - } - - @Test - public void removeTest() throws IndexOutOfBoundsException { - String r1 = linkedList.remove(1).toString(); - Assert.assertEquals("b", r1); - Assert.assertEquals(3, linkedList.size()); - - String r0 = linkedList.remove(0).toString(); - Assert.assertEquals("a", r0); - Assert.assertEquals(2, linkedList.size()); - - String rs = linkedList.remove(linkedList.size() - 1).toString(); - Assert.assertEquals("d", rs); - Assert.assertEquals(1, linkedList.size()); - - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - linkedList.remove(100); - linkedList.remove(-1); - } - - - @Test - public void addIndexTest() throws IndexOutOfBoundsException { - linkedList.add(0, "0"); - Assert.assertEquals("0", linkedList.get(0).toString()); - linkedList.add(linkedList.size(), "s"); - Assert.assertEquals("s", linkedList.get(linkedList.size() - 1).toString()); - linkedList.add(2, "2a"); - Assert.assertEquals("2a", linkedList.get(2).toString()); - thrown.expect(IndexOutOfBoundsException.class); - thrown.expectMessage("index boom"); - linkedList.add(100, "10a"); - - } - - - @Test - public void reverseTest() { - linkedList.reverse(); - Assert.assertEquals("[d,c,b,a]", linkedList.toString()); - } - - @Test - public void removeFirstHalfTest() { - intList.removeFirstHalf(); - Assert.assertEquals("[4,5,6,7,8]", intList.toString()); - Assert.assertEquals(5, intList.size()); - linkedList.removeFirstHalf(); - Assert.assertEquals("[c,d]", linkedList.toString()); - Assert.assertEquals(2, linkedList.size()); - } - - @Test - public void removeITest() { - intList.remove(0, 10); - Assert.assertEquals("[]", intList.toString()); - Assert.assertEquals(0, intList.size()); - - - linkedList.remove(1, 2); - Assert.assertEquals("[a,d]", linkedList.toString()); - Assert.assertEquals(2, linkedList.size()); - - - LinkedList l = new LinkedList(); - l.add("a"); - l.add("b"); - l.add("c"); - l.add("d"); - l.remove(0, 2); - Assert.assertEquals("[c,d]", l.toString()); - Assert.assertEquals(2, l.size()); - } - - - @Test - public void getElementsTest() { - int[] a = {1, 3, 4, 6}; - - LinkedList l = new LinkedList(); - l.add(1); - l.add(3); - l.add(4); - l.add(6); - int[] re = intList.getElements(l); - - Assert.assertEquals(a.length, re.length); - for (int i = 0; i < a.length; i++) { - Assert.assertEquals(a[i], re[i]); - } - - } - - - @Test - public void subtractTest() { - LinkedList l = new LinkedList(); - l.add(1); - l.add(3); - l.add(4); - l.add(6); - intList.subtract(l); - Assert.assertEquals(5, intList.size()); - Assert.assertEquals("[0,2,5,7,8]", intList.toString()); - } - - - @Test - public void removeDuplicateValuesTest() { - LinkedList list = new LinkedList(); - list.add(1); - list.add(1); - list.add(2); - list.add(2); - list.add(3); - list.add(5); - list.add(5); - list.add(6); - list.removeDuplicateValues(); - - Assert.assertEquals("[1,2,3,5,6]", list.toString()); - } - - - @Test - public void removeRangeTest() { - { - LinkedList linkedList = new LinkedList(); - - linkedList.add(11); - linkedList.add(12); - linkedList.add(13); - linkedList.add(14); - linkedList.add(16); - linkedList.add(16); - linkedList.add(19); - - linkedList.removeRange(10, 19); - Assert.assertEquals("[19]", linkedList.toString()); - } - - { - LinkedList linkedList = new LinkedList(); - - linkedList.add(11); - linkedList.add(12); - linkedList.add(13); - linkedList.add(14); - linkedList.add(16); - linkedList.add(16); - linkedList.add(19); - - linkedList.removeRange(10, 14); - Assert.assertEquals("[14,16,16,19]", linkedList.toString()); - } - } - - - @Test - public void intersectionTest() { - LinkedList list1 = new LinkedList(); - list1.add(1); - list1.add(6); - list1.add(7); - - LinkedList list2 = new LinkedList(); - list2.add(2); - list2.add(5); - list2.add(6); - - LinkedList newList = list1.intersection(list2); - Assert.assertEquals("[6]", newList.toString()); - } - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/StackUtilTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/StackUtilTest.java deleted file mode 100644 index 48589f57d3..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/StackUtilTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package me.lzb.basic; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.Stack; - -public class StackUtilTest { - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testAddToBottom() { - Stack s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - - StackUtil.addToBottom(s, 0); - - Assert.assertEquals("[0, 1, 2, 3]", s.toString()); - - } - @Test - public void testReverse() { - Stack s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - s.push(4); - s.push(5); - Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); - StackUtil.reverse(s); - Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); - } - - @Test - public void testRemove() { - Stack s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - StackUtil.remove(s, 2); - Assert.assertEquals("[1, 3]", s.toString()); - } - - @Test - public void testGetTop() { - Stack s = new Stack(); - s.push(1); - s.push(2); - s.push(3); - s.push(4); - s.push(5); - { - Object[] values = StackUtil.getTop(s, 3); - Assert.assertEquals(5, values[0]); - Assert.assertEquals(4, values[1]); - Assert.assertEquals(3, values[2]); - } - Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); - } - - @Test - public void testIsValidPairs() { - Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); - Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); - } - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/ArrayListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/ArrayListTest.java new file mode 100644 index 0000000000..2240264590 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/ArrayListTest.java @@ -0,0 +1,105 @@ +package me.lzb.basic.list; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * ArrayList测试 + * Created by LZB on 2017/3/11. + */ + +public class ArrayListTest { + + private ArrayList arrayList; + + private String[] strArray; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void instantiate() throws Exception { + arrayList = new ArrayList(); + arrayList.add("a"); + arrayList.add("b"); + arrayList.add("c"); + arrayList.add("d"); + + strArray = new String[]{"a", "b", "c", "d"}; + } + + + @Test + public void sizeTest() { + Assert.assertEquals(4, arrayList.size(), 0); + } + + @Test + public void getTest() throws IndexOutOfBoundsException { + Assert.assertEquals("a", arrayList.get(0).toString()); + Assert.assertEquals("c", arrayList.get(2).toString()); + Assert.assertEquals("d", arrayList.get(3).toString()); + + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + arrayList.get(100); + arrayList.get(-1); + } + + @Test + public void iteratoreTest(){ + Iterator iterator = arrayList.iterator(); + int a = 0; + while (iterator.hasNext()){ + Assert.assertEquals(strArray[a], iterator.next().toString()); + a = a + 1; + } + } + + + @Test + public void addTest() { + arrayList.add("f"); + Assert.assertEquals("f", arrayList.get(4).toString()); + } + + @Test + public void removeTest() throws IndexOutOfBoundsException { + String r1 = arrayList.remove(1).toString(); + Assert.assertEquals("b", r1); + Assert.assertEquals(3, arrayList.size()); + + String r0 = arrayList.remove(0).toString(); + Assert.assertEquals("a", r0); + Assert.assertEquals(2, arrayList.size()); + + String rs = arrayList.remove(arrayList.size() - 1).toString(); + Assert.assertEquals("d", rs); + Assert.assertEquals(1, arrayList.size()); + + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + arrayList.remove(100); + + } + + + @Test + public void addIndexTest() throws IndexOutOfBoundsException { + arrayList.add(0, "0"); + Assert.assertEquals("0", arrayList.get(0).toString()); + arrayList.add(arrayList.size(), "s"); + Assert.assertEquals("s", arrayList.get(arrayList.size() - 1).toString()); + arrayList.add(2, "2a"); + Assert.assertEquals("2a", arrayList.get(2).toString()); + + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + arrayList.add(10, "10a"); + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/LinkedListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/LinkedListTest.java new file mode 100644 index 0000000000..486957915f --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/list/LinkedListTest.java @@ -0,0 +1,260 @@ +package me.lzb.basic.list; + +import me.lzb.basic.list.Iterator; +import me.lzb.basic.list.LinkedList; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + + +/** + * linkedliksTest + * Created by LZB on 2017/3/11. + */ +public class LinkedListTest { + + private LinkedList linkedList; + + private LinkedList intList; + + private String[] strArray; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void instantiate() throws Exception { + linkedList = new LinkedList(); + linkedList.add("a"); + linkedList.add("b"); + linkedList.add("c"); + linkedList.add("d"); + + strArray = new String[]{"a", "b", "c", "d"}; + + intList = new LinkedList(); + intList.add(0); + intList.add(1); + intList.add(2); + intList.add(3); + intList.add(4); + intList.add(5); + intList.add(6); + intList.add(7); + intList.add(8); + + } + + + @Test + public void iteratoreTest() { + Iterator iterator = linkedList.iterator(); + int a = 0; + while (iterator.hasNext()) { + Assert.assertEquals(strArray[a], iterator.next().toString()); + a = a + 1; + } + } + + + @Test + public void sizeTest() { + Assert.assertEquals(4, linkedList.size(), 0); + } + + @Test + public void getTest() throws IndexOutOfBoundsException { + Assert.assertEquals("a", linkedList.get(0).toString()); + Assert.assertEquals("b", linkedList.get(1).toString()); + Assert.assertEquals("d", linkedList.get(3).toString()); + + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + linkedList.get(100); + linkedList.get(-1); + } + + + @Test + public void addTest() { + linkedList.add("f"); + Assert.assertEquals("f", linkedList.get(4).toString()); + } + + @Test + public void removeTest() throws IndexOutOfBoundsException { + String r1 = linkedList.remove(1).toString(); + Assert.assertEquals("b", r1); + Assert.assertEquals(3, linkedList.size()); + + String r0 = linkedList.remove(0).toString(); + Assert.assertEquals("a", r0); + Assert.assertEquals(2, linkedList.size()); + + String rs = linkedList.remove(linkedList.size() - 1).toString(); + Assert.assertEquals("d", rs); + Assert.assertEquals(1, linkedList.size()); + + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + linkedList.remove(100); + linkedList.remove(-1); + } + + + @Test + public void addIndexTest() throws IndexOutOfBoundsException { + linkedList.add(0, "0"); + Assert.assertEquals("0", linkedList.get(0).toString()); + linkedList.add(linkedList.size(), "s"); + Assert.assertEquals("s", linkedList.get(linkedList.size() - 1).toString()); + linkedList.add(2, "2a"); + Assert.assertEquals("2a", linkedList.get(2).toString()); + thrown.expect(IndexOutOfBoundsException.class); + thrown.expectMessage("index boom"); + linkedList.add(100, "10a"); + + } + + + @Test + public void reverseTest() { + linkedList.reverse(); + Assert.assertEquals("[d,c,b,a]", linkedList.toString()); + } + + @Test + public void removeFirstHalfTest() { + intList.removeFirstHalf(); + Assert.assertEquals("[4,5,6,7,8]", intList.toString()); + Assert.assertEquals(5, intList.size()); + linkedList.removeFirstHalf(); + Assert.assertEquals("[c,d]", linkedList.toString()); + Assert.assertEquals(2, linkedList.size()); + } + + @Test + public void removeITest() { + intList.remove(0, 10); + Assert.assertEquals("[]", intList.toString()); + Assert.assertEquals(0, intList.size()); + + + linkedList.remove(1, 2); + Assert.assertEquals("[a,d]", linkedList.toString()); + Assert.assertEquals(2, linkedList.size()); + + + LinkedList l = new LinkedList(); + l.add("a"); + l.add("b"); + l.add("c"); + l.add("d"); + l.remove(0, 2); + Assert.assertEquals("[c,d]", l.toString()); + Assert.assertEquals(2, l.size()); + } + + + @Test + public void getElementsTest() { + int[] a = {1, 3, 4, 6}; + + LinkedList l = new LinkedList(); + l.add(1); + l.add(3); + l.add(4); + l.add(6); + int[] re = intList.getElements(l); + + Assert.assertEquals(a.length, re.length); + for (int i = 0; i < a.length; i++) { + Assert.assertEquals(a[i], re[i]); + } + + } + + + @Test + public void subtractTest() { + LinkedList l = new LinkedList(); + l.add(1); + l.add(3); + l.add(4); + l.add(6); + intList.subtract(l); + Assert.assertEquals(5, intList.size()); + Assert.assertEquals("[0,2,5,7,8]", intList.toString()); + } + + + @Test + public void removeDuplicateValuesTest() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(1); + list.add(2); + list.add(2); + list.add(3); + list.add(5); + list.add(5); + list.add(6); + list.removeDuplicateValues(); + + Assert.assertEquals("[1,2,3,5,6]", list.toString()); + } + + + @Test + public void removeRangeTest() { + { + LinkedList linkedList = new LinkedList(); + + linkedList.add(11); + linkedList.add(12); + linkedList.add(13); + linkedList.add(14); + linkedList.add(16); + linkedList.add(16); + linkedList.add(19); + + linkedList.removeRange(10, 19); + Assert.assertEquals("[19]", linkedList.toString()); + } + + { + LinkedList linkedList = new LinkedList(); + + linkedList.add(11); + linkedList.add(12); + linkedList.add(13); + linkedList.add(14); + linkedList.add(16); + linkedList.add(16); + linkedList.add(19); + + linkedList.removeRange(10, 14); + Assert.assertEquals("[14,16,16,19]", linkedList.toString()); + } + } + + + @Test + public void intersectionTest() { + LinkedList list1 = new LinkedList(); + list1.add(1); + list1.add(6); + list1.add(7); + + LinkedList list2 = new LinkedList(); + list2.add(2); + list2.add(5); + list2.add(6); + + LinkedList newList = list1.intersection(list2); + Assert.assertEquals("[6]", newList.toString()); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/JosephusTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..cc984089db --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/JosephusTest.java @@ -0,0 +1,29 @@ +package me.lzb.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + //6没死啊 + Assert.assertEquals("[1, 3, 5, 0, 4, 2]", Josephus.execute(7, 2).toString()); + + + Assert.assertEquals("[2, 5, 1, 6, 4]", Josephus.execute(7, 3).toString()); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/QueueTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/QueueTest.java new file mode 100644 index 0000000000..7c10394b40 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/queue/QueueTest.java @@ -0,0 +1,106 @@ +package me.lzb.basic.queue; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by LZB on 2017/4/27. + */ +public class QueueTest { + + + @Test + public void queueWithTwoStacksTest() { + QueueWithTwoStacks q = new QueueWithTwoStacks(); + Assert.assertTrue(q.isEmpty()); + Assert.assertEquals(0, q.size()); + + Object o; + + + q.enQueue("a"); + Assert.assertEquals("[a]1", q.toString() + q.size()); + + q.enQueue("b"); + Assert.assertEquals("[a,b]2", q.toString() + q.size()); + + q.enQueue("c"); + Assert.assertEquals("[a,b,c]3", q.toString() + q.size()); + + o = q.deQueue(); + Assert.assertEquals("[b,c]2", q.toString() + q.size()); + Assert.assertEquals("a", o.toString()); + + q.enQueue("d"); + Assert.assertEquals("[b,c,d]3", q.toString() + q.size()); + + + o = q.deQueue(); + Assert.assertEquals("[c,d]2", q.toString() + q.size()); + Assert.assertEquals("b", o.toString()); + + o = q.deQueue(); + Assert.assertEquals("[d]1", q.toString() + q.size()); + Assert.assertEquals("c", o.toString()); + + o = q.deQueue(); + Assert.assertEquals("[]0", q.toString() + q.size()); + Assert.assertEquals("d", o.toString()); + } + + public void circleQueueTest() { + CircleQueue q = new CircleQueue<>(5); + Assert.assertTrue(q.isEmpty()); + Assert.assertEquals(0, q.size()); + + q.enQueue("a"); + Assert.assertEquals("[a]1", q.toString() + q.size()); + + q.enQueue("b"); + Assert.assertEquals("[a,b]2", q.toString() + q.size()); + + q.enQueue("c"); + Assert.assertEquals("[a,b,c]3", q.toString() + q.size()); + + q.enQueue("d"); + Assert.assertEquals("[a,b,c,d]4", q.toString() + q.size()); + + q.enQueue("e"); + Assert.assertEquals("[a,b,c,d,e]5", q.toString() + q.size()); + + + q.enQueue("f"); + Assert.assertEquals("[b,c,d,e,f]5", q.toString() + q.size()); + + + Object o; + + o = q.deQueue(); + Assert.assertEquals("[c,d,e,f]4", q.toString() + q.size()); + Assert.assertEquals("b", o.toString()); + + + o = q.deQueue(); + Assert.assertEquals("[d,e,f]3", q.toString() + q.size()); + Assert.assertEquals("c", o.toString()); + + q.enQueue("g"); + Assert.assertEquals("[d,e,f,g]4", q.toString() + q.size()); + + o = q.deQueue(); + Assert.assertEquals("[e,f,g]3", q.toString() + q.size()); + Assert.assertEquals("d", o.toString()); + + o = q.deQueue(); + Assert.assertEquals("[f,g]2", q.toString() + q.size()); + Assert.assertEquals("e", o.toString()); + + o = q.deQueue(); + Assert.assertEquals("[g]1", q.toString() + q.size()); + Assert.assertEquals("f", o.toString()); + + o = q.deQueue(); + Assert.assertEquals("[]0", q.toString() + q.size()); + Assert.assertEquals("g", o.toString()); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackTest.java new file mode 100644 index 0000000000..da0b954a4a --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackTest.java @@ -0,0 +1,87 @@ +package me.lzb.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by LZB on 2017/5/4. + */ +public class StackTest { + + @Test + public void QuickMinStackTest() { + + QuickMinStack stack = new QuickMinStack(); + stack.push(1); + stack.push(3); + stack.push(0); + stack.push(2); + + Assert.assertEquals(0, stack.findMin()); + Assert.assertEquals(2, stack.pop()); + Assert.assertEquals(0, stack.findMin()); + Assert.assertEquals(0, stack.pop()); + Assert.assertEquals(1, stack.findMin()); + } + + @Test + public void StackWithTwoQueuesTest() { + StackWithTwoQueues stack = new StackWithTwoQueues(); + + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + Assert.assertEquals("[1,2,3,4]", stack.toString()); + Assert.assertEquals("4", String.valueOf(stack.pop())); + Assert.assertEquals("[1,2,3]", stack.toString()); + Assert.assertEquals("3", String.valueOf(stack.pop())); + Assert.assertEquals("[1,2]", stack.toString()); + } + + @Test + public void TwoStackInOneArrayTest() { + TwoStackInOneArray stack = new TwoStackInOneArray(); + + + stack.push1(1); + stack.push1(2); + stack.push1(3); + stack.push1(4); + stack.push1(5); + stack.push1(6); + Assert.assertEquals(6, stack.size1()); + + stack.push2(1); + stack.push2(2); + stack.push2(3); + stack.push2(4); + stack.push2(5); + stack.push2(6); + + + Assert.assertEquals("[1,2,3,4,5,6]|[1,2,3,4,5,6]", stack.toString()); + + Assert.assertEquals(6, stack.size1()); + + Assert.assertEquals(6, stack.peek1()); + + Assert.assertEquals(6, stack.peek2()); + + + Assert.assertEquals(6, stack.pop1()); + + Assert.assertEquals(6, stack.pop2()); + + Assert.assertEquals("[1,2,3,4,5]|[1,2,3,4,5]", stack.toString()); + + Assert.assertEquals(5, stack.pop1()); + Assert.assertEquals(4, stack.pop1()); + + Assert.assertEquals(5, stack.pop2()); + + Assert.assertEquals("[1,2,3]|[1,2,3,4]", stack.toString()); + + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackUtilTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..e07acade1b --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/stack/StackUtilTest.java @@ -0,0 +1,78 @@ +package me.lzb.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Stack; + +public class StackUtilTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAddToBottom() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + + StackUtil.addToBottom(s, 0); + + Assert.assertEquals("[0, 1, 2, 3]", s.toString()); + + } + @Test + public void testReverse() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + StackUtil.reverse(s); + Assert.assertEquals("[5, 4, 3, 2, 1]", s.toString()); + } + + @Test + public void testRemove() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + StackUtil.remove(s, 2); + Assert.assertEquals("[1, 3]", s.toString()); + } + + @Test + public void testGetTop() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + { + Object[] values = StackUtil.getTop(s, 3); + Assert.assertEquals(5, values[0]); + Assert.assertEquals(4, values[1]); + Assert.assertEquals(3, values[2]); + } + Assert.assertEquals("[1, 2, 3, 4, 5]", s.toString()); + } + + @Test + public void testIsValidPairs() { + Assert.assertTrue(StackUtil.isValidPairs("([e{d}f])")); + Assert.assertFalse(StackUtil.isValidPairs("([b{x]y})")); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinaryTreeUtilTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..6656fdfc4a --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/tree/BinaryTreeUtilTest.java @@ -0,0 +1,90 @@ +package me.lzb.basic.tree; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +/** + * @author LZB + */ +public class BinaryTreeUtilTest { + BinaryTreeNode root = null; + + @Before + public void setUp() throws Exception { + root = new BinaryTreeNode<>(1); + root.setLeft(new BinaryTreeNode<>(2)); + root.setRight(new BinaryTreeNode<>(5)); + root.getLeft().setLeft(new BinaryTreeNode<>(3)); + root.getLeft().setRight(new BinaryTreeNode<>(4)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + + + } + + @Test + public void testInOrderVisit() { + + + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[3, 2, 4, 1, 5]", result.toString()); + + } + + @Test + public void testPostOrderVisit() { + + + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[3, 4, 2, 5, 1]", result.toString()); + + } + + + + @Test + public void testPreOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode<>(6)); + node.setRight(new BinaryTreeNode<>(7)); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 6, 7, 5]", result.toString()); + + } + + @Test + public void testInOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode<>(6)); + node.setRight(new BinaryTreeNode<>(7)); + + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[3, 2, 6, 4, 7, 1, 5]", result.toString()); + + } + + @Test + public void testPostOrderWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode<>(6)); + node.setRight(new BinaryTreeNode<>(7)); + + List result = BinaryTreeUtil.postOrderWithoutRecursion(root); + Assert.assertEquals("[3, 6, 7, 4, 2, 5, 1]", result.toString()); + + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/pom.xml b/group24/1148285693/learning2017/mini-jvm/pom.xml new file mode 100644 index 0000000000..694ec40612 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/pom.xml @@ -0,0 +1,23 @@ + + + + learning2017 + me.lzb + 1.0 + + 4.0.0 + + mini-jvm + mini-jvm + 1.0 + + + + me.lzb + common + 1.0 + + + \ No newline at end of file diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java index 5fd864b8a8..32e0c24bdf 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java @@ -103,12 +103,12 @@ public void setClzIndex(ClassIndex 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()); + if (this.accessFlag.isPublicClass()) { + System.out.println("Access flag : public "); + } + System.out.println("Class Name:" + getClassName()); + + System.out.println("Super Class Name:" + getSuperClassName()); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java index 83eec1cbc7..a662e9a6ff 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/BiPushCmd.java @@ -2,7 +2,11 @@ import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.Heap; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class BiPushCmd extends OneOperandCmd { @@ -11,11 +15,20 @@ public BiPushCmd(ClassFile clzFile, String opCode) { } - @Override - public String toString(ConstantPool pool) { - return this.getOffset() + ": " + this.getOpCode() + " " + this.getReadableCodeText() + " " + this.getOperand(); + public String toString() { + return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " " + this.getOperand(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitBiPushCmd(this); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java index 07e35cb0ce..b79f7d7f2c 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/ByteCodeCommand.java @@ -3,6 +3,9 @@ import me.lzb.jvm.clz.ClassFile; import me.lzb.jvm.constant.ConstantInfo; import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; import java.util.HashMap; import java.util.Map; @@ -14,58 +17,99 @@ public abstract class ByteCodeCommand { ClassFile clzFile; private int offset; - private static Map codeMap = new HashMap(); + + 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 final String iload_0 = "1A"; + public static final String lload_0 = "1E"; + public static final String fload_2 = "24"; + + + private static Map codeMap = new HashMap<>(); static { - codeMap.put("01", "aconst_null"); + codeMap.put(aconst_null, "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(new_object, "new"); + codeMap.put(lstore, "lstore"); + codeMap.put(invokespecial, "invokespecial"); + codeMap.put(invokevirtual, "invokevirtual"); + codeMap.put(getfield, "getfield"); + codeMap.put(putfield, "putfield"); + codeMap.put(getstatic, "getstatic"); - codeMap.put("2A", "aload_0"); - codeMap.put("2B", "aload_1"); - codeMap.put("2C", "aload_2"); + codeMap.put(aload_0, "aload_0"); + codeMap.put(aload_1, "aload_1"); + codeMap.put(aload_2, "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(bipush, "bipush"); + codeMap.put(iload, "iload"); + codeMap.put(iload_0, "iload_0"); + codeMap.put(iload_1, "iload_1"); + codeMap.put(iload_2, "iload_2"); + codeMap.put(iload_3, "iload_3"); - codeMap.put("25", "fload_3"); + codeMap.put(fload_3, "fload_3"); - codeMap.put("1E", "lload_0"); + codeMap.put(lload_0, "lload_0"); - codeMap.put("24", "fload_2"); - codeMap.put("4C", "astore_1"); + codeMap.put(fload_2, "fload_2"); + codeMap.put(astore_1, "astore_1"); - codeMap.put("A2", "if_icmp_ge"); - codeMap.put("A4", "if_icmple"); + codeMap.put(if_icmp_ge, "if_icmp_ge"); + codeMap.put(if_icmple, "if_icmple"); codeMap.put("A7", "goto"); codeMap.put("B1", "return"); - codeMap.put("AC", "ireturn"); - codeMap.put("AE", "freturn"); + codeMap.put(ireturn, "ireturn"); + codeMap.put(freturn, "freturn"); - codeMap.put("03", "iconst_0"); - codeMap.put("04", "iconst_1"); + codeMap.put(iconst_0, "iconst_0"); + codeMap.put(iconst_1, "iconst_1"); - codeMap.put("3C", "istore_1"); - codeMap.put("3D", "istore_2"); + codeMap.put(istore_1, "istore_1"); + codeMap.put(istore_2, "istore_2"); - codeMap.put("59", "dup"); + codeMap.put(dup, "dup"); - codeMap.put("60", "iadd"); - codeMap.put("84", "iinc"); + codeMap.put(iadd, "iadd"); + codeMap.put(iinc, "iinc"); - codeMap.put("12", "ldc"); + codeMap.put(ldc, "ldc"); } @@ -86,7 +130,7 @@ public void setOffset(int offset) { this.offset = offset; } - protected ConstantInfo getConstantInfo(int index) { + public ConstantInfo getConstantInfo(int index) { return this.getClassFile().getConstantPool().getConstantInfo(index); } @@ -106,11 +150,11 @@ public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(this.opCode); - + buffer.append(":"); + buffer.append(this.codeMap.get(opCode)); return buffer.toString(); } - public abstract String toString(ConstantPool pool); public String getReadableCodeText() { String txt = codeMap.get(opCode); @@ -120,5 +164,7 @@ public String getReadableCodeText() { return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame, ExecutionResult result); + + public abstract void printExecute(ExecutionVisitor visitor); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java index a5fe80425b..27429d0695 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetFieldCmd.java @@ -2,7 +2,11 @@ import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.FieldRefInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class GetFieldCmd extends TwoOperandCmd { @@ -10,10 +14,25 @@ public GetFieldCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } + public String toString() { + + return super.getOperandAsField(); + } + + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); - return super.getOperandAsField(pool); + frame.getOprandStack().push(fieldValue); + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitGetFieldCmd(this); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java index 2d4d8d53a6..4144b0dae8 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/GetStaticFieldCmd.java @@ -1,7 +1,12 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.FieldRefInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.Heap; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -10,10 +15,29 @@ public GetStaticFieldCmd(ClassFile clzFile, String opCode) { } + public String toString() { + return super.getOperandAsField(); + } + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); - return super.getOperandAsField(pool); + if ("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)) { + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitGetStaticFieldCmd(this); } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java index 6af68455a0..de1b9d3493 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeSpecialCmd.java @@ -1,7 +1,12 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.MethodRefInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.MethodArea; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.method.Method; +import me.lzb.jvm.print.ExecutionVisitor; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -11,10 +16,32 @@ public InvokeSpecialCmd(ClassFile clzFile, String opCode) { } + + public String toString() { + return super.getOperandAsMethod(); + } + + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + // 不实现jang.lang.Object 的init方法 + if (methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")) { + return; - return super.getOperandAsMethod(pool); + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + //设定执行结果和下一个方法 + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitInvokeSpecialCmd(this); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java index 5d87c07505..caf195c206 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/InvokeVirtualCmd.java @@ -1,7 +1,13 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.MethodRefInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.MethodArea; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.method.Method; +import me.lzb.jvm.print.ExecutionVisitor; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -9,11 +15,73 @@ public InvokeVirtualCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } + public String toString() { + return super.getOperandAsMethod(); + } + + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if (isSystemOutPrintlnMethod(className, methodName)) { + JavaObject jo = (JavaObject) frame.getOprandStack().pop(); + String value = jo.toString(); + System.out.println("-------------------" + value + "----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); - return super.getOperandAsMethod(pool); + while (currentClassName != null) { + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if (m != null) { + + break; + + } else { + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if (m == null) { + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); } + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitInvokeVirtualCmd(this); + } + private boolean isSystemOutPrintlnMethod(String className, String methodName) { + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java index a34a64b5b0..8a8278fcb7 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/LdcCmd.java @@ -4,6 +4,11 @@ import me.lzb.jvm.constant.ConstantInfo; import me.lzb.jvm.constant.ConstantPool; import me.lzb.jvm.constant.StringInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.Heap; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class LdcCmd extends OneOperandCmd { @@ -11,10 +16,9 @@ public LdcCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } - @Override - public String toString(ConstantPool pool) { - ConstantInfo info = (ConstantInfo) pool.getConstantInfo(this.getOperand()); + public String toString() { + ConstantInfo info = getConstantInfo(this.getOperand()); String value = "TBD"; if (info instanceof StringInfo) { @@ -22,8 +26,30 @@ public String toString(ConstantPool pool) { value = strInfo.toString(); } - return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " " + value; + return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText() + " #" + getOperand() + " // String " + value; + } + + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = pool.getConstantInfo(this.getOperand()); + + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo) info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } else { + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + } + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitLdcCmd(this); } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java index ba7d9df3a7..4b6544b2ce 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NewObjectCmd.java @@ -1,7 +1,12 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.ClassInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.Heap; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class NewObjectCmd extends TwoOperandCmd { @@ -9,10 +14,27 @@ public NewObjectCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } + public String toString() { + return super.getOperandAsClassInfo(); + } + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + int index = this.getIndex(); + + ClassInfo info = (ClassInfo) this.getConstantInfo(index); + + String clzName = info.getClassName(); - return super.getOperandAsClassInfo(pool); + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + //压入栈顶 + frame.getOprandStack().push(jo); + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitNewObjectCmd(this); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java index 242f02716a..2657181e94 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/NoOperandCmd.java @@ -1,7 +1,11 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.Heap; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class NoOperandCmd extends ByteCodeCommand { @@ -9,11 +13,130 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } - @Override - public String toString(ConstantPool pool) { + public String toString() { return this.getOffset() + ":" + this.getOpCode() + " " + this.getReadableCodeText(); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + String opCode = this.getOpCode(); + + if (ByteCodeCommand.aload_0.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.aload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.aload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.fload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.voidreturn.equals(opCode)) { + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if (ByteCodeCommand.ireturn.equals(opCode)) { + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.freturn.equals(opCode)) { + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } else if (ByteCodeCommand.astore_1.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.dup.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iconst_0.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iconst_1.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.istore_1.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.istore_2.equals(opCode)) { + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if (ByteCodeCommand.iadd.equals(opCode)) { + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue() + jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)) { + + frame.getOprandStack().push(null); + + } else { + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitNoOperandCmd(this); + } + public int getLength() { return 1; diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java index 00805c5dc7..de9391fb56 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/OneOperandCmd.java @@ -12,7 +12,6 @@ public OneOperandCmd(ClassFile clzFile, String opCode) { } public int getOperand() { - return this.operand; } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java index df00e5bb8e..6d6efcc7fe 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/PutFieldCmd.java @@ -1,7 +1,13 @@ package me.lzb.jvm.cmd; import me.lzb.jvm.clz.ClassFile; -import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.constant.ClassInfo; +import me.lzb.jvm.constant.FieldRefInfo; +import me.lzb.jvm.constant.NameAndTypeInfo; +import me.lzb.jvm.engine.ExecutionResult; +import me.lzb.jvm.engine.JavaObject; +import me.lzb.jvm.engine.StackFrame; +import me.lzb.jvm.print.ExecutionVisitor; public class PutFieldCmd extends TwoOperandCmd { @@ -10,10 +16,31 @@ public PutFieldCmd(ClassFile clzFile, String opCode) { super(clzFile, opCode); } + public String toString() { + return super.getOperandAsField(); + } + @Override - public String toString(ConstantPool pool) { + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo) this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo) this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : + // TODO 这里不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); - return super.getOperandAsField(pool); + objectRef.setFieldValue(fieldName, fieldValue); + } + + @Override + public void printExecute(ExecutionVisitor visitor) { + visitor.visitPutFieldCmd(this); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java index b87faca257..b1c1ac7041 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/cmd/TwoOperandCmd.java @@ -35,27 +35,25 @@ public int getIndex() { return index; } - protected String getOperandAsClassInfo(ConstantPool pool) { + protected String getOperandAsClassInfo() { int index = getIndex(); String codeTxt = getReadableCodeText(); - ClassInfo info = (ClassInfo) pool.getConstantInfo(index); - return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " " + info.getClassName(); + ClassInfo info = (ClassInfo) getConstantInfo(index); + return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " #" + index + " " + "// class " + info.getClassName(); } - protected String getOperandAsMethod(ConstantPool pool) { + public String getOperandAsMethod() { 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(); + return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " #" + index + " // Method " + info.toString(); } - protected String getOperandAsField(ConstantPool pool) { + public String getOperandAsField() { int index = getIndex(); - String codeTxt = getReadableCodeText(); FieldRefInfo info = (FieldRefInfo) this.getConstantInfo(index); - return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " " + info.toString(); + return this.getOffset() + ":" + this.getOpCode() + " " + codeTxt + " #" + index + " // Field " + info.toString(); } public int getLength() { diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java index 36e77e84d9..6ceebd96aa 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java @@ -5,7 +5,7 @@ /** * Created by LZB on 2017/4/15. */ -public class FieldRefInfo extends ConstantInfo{ +public class FieldRefInfo extends ConstantInfo { private int type = ConstantInfo.Fieldref_info; private int classInfoIndex; @@ -14,6 +14,7 @@ public class FieldRefInfo extends ConstantInfo{ public FieldRefInfo(ConstantPool pool) { super(pool); } + @Override public int getType() { return type; @@ -39,4 +40,25 @@ public int getNameAndTypeIndex() { public void setNameAndTypeIndex(int nameAndTypeIndex) { this.nameAndTypeIndex = nameAndTypeIndex; } + + 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(); + } + + public String getClassName() { + ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex()); + UTF8Info utf8Info = (UTF8Info) this.getConstantInfo(classInfo.getUtf8Index()); + return utf8Info.getValue(); + } + + public String toString() { + NameAndTypeInfo typeInfo = (NameAndTypeInfo) this.getConstantInfo(this.getNameAndTypeIndex()); + return typeInfo.getName() + ":" + typeInfo.getTypeInfo(); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java index bd921ccf67..0755af98ed 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java @@ -40,4 +40,26 @@ public int getNameAndTypeIndex() { public void setNameAndTypeIndex(int nameAndTypeIndex) { this.nameAndTypeIndex = nameAndTypeIndex; } + + 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(); + } + + public String toString(){ + return this.getMethodName() + ":" + this.getParamAndReturnType() ; + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java index 4cef60cc3f..7d14bf3bdc 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java @@ -40,4 +40,21 @@ public int getIndex2() { public void setIndex2(int index2) { this.index2 = index2; } + + + 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(); + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java index 5d5fc284af..0af04e46bb 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java @@ -30,4 +30,9 @@ public int getIndex() { public void setIndex(int index) { this.index = index; } + + public String toString(){ + return getConstantPool().getUTF8String(index); + } + } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..9afe234cfa --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package me.lzb.jvm.engine; + + +import me.lzb.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + public void setNextAction(int action) { + this.nextAction = action; + } + + public boolean isPauseAndRunNewFrame() { + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + + public boolean isExitCurrentFrame() { + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd() { + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump() { + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..ff1840ab38 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/ExecutorEngine.java @@ -0,0 +1,68 @@ +package me.lzb.jvm.engine; + + +import me.lzb.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +public class ExecutorEngine { + + private Stack stack = new Stack<>(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod) { + StackFrame stackFrame = StackFrame.create(mainMethod); + stack.push(stackFrame); + + while (!stack.isEmpty()) { + StackFrame frame = stack.peek(); + ExecutionResult result = frame.execute(); + + if (result.isPauseAndRunNewFrame()) { + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + stack.push(nextFrame); + } else { + stack.pop(); + } + } + + } + + + private void setupFunctionCallParams(StackFrame currentFrame, StackFrame nextFrame) { + Method method = nextFrame.getMethod(); + List paramList = method.getParameterList(); + + //把this传过去 + int paramNum = paramList.size() + 1; + + + List values = new ArrayList<>(); + + //从调用函数的栈帧的操作数栈中,取出paramNum个参数,等下传入被调用函数 + for (int i = 0; i < paramNum; i++) { + values.add(currentFrame.getOprandStack().pop()); + } + + //因为栈是先入后出,为了保证传入顺序一致,对list进行逆转 + + List params = new ArrayList<>(); + for (int i = values.size() - 1; i >= 0; i--) { + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + + + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java new file mode 100644 index 0000000000..6d53f86871 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/Heap.java @@ -0,0 +1,43 @@ +package me.lzb.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + + private Heap() { + } + + public static Heap getInstance() { + return instance; + } + + public JavaObject newObject(String clzName) { + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value) { + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value) { + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + + public JavaObject newInt(int value) { + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..186d8be67d --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/JavaObject.java @@ -0,0 +1,82 @@ +package me.lzb.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue) { + fieldValues.put(fieldName, fieldValue); + } + + public JavaObject(int type) { + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setStringValue(String value) { + stringValue = value; + } + + public String getStringValue() { + return this.stringValue; + } + + public void setIntValue(int value) { + this.intValue = value; + } + + public int getIntValue() { + return this.intValue; + } + + public int getType() { + return type; + } + + public JavaObject getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public String toString() { + switch (this.getType()) { + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className + ":" + this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default: + return null; + } + } + + public String getClassName() { + return this.className; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..ffc3c641fc --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MethodArea.java @@ -0,0 +1,89 @@ +package me.lzb.jvm.engine; + + +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.constant.MethodRefInfo; +import me.lzb.jvm.loader.ClassFileLoader; +import me.lzb.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap<>(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) { + + ClassFile clzFile = findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className) { + + if (map.get(className) != null) { + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType) { + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if (m == null) { + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + + public Method getMethod(MethodRefInfo methodRef) { + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if (m == null) { + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..fac0c1bb34 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package me.lzb.jvm.engine; + +import me.lzb.jvm.loader.ClassFileLoader; + +import java.io.IOException; + + +public class MiniJVM { + + public void run(String[] classPaths, String className) throws IOException { + + ClassFileLoader loader = new ClassFileLoader(); + for (int i = 0; i < classPaths.length; i++) { + loader.addClassPath(classPaths[i]); + } + + MethodArea methodArea = MethodArea.getInstance(); + + methodArea.setClassFileLoader(loader); + + ExecutorEngine engine = new ExecutorEngine(); + + className = className.replace(".", "/"); + + engine.execute(methodArea.getMainMethod(className)); + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..ed641cd931 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/engine/StackFrame.java @@ -0,0 +1,129 @@ +package me.lzb.jvm.engine; + +import me.lzb.jvm.cmd.ByteCodeCommand; +import me.lzb.jvm.method.Method; +import me.lzb.jvm.print.ExecutionFormat; +import me.lzb.jvm.print.ExecutionVisitor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + + +public class StackFrame { + + private List localVariableTable = new ArrayList<>(); + private Stack oprandStack = new Stack<>(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + public static StackFrame create(Method m) { + + StackFrame frame = new StackFrame(m); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + public JavaObject getLocalVariableValue(int index) { + return this.localVariableTable.get(index); + } + + public Stack getOprandStack() { + return this.oprandStack; + } + + public int getNextCommandIndex(int offset) { + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for (int i = 0; i < cmds.length; i++) { + if (cmds[i].getOffset() == offset) { + return i; + } + } + throw new RuntimeException("Can't find next command"); + } + + public ExecutionResult execute() { + + ByteCodeCommand[] commands = m.getCmds(); + + + while (index < commands.length) { + + ExecutionResult result = new ExecutionResult(); + //缺省值是执行下一条命令 + result.setNextAction(ExecutionResult.RUN_NEXT_CMD); + + //输出执行的命令 + ExecutionVisitor format = ExecutionFormat.getInstance(); + commands[index].printExecute(format); + +// System.out.println(commands[index].toString()); + + commands[index].execute(this, result); + + if (result.isRunNextCmd()) { + index++; + } else if (result.isExitCurrentFrame()) { + return result; + } else if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } else if (result.isJump()) { + int offset = result.getNextCmdOffset(); + this.index = getNextCommandIndex(offset); + } else { + index++; + } + + } + + //当前StackFrmae的指令全部执行完毕,可以退出了 + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + } + + + public void setLocalVariableTable(List values) { + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo) { + //问题: 为什么要这么做?? + if (this.localVariableTable.size() - 1 < index) { + for (int i = this.localVariableTable.size(); i <= index; i++) { + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod() { + return m; + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileLoader.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileLoader.java index 593694066d..d8912cb1bb 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileLoader.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileLoader.java @@ -16,10 +16,6 @@ public class ClassFileLoader { private List clzPaths = new ArrayList<>(); public byte[] readBinaryCode(String className) throws IOException { -// String fileName = className.replaceAll(".*\\.", "") + ".class"; -// String pkg = className.replaceAll("\\.[^\\.]+$", ""); -// String packagePath = pkg.replaceAll("\\.", "\\\\"); - className = className.replace('.', File.separatorChar) + ".class"; for (String s : clzPaths) { byte[] data = FileUtils.readByteCodes(s + className); @@ -46,8 +42,13 @@ public String getClassPath() { } - public ClassFile loadClass(String className) throws IOException { - byte[] codes = this.readBinaryCode(className); + public ClassFile loadClass(String className) { + byte[] codes; + try { + codes = this.readBinaryCode(className); + } catch (IOException e) { + return null; + } ClassFileParser parser = new ClassFileParser(codes); return parser.parse(); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java index 829b1670c7..285ff441c7 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/CommandParser.java @@ -11,40 +11,6 @@ * Created by LZB on 2017/4/22. */ public class CommandParser { - public static final String aconst_null = "01"; - public static final String new_object = "BB"; - public static final String lstore = "37"; - public static final String invokespecial = "B7"; - public static final String invokevirtual = "B6"; - public static final String getfield = "B4"; - public static final String putfield = "B5"; - public static final String getstatic = "B2"; - public static final String ldc = "12"; - public static final String dup = "59"; - public static final String bipush = "10"; - public static final String aload_0 = "2A"; - public static final String aload_1 = "2B"; - public static final String aload_2 = "2C"; - public static final String iload = "15"; - public static final String iload_1 = "1B"; - public static final String iload_2 = "1C"; - public static final String iload_3 = "1D"; - public static final String fload_3 = "25"; - - public static final String voidreturn = "B1"; - public static final String ireturn = "AC"; - public static final String freturn = "AE"; - - public static final String astore_1 = "4C"; - public static final String if_icmp_ge = "A2"; - public static final String if_icmple = "A4"; - public static final String goto_no_condition = "A7"; - public static final String iconst_0 = "03"; - public static final String iconst_1 = "04"; - public static final String istore_1 = "3C"; - public static final String istore_2 = "3D"; - public static final String iadd = "60"; - public static final String iinc = "84"; private int index; @@ -74,6 +40,15 @@ private String nextCharsToString(int nextLength) { return String.valueOf(nextChars(nextLength)); } + + private String next2CharAsString() { + return nextCharsToString(2); + } + + private int next2CharAsInt() { + return nextCharsToInt(2); + } + private boolean hasNext() { return index < data.length; } @@ -81,67 +56,71 @@ private boolean hasNext() { public ByteCodeCommand[] parse(ClassFile clzFile) { + List cmds = new ArrayList<>(); while (hasNext()) { - String opCode = nextCharsToString(2); + String opCode = next2CharAsString(); - if (new_object.equals(opCode)) { + if (ByteCodeCommand.new_object.equals(opCode)) { NewObjectCmd cmd = new NewObjectCmd(clzFile, opCode); - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); cmds.add(cmd); - } else if (invokespecial.equals(opCode)) { + } else if (ByteCodeCommand.invokespecial.equals(opCode)) { InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); - - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); - + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); + // System.out.println( cmd.toString(clzFile.getConstPool())); cmds.add(cmd); - } else if (invokevirtual.equals(opCode)) { - InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); - - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); + } else if (ByteCodeCommand.invokevirtual.equals(opCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); cmds.add(cmd); - } else if (getfield.equals(opCode)) { + } else if (ByteCodeCommand.getfield.equals(opCode)) { GetFieldCmd cmd = new GetFieldCmd(clzFile, opCode); - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); - + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); cmds.add(cmd); - } else if (getstatic.equals(opCode)) { + } else if (ByteCodeCommand.getstatic.equals(opCode)) { GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, opCode); - - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); - + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); cmds.add(cmd); - } else if (putfield.equals(opCode)) { + } else if (ByteCodeCommand.putfield.equals(opCode)) { PutFieldCmd cmd = new PutFieldCmd(clzFile, opCode); - cmd.setOprand1(nextCharsToInt(2)); - cmd.setOprand2(nextCharsToInt(2)); + cmd.setOprand1(next2CharAsInt()); + cmd.setOprand2(next2CharAsInt()); cmds.add(cmd); - } else if (ldc.equals(opCode)) { + } else if (ByteCodeCommand.ldc.equals(opCode)) { LdcCmd cmd = new LdcCmd(clzFile, opCode); - cmd.setOperand(nextCharsToInt(2)); + cmd.setOperand(next2CharAsInt()); cmds.add(cmd); - } else if (bipush.equals(opCode)) { + } else if (ByteCodeCommand.bipush.equals(opCode)) { BiPushCmd cmd = new BiPushCmd(clzFile, opCode); - cmd.setOperand(nextCharsToInt(2)); + cmd.setOperand(next2CharAsInt()); cmds.add(cmd); - } else if (dup.equals(opCode) || aload_0.equals(opCode) || aload_1.equals(opCode) || aload_2.equals(opCode) - || iload_1.equals(opCode) || iload_2.equals(opCode) || iload_3.equals(opCode) - || fload_3.equals(opCode) || voidreturn.equals(opCode) || astore_1.equals(opCode)) { + } else if (ByteCodeCommand.dup.equals(opCode) + || ByteCodeCommand.aload_0.equals(opCode) + || ByteCodeCommand.aload_1.equals(opCode) + || ByteCodeCommand.aload_2.equals(opCode) + || ByteCodeCommand.iload_1.equals(opCode) + || ByteCodeCommand.iload_2.equals(opCode) + || ByteCodeCommand.iload_3.equals(opCode) + || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.voidreturn.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode)) { NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); cmds.add(cmd); } else { - throw new RuntimeException("Sorry, the java instruction " + opCode + "has not been implement."); + throw new RuntimeException("Sorry, the java instruction " + opCode + " has not been implemented"); } + } calcuateOffset(cmds); @@ -161,28 +140,28 @@ private static void calcuateOffset(List cmds) { } - 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(); - } - - } +// private static class CommandIterator { +// String codes = null; +// int pos = 0; +// +// CommandIterator(String codes) { +// this.codes = codes; +// } +// +// public boolean hasNext() { +// return pos < this.codes.length(); +// } +// +// public String next2CharAsString() { +// String result = codes.substring(pos, pos + 2); +// pos += 2; +// return result; +// } +// +// public int next2CharAsInt() { +// String s = this.next2CharAsString(); +// return Integer.valueOf(s, 16).intValue(); +// } +// +// } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java index 8c35d5aec5..43acd00549 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java @@ -1,8 +1,13 @@ package me.lzb.jvm.method; +import me.lzb.common.utils.StringUtils; import me.lzb.jvm.attr.CodeAttr; import me.lzb.jvm.clz.ClassFile; import me.lzb.jvm.cmd.ByteCodeCommand; +import me.lzb.jvm.constant.UTF8Info; + +import java.util.ArrayList; +import java.util.List; /** * Created by LZB on 2017/4/15. @@ -68,4 +73,63 @@ public void setClzFile(ClassFile clzFile) { public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + + private String getParamAndReturnType() { + UTF8Info paramAndReturnTypeInfo = (UTF8Info) getClzFile().getConstantPool().getConstantInfo(getDescriptorIndex()); + return paramAndReturnTypeInfo.getValue(); + } + + public List getParameterList() { + + //(Ljava/lang/String;I)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + + // Ljava/lang/String;I + String param = paramAndType.substring(first + 1, last); + + List paramList = new ArrayList<>(); + + if (StringUtils.isBlank(param)) { + return paramList; + } + + while (StringUtils.isNotBlank(param)) { + + int pos = 0; + // 这是一个对象类型 + if (param.charAt(pos) == 'L') { + + int end = param.indexOf(";"); + + if (end == -1) { + throw new RuntimeException("对象类型参数结尾没有\";\""); + } + paramList.add(param.substring(pos + 1, end)); + + pos = end + 1; + + } else if (param.charAt(pos) == 'I') { + // int + paramList.add("I"); + pos++; + + } else if (param.charAt(pos) == 'F') { + // float + paramList.add("F"); + pos++; + + } else { + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java index 0b1566669a..f5b008a41b 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ClassPrinter.java @@ -1,5 +1,6 @@ package me.lzb.jvm.print; +import me.lzb.common.utils.AppUtils; import me.lzb.jvm.clz.ClassFile; import me.lzb.jvm.constant.ConstantInfo; import me.lzb.jvm.constant.ConstantPool; @@ -13,9 +14,14 @@ public class ClassPrinter { private ConstantPool pool; + private int poolLong; + public ClassPrinter(ClassFile classFile) { this.classFile = classFile; this.pool = classFile.getConstantPool(); + + this.poolLong = AppUtils.getDigit(this.pool.getSize()); + } @@ -26,11 +32,28 @@ public void print() { System.out.println("Constant Pool:"); + for (int i = 1; i <= pool.getSize(); i++) { ConstantInfo constantInfo = pool.getConstantInfo(i); - System.out.print("#" + i + " = "); + System.out.print(dq(i) + " = "); constantInfo.print(visitor); } } + private String dq(int i) { + int iLong = AppUtils.getDigit(i); + + int c = poolLong - iLong; + + StringBuffer sb = new StringBuffer(); + if (c > 0) { + for (int j = 0; j < c; j++) { + sb.append(" "); + } + } + sb.append("#"); + sb.append(i); + return sb.toString(); + } + } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionFormat.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionFormat.java new file mode 100644 index 0000000000..2bcd612840 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionFormat.java @@ -0,0 +1,111 @@ +package me.lzb.jvm.print; + +import me.lzb.common.utils.StringUtils; +import me.lzb.jvm.cmd.*; +import me.lzb.jvm.constant.*; + +/** + * Created by LZB on 2017/5/1. + */ +public class ExecutionFormat implements ExecutionVisitor { + + private static final int one = 19; + + private static final int two = 19; + + private static ExecutionFormat format = null; + + public static ExecutionFormat getInstance() { + if (format == null) { + format = new ExecutionFormat(); + } + return format; + } + + private ExecutionFormat(){ + + } + + + @Override + public void visitBiPushCmd(BiPushCmd cmd) { + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + StringUtils.appendSpace(one, cmd.getReadableCodeText()) + cmd.getOperand()); + } + + @Override + public void visitGetFieldCmd(GetFieldCmd cmd) { + exFile(cmd); + } + + @Override + public void visitGetStaticFieldCmd(GetStaticFieldCmd cmd) { + exFile(cmd); + } + + @Override + public void visitInvokeSpecialCmd(InvokeSpecialCmd cmd) { + exMethod(cmd); + } + + @Override + public void visitInvokeVirtualCmd(InvokeVirtualCmd cmd) { + exMethod(cmd); + } + + @Override + public void visitLdcCmd(LdcCmd cmd) { + ConstantInfo info = cmd.getConstantInfo(cmd.getOperand()); + + String value = "TBD"; + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo) info; + value = strInfo.toString(); + } + + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + StringUtils.appendSpace(one, cmd.getReadableCodeText()) + "#" + StringUtils.appendSpace(two, cmd.getOperand() + "") + "// String " + value); + } + + @Override + public void visitNewObjectCmd(NewObjectCmd cmd) { + int index = cmd.getIndex(); + String codeTxt = cmd.getReadableCodeText(); + ClassInfo info = (ClassInfo) cmd.getConstantInfo(index); + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + StringUtils.appendSpace(one, codeTxt) + "#" + StringUtils.appendSpace(two, index + "") + "// class " + info.getClassName()); + } + + @Override + public void visitNoOperandCmd(NoOperandCmd cmd) { + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + cmd.getReadableCodeText()); + } + + @Override + public void visitPutFieldCmd(PutFieldCmd cmd) { + exFile(cmd); + } + + + private void exFile(TwoOperandCmd cmd) { + int index = cmd.getIndex(); + String codeTxt = cmd.getReadableCodeText(); + FieldRefInfo info = (FieldRefInfo) cmd.getConstantInfo(index); + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + StringUtils.appendSpace(one, codeTxt) + "#" + StringUtils.appendSpace(two, index + "") + "// Field " + info.toString()); + } + + private void exMethod(TwoOperandCmd cmd) { + int index = cmd.getIndex(); + String codeTxt = cmd.getReadableCodeText(); + MethodRefInfo info = (MethodRefInfo) cmd.getConstantInfo(index); + System.out.println(getOffset(cmd.getOffset()) + ":" + cmd.getOpCode() + " " + StringUtils.appendSpace(one, codeTxt) + "#" + StringUtils.appendSpace(two, index + "") + "// Method " + info.toString()); + } + + + private String getOffset(int offset) { + String s = String.valueOf(offset); + if (s.length() == 1) { + s = " " + s; + } + return s; + + + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionVisitor.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionVisitor.java new file mode 100644 index 0000000000..427894a6ed --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/ExecutionVisitor.java @@ -0,0 +1,29 @@ +package me.lzb.jvm.print; + +import me.lzb.jvm.cmd.*; + +/** + * Created by LZB on 2017/5/1. + */ +public interface ExecutionVisitor { + + void visitBiPushCmd(BiPushCmd cmd); + + void visitGetFieldCmd(GetFieldCmd cmd); + + void visitGetStaticFieldCmd(GetStaticFieldCmd cmd); + + void visitInvokeSpecialCmd(InvokeSpecialCmd cmd); + + void visitInvokeVirtualCmd(InvokeVirtualCmd cmd); + + void visitLdcCmd(LdcCmd cmd); + + void visitNewObjectCmd(NewObjectCmd cmd); + + void visitNoOperandCmd(NoOperandCmd cmd); + + void visitPutFieldCmd(PutFieldCmd cmd); + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java index 663496de8e..bf62883c21 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintFormat.java @@ -1,5 +1,6 @@ package me.lzb.jvm.print; +import me.lzb.common.utils.StringUtils; import me.lzb.jvm.clz.ClassFile; import me.lzb.jvm.constant.*; @@ -8,14 +9,15 @@ */ public class PrintFormat implements PrintVisitor { + private int FOURTEENTH = 14; @Override public void visitBasicMsg(ClassFile info) { System.out.println("Access flag : " + info.getAccessFlag().getFlagString()); - System.out.println("Class Name:" + info.getClassName()); + System.out.println("Class name:" + info.getClassName()); - System.out.println("Super Class Name:" + info.getSuperClassName()); + System.out.println("Super Class name:" + info.getSuperClassName()); System.out.println("minor version:" + info.getMinorVersion()); @@ -27,31 +29,35 @@ public void visitBasicMsg(ClassFile info) { @Override public void visistUTF8(UTF8Info info) { - System.out.println("UTF8 " + info.getValue()); + System.out.println("UTF8 " + info.getValue()); } @Override public void visitClassInfo(ClassInfo info) { - System.out.println("Class #" + info.getUtf8Index() + " " + info.getClassName()); + System.out.println("Class #" + StringUtils.appendSpace(FOURTEENTH, info.getUtf8Index() + "") + "// " + info.getClassName()); } @Override public void visitFieldRef(FieldRefInfo info) { - System.out.println("FieldRef #" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + System.out.println("FieldRef #" + StringUtils.appendSpace(FOURTEENTH, info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()) + "// " + info.getClassName() + ". " + info.toString()); } @Override public void visitMethodRef(MethodRefInfo info) { - System.out.println("MethodRef #" + info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()); + System.out.println("MethodRef #" + StringUtils.appendSpace(FOURTEENTH, info.getClassInfoIndex() + ".#" + info.getNameAndTypeIndex()) + "// " + info.getClassName() + ". " + info.toString()); } @Override public void visitNameAndType(NameAndTypeInfo info) { - System.out.println("NameAndType #" + info.getIndex1() + ":#" + info.getIndex2()); + // // + System.out.println("NameAndType #" + StringUtils.appendSpace(FOURTEENTH, info.getIndex1() + ":#" + info.getIndex2()) + "// " + info.toString()); } @Override public void visitString(StringInfo info) { - System.out.println("String #" + info.getIndex()); + System.out.println("String #" + StringUtils.appendSpace(FOURTEENTH, info.getIndex() + "") + "// " + info.toString()); } + + + } diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java index 6d846786bc..350d424cd1 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/print/PrintVisitor.java @@ -7,17 +7,17 @@ * Created by LZB on 2017/4/23. */ public interface PrintVisitor { - public void visitBasicMsg(ClassFile info); + void visitBasicMsg(ClassFile info); - public void visitClassInfo(ClassInfo info); + void visitClassInfo(ClassInfo info); - public void visitFieldRef(FieldRefInfo info); + void visitFieldRef(FieldRefInfo info); - public void visitMethodRef(MethodRefInfo info); + void visitMethodRef(MethodRefInfo info); - public void visitNameAndType(NameAndTypeInfo info); + void visitNameAndType(NameAndTypeInfo info); - public void visitString(StringInfo info); + void visitString(StringInfo info); - public void visistUTF8(UTF8Info info); + void visistUTF8(UTF8Info info); } diff --git a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java index b4adbcf888..a9f20b23c1 100644 --- a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java +++ b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java @@ -17,7 +17,6 @@ import org.junit.Before; import org.junit.Test; -import java.io.IOException; import java.util.List; @@ -98,21 +97,15 @@ public void testMagicNumber() throws Exception { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); - try { - clzFile = loader.loadClass(className); - } catch (IOException e) { - e.printStackTrace(); - } + clzFile = loader.loadClass(className); clzFile.print(); } @Test public void testVersion() { - Assert.assertEquals(0, clzFile.getMinorVersion()); Assert.assertEquals(52, clzFile.getMajorVersion()); - } @Test diff --git a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/MiniJVMTest.java b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/MiniJVMTest.java new file mode 100644 index 0000000000..0be0dea7c4 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/MiniJVMTest.java @@ -0,0 +1,28 @@ +package me.lzb.jvm; + +import me.lzb.jvm.engine.MiniJVM; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class MiniJVMTest { + + static String PATH = EmployeeV1.class.getResource("/").getPath(); + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "me.lzb.jvm.EmployeeV1"); + + } + +} diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/graph/Graph.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/graph/Graph.java deleted file mode 100644 index 5ef6aba81a..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/graph/Graph.java +++ /dev/null @@ -1,366 +0,0 @@ -package me.lzb.other.graph; - -import java.util.*; - -/** - * 遍历无向图的所有最长一笔画 - * 深度优先,达到最深时,后退,继续搜索另一条路径 - * Created by LZB on 2017/4/8. - */ -public class Graph { - /** - * 换行符 - */ - private static final String NEWLINE = System.getProperty("line.separator"); - /** - * 路径分割符号 - */ - private static final String PATH_SEPARATOR = "->"; - - /** - * 顶点数目 - */ - private int vertexCount; - - /** - * 边的数目 - */ - private int edgeCount; - - /** - * 出现过路径的最长变数 - * 如果等于总边数,说明存在欧拉路径 - */ - int maxEdge = 0; - - /** - * 顶点数组,每个list是与顶点关联的所有边 - */ - private LinkedList[] edgeList; - - /** - * 边 - */ - private class Edge { - /** - * 边的id - */ - int id; - - /** - * 是否被正向搜索 - */ - boolean isSearched; - - /** - * 顶点v - */ - int v; - - /** - * 顶点b - */ - int w; - - /** - * 保存回滚操作中,被回滚的的路径方向,以及,前提路径 - * 因为在不同级别的回滚中,可能会有多条临时路径,所以用list存放 - * 顶点->顶点:路径id->路径id->路径id - * 1->2:0->1->2 - */ - ArrayList to = new ArrayList<>(); - - /** - * 构造函数 - * @param v 顶点v - * @param w 顶点w - */ - public Edge(int v, int w) { - this.v = v; - this.w = w; - isSearched = false; - id = edgeCount; - } - - - /** - * 在当前前提路径下,是否有 - * @param v0 出发顶点 - * @param P 前提路径 - * @return true false - */ - public boolean isFrom(int v0, String P) { - return isTheSameTo(v0, getAnotherV(v0), P); - } - - /** - * 临时路径是否相同 - * @param v0 出发顶点 - * @param v1 到达顶点 - * @param p 前提路径 - * @return true false - */ - public boolean isTheSameTo(int v0, int v1, String p) { - if (to.size() == 0) { - return false; - } - String ss = v0 + PATH_SEPARATOR + v1 + ":" + p; - for (String s : to) { - if (ss.equals(s)) { - return true; - } - } - return false; - } - - /** - * 删除临时路径 - * @param v0 出发顶点 - * @param v1 到达顶点 - * @param p 前提路径 - */ - public void removeTo(int v0, int v1, String p) { - if (to.size() == 0) { - return; - } - String ss = v0 + PATH_SEPARATOR + v1 + ":" + p; - for (Iterator iterator = to.iterator(); iterator.hasNext(); ) { - String s = iterator.next(); - if (ss.equals(s)) { - iterator.remove(); - return; - } - } - } - - /** - * 增加临时路径 - * @param v0 出发顶点 - * @param v1 到达顶点 - * @param p 前提路径 - */ - public void addTo(int v0, int v1, String p) { - String ss = v0 + PATH_SEPARATOR + v1 + ":" + p; - for (String s : to) { - if (ss.equals(s)) { - return; - } - } - to.add(ss); - - } - - /** - * 获取边的另外一条顶点 - * @param vertex - * @return - */ - public int getAnotherV(int vertex) { - if (vertex == v) { - return w; - } else { - return v; - } - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - Edge c = (Edge) obj; - return this.id == c.id; - } - - @Override - public int hashCode() { - return id; - } - } - - /** - * 构造函数 - * @param vertexNum 顶点总数 - * @param edgeCount 边的总数 - */ - public Graph(int vertexNum, int edgeCount) { - this.vertexCount = vertexNum; - this.edgeCount = 0; - edgeList = new LinkedList[edgeCount]; - for (int i = 0; i < edgeCount; i++) { - edgeList[i] = new LinkedList<>(); - } - } - - public void addEdge(int v1, int v2) { - Edge c = new Edge(v2, v1); - edgeList[v1].add(c); - edgeList[v2].add(c); - edgeCount++; - } - - - public void addEdge(int[][] edgeArray) { - for (int i = 0; i < edgeArray.length; i++) { - addEdge(edgeArray[i][0], edgeArray[i][1]); - } - } - - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(vertexCount + " vertices, " + edgeCount + " edges " + NEWLINE); - for (int v = 0; v < vertexCount; v++) { - s.append(v + ": "); - for (Edge w : edgeList[v]) { - s.append(w.getAnotherV(v) + " "); - } - s.append(NEWLINE); - } - return s.toString(); - } - - - /** - * 更新出现过路径的最长边数 - * @param a - */ - private void updateMax(int a) { - if (a > maxEdge) { - maxEdge = a; - } - } - - - public boolean isEuler() { - int start = 0; - Stack stack = new Stack<>(); - stack.push(start); - - //TODO 退出递归的条件 -// try { - search(start, start, stack, new Stack<>()); -// }catch (EmptyStackException e){ - -// } - - System.out.println("最长边数:" + maxEdge); - return maxEdge == edgeCount; - } - - - - - /** - * 正向搜索 - * 传进去一个节点,顺着一条没有搜索过的边找到下一个节点。当搜索到死路时,回滚 - * @param v 当前提点 - * @param stack 当前路径的节点顺序 - * @param sp 当前路径的路径顺序 - */ - public void search(int start, int v, Stack stack, Stack sp) { - - LinkedList list = edgeList[v]; - - boolean anotherWay = false; - for (Edge w : list) { - if (!w.isSearched && !w.isTheSameTo(v, w.getAnotherV(v), getPath(sp))) { - anotherWay = true; - w.isSearched = true; - stack.push(w.getAnotherV(v)); - updateMax(sp.size()); - sp.push(w); - search(start, w.getAnotherV(v), stack, sp); - } - } - - if (!anotherWay) { - System.out.println("最长:==============================="); - rollback(start, stack, sp); - } - - } - - - - /** - * 回滚,回滚当上一个节点,如果当前节点有可以使用的边,调用搜索,如果没有,递归继续回滚 - * 如果需要递归回滚,回滚到第二级之前,清空所有,当前路径下,从该点出发的方向 - * 被回滚的路径,需要保存路径方向,以及提前路径 - * @param stack 当前路径的节点顺序 - * @param sp 当前路径的路径顺序 - */ - public void rollback(int start, Stack stack, Stack sp) { - - String ss = getPath(sp); - String output = "顶点:" + stack.toString() - + NEWLINE + "路径:" + ss - + NEWLINE; - System.out.println(output); - -// if(stack.size() == 1){ -// return; -// } - - - Edge e = sp.pop(); //需要回滚的路径 - String pp = getPath(sp); //前提路径 - - int vz = stack.pop(); - int vy = stack.peek(); - - boolean rollbakc2 = true; - - LinkedList l = edgeList[vy]; - - //判断当前节点是否存在空闲路径,是否要回滚两级 - //空闲路径:没有被正向搜索,也没有被缓存当前前提路径下,从改节点出发的方向 - for (Edge w : l) { - if (!w.isSearched && !w.isTheSameTo(vy, w.getAnotherV(vy), pp)) { - rollbakc2 = false; - break; - } - } - - - //回滚当前路径,回滚一级 - int r = vy; - for (Edge w : l) { - if (w.equals(e)) { - w.addTo(vy, vz, pp); - w.isSearched = false; - break; - } - } - - if (rollbakc2) { - //回滚两级, 清空所有,当前路径下,从该点出发的方向 - - for (Edge w : l) { - if (!w.isSearched && w.isFrom(vy, pp)) { - w.removeTo(vy, w.getAnotherV(vy), pp); - } - } - rollback(start, stack, sp); - } - - search(start, r, stack, sp); - - } - - public String getPath(Stack stack) { - String s = ""; - for (Edge x : stack) { - s = s + x.id + PATH_SEPARATOR; - } - s = s.replaceAll(PATH_SEPARATOR + "$", ""); - return s; - } - - - public static void main(String[] args) { - int[][] aa = new int[][]{{0, 1}, {0, 1}, {0, 3}, {1, 3}, {1, 2}, {1, 2}, {2, 3}}; - Graph g = new Graph(4, aa.length); - g.addEdge(aa); - System.out.println(g.toString()); - System.out.println(g.isEuler()); - } -} diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest1.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest1.java deleted file mode 100644 index 4b8b3d4ce8..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest1.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.lzb.other.lock; - -/** - * Created by LZB on 2017/3/30. - */ -public class ReentrantTest1 implements Runnable{ - - public synchronized void get(){ - System.out.println(Thread.currentThread().getId()); - set(); - } - - public synchronized void set(){ - System.out.println(Thread.currentThread().getId()); - } - - @Override - public void run() { - get(); - } - public static void main(String[] args) { - ReentrantTest1 ss=new ReentrantTest1(); - new Thread(ss).start(); - new Thread(ss).start(); - new Thread(ss).start(); - } -} \ No newline at end of file diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest2.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest2.java deleted file mode 100644 index c630ea9e33..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest2.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.lzb.other.lock; - -import java.util.concurrent.locks.ReentrantLock; - -/** - * Created by LZB on 2017/3/30. - */ -public class ReentrantTest2 implements Runnable { - ReentrantLock lock = new ReentrantLock(); - - public void get() { - lock.lock(); - System.out.println(Thread.currentThread().getId()); - set(); - lock.unlock(); - } - - public void set() { - lock.lock(); - System.out.println(Thread.currentThread().getId()); - lock.unlock(); - } - - @Override - public void run() { - get(); - } - - public static void main(String[] args) { - ReentrantTest2 ss = new ReentrantTest2(); - new Thread(ss).start(); - new Thread(ss).start(); - new Thread(ss).start(); - } -} \ No newline at end of file diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/MyInvocationHandler.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/MyInvocationHandler.java deleted file mode 100644 index d89298c786..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/MyInvocationHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -package me.lzb.other.proxy; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * Created by LZB on 2017/3/29. - */ -public class MyInvocationHandler implements InvocationHandler { - - // 目标对象 - private Object target; - - /** - * 构造方法 - * - * @param target 目标对象 - */ - public MyInvocationHandler(Object target) { - super(); - this.target = target; - } - - - /** - * 执行目标对象的方法 - */ - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - - // 在目标对象的方法执行之前简单的打印一下 - System.out.println("------------------before------------------"); - - // 执行目标对象的方法 - Object result = method.invoke(target, args); - - // 在目标对象的方法执行之后简单的打印一下 - System.out.println("-------------------after------------------"); - - return result; - } - - /** - * 获取目标对象的代理对象 - * - * @return 代理对象 - */ - public Object getProxy() { - return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - target.getClass().getInterfaces(), this); - } -} diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserService.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserService.java deleted file mode 100644 index d57431acab..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserService.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.lzb.other.proxy; - -/** - * Created by LZB on 2017/3/29. - */ -public interface UserService { - /** - * 目标方法 - */ - void add(); -} diff --git a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserServiceImpl.java b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserServiceImpl.java deleted file mode 100644 index 614b60d9c9..0000000000 --- a/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserServiceImpl.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.lzb.other.proxy; - -/** - * Created by LZB on 2017/3/29. - */ -public class UserServiceImpl implements UserService { - - public void add() { - System.out.println("--------------------add---------------"); - } -} \ No newline at end of file diff --git a/group24/1148285693/learning2017/other/src/test/java/me/lzb/other/proxy/ProxyTest.java b/group24/1148285693/learning2017/other/src/test/java/me/lzb/other/proxy/ProxyTest.java deleted file mode 100644 index 0a01679ad3..0000000000 --- a/group24/1148285693/learning2017/other/src/test/java/me/lzb/other/proxy/ProxyTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.lzb.other.proxy; - -import org.junit.Test; - -/** - * Created by LZB on 2017/3/29. - */ -public class ProxyTest { - - @Test - public void testProxy() throws Throwable { - // 实例化目标对象 - UserService userService = new UserServiceImpl(); - - // 实例化InvocationHandler - MyInvocationHandler invocationHandler = new MyInvocationHandler(userService); - - // 根据目标对象生成代理对象 - UserService proxy = (UserService) invocationHandler.getProxy(); - - // 调用代理对象的方法 - proxy.add(); - - } -} diff --git a/group24/1148285693/learning2017/pom.xml b/group24/1148285693/learning2017/pom.xml index 8dc41781ba..5fd8108696 100644 --- a/group24/1148285693/learning2017/pom.xml +++ b/group24/1148285693/learning2017/pom.xml @@ -1,155 +1,161 @@ - - - 4.0.0 - - me.lzb - learning2017 - 1.0 - learning2017 - pom - - https://github.com/lzbferrari/coding2017 - 2017编程提高 - - - - lzb - https://github.com/lzbferrari - lzbferrari@gmail.com - - - - - common - learning-basic - mini-jvm - other - - - - 1.8 - 1.8 - UTF-8 - UTF-8 - UTF-8 - - - - - - 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 - - - - - org.apache.httpcomponents - httpclient - 4.5.3 - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - ${java.version} - ${java.version} - UTF-8 - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.19.1 - - - org.apache.maven.surefire - surefire-junit47 - 2.19.1 - - - - false - - - - - + + + 4.0.0 + + me.lzb + learning2017 + 1.0 + learning2017 + pom + + https://github.com/lzbferrari/coding2017 + 2017编程提高 + + + + lzb + https://github.com/lzbferrari + lzbferrari@gmail.com + + + + + common + learning-basic + mini-jvm + + + + 1.8 + 1.8 + UTF-8 + UTF-8 + UTF-8 + + + + + + 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 + + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + ${java.version} + ${java.version} + UTF-8 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + + + org.apache.maven.surefire + surefire-junit47 + 2.19.1 + + + + false + true + 1 + false + + ${java.io.tmpdir} + + + + + + \ No newline at end of file diff --git a/group24/121111914/.classpath b/group24/121111914/.classpath index 3e9442280c..23c456e3e2 100644 --- a/group24/121111914/.classpath +++ b/group24/121111914/.classpath @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/ArrayList.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/ArrayList.java deleted file mode 100644 index e9c2a390fb..0000000000 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/ArrayList.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.github.ipk2015.coding2017.basic; - -import java.util.Arrays; - -public class ArrayList implements List { - - private int size = 0; - - private Object[] elementData = new Object[100]; - - public void add(Object o){ - add(size,o); - } - /* - * 分两种情况,index的范围为0到size,超出则抛出异常 - * */ - public void add(int index, Object o){ - ListUtils.checkIndexInRange(index,size); - if(size==elementData.length){ - elementData=Arrays.copyOf(elementData, size+1); - } - if(indexindex;i--){ - elementData[i]=elementData[i-1]; - } - } - elementData[index]=o; - size++; - } - - public Object get(int index){ - ListUtils.checkIndexInRange(index,size-1); - return elementData[index]; - } - - public Object remove(int index){ - ListUtils.checkIndexInRange(index,size-1); - Object object=elementData[index]; - for(int i=index;iindex;i--){ + elementData[i]=elementData[i-1]; + } + } + elementData[index]=o; + size++; + } + + public Object get(int index){ + ListUtils.checkIndexInRange(index,size-1); + return elementData[index]; + } + + public Object remove(int index){ + ListUtils.checkIndexInRange(index,size-1); + Object object=elementData[index]; + for(int i=index;i list= new ArrayList(); + for(int i=0;i=array[i+1]){ + throw new RuntimeException("不是排序好的数组"); + } + } + } + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + * @param oldArray + * @param size + * @return + */ + public int[] grow(int [] oldArray, int size){ + int[] newArray=new int[oldArray.length+size]; + for(int i=0;i list=new ArrayList(); + list.add(1); + list.add(1); + int size=2; + int lastElement=2; + while(lastElement list=new ArrayList(); + list.add(2); + for(int i=3;i list=new ArrayList(); + for(int i=2;i + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + private int size = 0; + public boolean isEmpty() { + return size == 0; + + } + + public int size() { + return size; + } + + + + public void enQueue(E data) { + if(size == DEFAULT_SIZE){ + throw new RuntimeException("queue size is max"); + } + elementData[rear] = data; + rear = (rear+1)%DEFAULT_SIZE; + size++; + } + + public E deQueue() { + if(size == 0){ + throw new RuntimeException("queue size is 0"); + } + E e = (E)elementData[front]; + elementData[front] = null; + front = (front+1)%DEFAULT_SIZE; + size--; + return e; + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Josephus.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..ea50564c1f --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Josephus.java @@ -0,0 +1,38 @@ +package com.github.ipk2015.coding2017.basic.queue; + + + +import java.util.ArrayList; +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 queue = new CircleQueue(); + for(int i = 0;i list = new ArrayList(); + Integer element = null; + while(!queue.isEmpty()){ + element = (Integer) queue.deQueue(); + if(i == m){ + list.add(element); + i = 1; + }else{ + queue.enQueue(element); + i++; + } + } + return list; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/JosephusTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d319ce304 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.github.ipk2015.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Queue.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Queue.java new file mode 100644 index 0000000000..e880b1f0af --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/Queue.java @@ -0,0 +1,21 @@ +package com.github.ipk2015.coding2017.basic.queue; + +import com.github.ipk2015.coding2017.basic.linkedlist.LinkedList; + +public class Queue { + private LinkedList elementDatas=new LinkedList(); + public void enQueue(Object o){ + elementDatas.add(o); + } + public Object deQueue(){ + return elementDatas.removeFirst(); + } + + public boolean isEmpty(){ + return size()==0; + } + + public int size(){ + return elementDatas.size(); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/QueueWithTwoStacks.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..c9e724aa4a --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,56 @@ +package com.github.ipk2015.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() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size()+stack2.size(); + } + + + + public void enQueue(E item) { + stack1.push(item); + } + + public E deQueue() { + if(size() == 0){ + throw new RuntimeException("queue size is 0"); + } + if(stack2.isEmpty()){ + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + return stack2.pop(); + } + + + + } + diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/QuickMinStack.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..9f044cc1f9 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/QuickMinStack.java @@ -0,0 +1,37 @@ +package com.github.ipk2015.coding2017.basic.stack; + +import java.util.HashMap; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + private Stack normalStack = new Stack(); + private Stack minStack = new Stack(); + public void push(int data){ + normalStack.push(data); + if(minStack.isEmpty()){ + minStack.push(data); + }else{ + if(data <= (Integer)minStack.peek()){ + minStack.push(data); + } + } + } + public int pop(){ + int element = (Integer)normalStack.pop(); + if(element == (Integer)minStack.peek()){ + minStack.pop(); + } + return element; + } + public int peek(){ + return (Integer)normalStack.peek(); + } + public int findMin(){ + return (Integer)minStack.peek(); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/Stack.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/Stack.java index ddb9b62dda..ca448a3862 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/Stack.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/Stack.java @@ -2,7 +2,9 @@ import java.util.EmptyStackException; -import com.github.ipk2015.coding2017.basic.ArrayList; +import com.github.ipk2015.coding2017.basic.array.ArrayList; + + public class Stack { private ArrayList elementData = new ArrayList(); diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/StackWithTwoQueues.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..7d6da60917 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,42 @@ +package com.github.ipk2015.coding2017.basic.stack; + +import com.github.ipk2015.coding2017.basic.queue.Queue; + +public class StackWithTwoQueues { + + private Queue queue1 = new Queue(); + private Queue queue2 = new Queue(); + + public void push(Object data) { + queue1.enQueue(data); + } + + public Object pop() { + if(queue1.size() == 1){ + return queue1.deQueue(); + } + if(queue2.isEmpty()){ + moveElements(queue1,queue2); + } + return queue2.deQueue(); + } + + private void moveElements(Queue oirQueue,Queue aimQueue){ + if(oirQueue.isEmpty()){ + return; + }else{ + Object element = oirQueue.deQueue(); + moveElements(oirQueue,aimQueue); + aimQueue.enQueue(element); + } + } + + public boolean isEmpty(){ + return queue1.isEmpty() && queue2.isEmpty(); + } + + public int size(){ + return queue1.size()+queue2.size(); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/TwoStackInOneArray.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..e8e8488fe6 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,83 @@ +package com.github.ipk2015.coding2017.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + private int pointer1 = 0; + private int pointer2 = 9; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if(pointer1 == pointer2){ + enlargeDataArray(); + } + data[pointer1++] = o; + } + + private void enlargeDataArray(){ + Object[] newData = new Object[data.length+100]; + for(int i = 0;i < pointer1;i++){ + newData[i] = data[i]; + } + for(int i = pointer2+1;i < data.length;i++){ + newData[i+100] = data[i]; + } + pointer2 += 100; + data = newData; + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + Object object = data[pointer1-1]; + data[pointer1-1] = null; + pointer1--; + return object; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return data[pointer1-1]; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if(pointer1 == pointer2){ + enlargeDataArray(); + } + data[pointer2--] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + Object object = data[pointer2+1]; + data[pointer2+1] = null; + pointer2++; + return object; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return data[pointer2+1]; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/ArrayListTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/ArrayListTest.java index 72a9a84b66..43f1e50ca9 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/ArrayListTest.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/ArrayListTest.java @@ -5,7 +5,9 @@ import org.junit.Before; import org.junit.Test; -import com.github.ipk2015.coding2017.basic.ArrayList; +import com.github.ipk2015.coding2017.basic.array.ArrayList; + + public class ArrayListTest { ArrayList list; diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QueueTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QueueTest.java index 53c63d8564..f27c7b22f2 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QueueTest.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QueueTest.java @@ -5,7 +5,7 @@ import org.junit.Before; import org.junit.Test; -import com.github.ipk2015.coding2017.basic.Queue; +import com.github.ipk2015.coding2017.basic.queue.Queue; public class QueueTest { Queue queue; diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QuickMinStackTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QuickMinStackTest.java new file mode 100644 index 0000000000..f976861dbb --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/test/QuickMinStackTest.java @@ -0,0 +1,56 @@ +package com.github.ipk2015.coding2017.basic.test; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.github.ipk2015.coding2017.basic.stack.QuickMinStack; + +public class QuickMinStackTest { + QuickMinStack stack; + @Before + public void setUp() throws Exception { + stack = new QuickMinStack(); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPush() { + stack.push(11); + assertEquals(11, stack.peek()); + stack.push(22); + assertEquals(22, stack.peek()); + } + + @Test + public void testPop() { + stack.push(11); + stack.push(22); + stack.push(33); + assertEquals(33, stack.pop()); + assertEquals(22, stack.pop()); + assertEquals(11, stack.pop()); + } + + @Test + public void testFindMin() { + + stack.push(4); + stack.push(2); + stack.push(3); + stack.push(5); + assertEquals(2, stack.findMin()); + stack.pop(); + assertEquals(2, stack.findMin()); + stack.pop(); + assertEquals(2, stack.findMin()); + stack.pop(); + assertEquals(4, stack.findMin()); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/coderising/array/ArrayUtil.java b/group24/121111914/src/com/github/ipk2015/coding2017/coderising/array/ArrayUtil.java deleted file mode 100644 index d1ddfb6339..0000000000 --- a/group24/121111914/src/com/github/ipk2015/coding2017/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.github.ipk2015.coding2017.coderising.array; - - - -import java.util.ArrayList; -import java.util.Arrays; - -public class ArrayUtil { - /** - * 给定一个整形数组a , 对该数组的值进行置换 - 例如: a = [7, 9 , 30, 3] , 置换后为 [3, 30, 9,7] - 如果 a = [7, 9, 30, 3, 4] , 置换后为 [4,3, 30 , 9,7] - * @param origin - * @return - */ - public void reverseArray(int[] origin){ - int temp=0; - for(int i=0;i list= new ArrayList(); - for(int i=0;i=array[i+1]){ - throw new RuntimeException("不是排序好的数组"); - } - } - } - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - * @param oldArray - * @param size - * @return - */ - public int[] grow(int [] oldArray, int size){ - int[] newArray=new int[oldArray.length+size]; - for(int i=0;i list=new ArrayList(); - list.add(1); - list.add(1); - int size=2; - int lastElement=2; - while(lastElement list=new ArrayList(); - list.add(2); - for(int i=3;i list=new ArrayList(); - for(int i=2;i list = getMethods(); for(Method m : list){ + String name = ((UTF8Info)pool.getConstantInfo(m.getNameIndex())).getValue(); String desc = ((UTF8Info)pool.getConstantInfo(m.getDescriptorIndex())).getValue(); if(name.equalsIgnoreCase(methodName) && desc.equalsIgnoreCase(paramAndReturnType)){ diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/BiPushCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/BiPushCmd.java index 80d3076ea1..66f2ac6275 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/BiPushCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/BiPushCmd.java @@ -2,6 +2,10 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.Heap; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -15,6 +19,13 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int operand = this.getOperand(); + JavaObject newInt = Heap.getInstance().newInt(operand); + frame.getOprandStack().push(newInt); + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/ByteCodeCommand.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/ByteCodeCommand.java index f2c72d31f1..fb10cd1cfe 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/ByteCodeCommand.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/ByteCodeCommand.java @@ -8,6 +8,8 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; @@ -18,6 +20,41 @@ public abstract class ByteCodeCommand { ClassFile clzFile; private int offset; + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private static Map codeMap = new HashMap(); static{ @@ -128,5 +165,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java index ad694d7eec..55679f4223 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -15,6 +19,16 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + FieldRefInfo fieldRefInfo = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRefInfo.getFieldName(); + JavaObject javaObject = frame.getOprandStack().pop(); + JavaObject fieldValue = javaObject.getFieldValue(fieldName); + frame.getOprandStack().push(fieldValue); + } + diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java index 87bfca3c7f..81f7d534c4 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/GetStaticFieldCmd.java @@ -2,6 +2,11 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.Heap; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -16,4 +21,25 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + }else{ + throw new RuntimeException("className:"+className + +",fieldName:"+fieldName + +",fieldType:"+fieldType + +",not included"); + } + + } + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java index e573129d76..9a0bfa0376 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeSpecialCmd.java @@ -2,6 +2,11 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.MethodArea; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; +import com.github.ipk2015.coding2017.minijvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -16,6 +21,20 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method method = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(method); + } + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java index 989c3f6fae..f4aa2b403c 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/InvokeVirtualCmd.java @@ -2,6 +2,12 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.MethodArea; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; +import com.github.ipk2015.coding2017.minijvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -15,6 +21,40 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if("java/io/PrintStream".equals(className) && "println".equals(methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + System.err.println("-------------------"+jo.toString()+"----------------"); + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + return; + } + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject javaObject = frame.getOprandStack().peek(); + MethodArea methodArea = MethodArea.getInstance(); + Method m = null; + String currentClassName = javaObject.getClassName(); + while(null != currentClassName){ + ClassFile currentClassFile = methodArea.findClassFile(currentClassName); + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), methodRefInfo.getParamAndReturnType()); + if(null != m){ + break; + }else{ + currentClassName = currentClassFile.getSuperClassName(); + } + } + if(null == m){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(m); + } + diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java index bc72a9f300..76e1d8dc64 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; import com.github.ipk2015.coding2017.minijvm.constant.StringInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.Heap; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -25,5 +29,20 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantPool pool = this.getConstantPool(); + ConstantInfo constantInfo = pool.getConstantInfo(this.getOperand()); + if(constantInfo instanceof StringInfo){ + StringInfo stringInfo = (StringInfo)constantInfo; + String value = stringInfo.toString(); + JavaObject javaObject = Heap.getInstance().newString(value); + frame.getOprandStack().push(javaObject); + }else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java index 973061d110..168e2b3626 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NewObjectCmd.java @@ -1,7 +1,13 @@ package com.github.ipk2015.coding2017.minijvm.cmd; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.Heap; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -15,5 +21,12 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassInfo classInfo = (ClassInfo)this.getConstantInfo(this.getIndex()); + JavaObject newObject = Heap.getInstance().newObject(classInfo.getClassName()); + frame.getOprandStack().push(newObject); + } + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java index 62c51c2b3a..0d65211c65 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/NoOperandCmd.java @@ -2,6 +2,10 @@ import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.Heap; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -20,4 +24,122 @@ public int getLength(){ return 1; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { +String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + } + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java index e73ff203d5..30d315d25b 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/cmd/PutFieldCmd.java @@ -1,7 +1,14 @@ package com.github.ipk2015.coding2017.minijvm.cmd; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantInfo; import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.FieldRefInfo; +import com.github.ipk2015.coding2017.minijvm.constant.NameAndTypeInfo; +import com.github.ipk2015.coding2017.minijvm.engine.ExecutionResult; +import com.github.ipk2015.coding2017.minijvm.engine.JavaObject; +import com.github.ipk2015.coding2017.minijvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -15,5 +22,19 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + ClassInfo classInfo = (ClassInfo)this.getConstantInfo(fieldRefInfo.getClassInfoIndex()); + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRefInfo.getNameAndTypeIndex()); + // for example : name + String fieldName = nameAndTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameAndTypeInfo.getTypeInfo(); + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + objectRef.setFieldValue(fieldName, fieldValue); + } + } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutionResult.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..41fe9c7771 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.github.ipk2015.coding2017.minijvm.engine; + +import com.github.ipk2015.coding2017.minijvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutorEngine.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..6906922ee4 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/ExecutorEngine.java @@ -0,0 +1,55 @@ +package com.github.ipk2015.coding2017.minijvm.engine; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +import com.github.ipk2015.coding2017.minijvm.method.Method; + + + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + StackFrame stackFrame = StackFrame.create(mainMethod); + stack.push(stackFrame); + + while(!stack.isEmpty()){ + StackFrame frame = stack.peek(); + ExecutionResult executionResult = frame.execute(); + if(executionResult.isPauseAndRunNewFrame()){ + Method nextMethod = executionResult.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + stack.push(nextFrame); + }else{ + stack.pop(); + } + } + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + Method nextMethod = nextFrame.getMethod(); + List parameterList = nextMethod.getParameterList(); + + int paramSize = parameterList.size()+1; + List params = new ArrayList(); + while(paramSize > 0){ + params.add(currentFrame.getOprandStack().pop()); + paramSize--; + } + Collections.reverse(params); + nextFrame.setLocalVariableTable(params); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/Heap.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/Heap.java new file mode 100644 index 0000000000..bfef12886a --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.github.ipk2015.coding2017.minijvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/JavaObject.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/JavaObject.java new file mode 100644 index 0000000000..07d2084f0a --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.github.ipk2015.coding2017.minijvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MethodArea.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MethodArea.java new file mode 100644 index 0000000000..a4041c88bd --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MethodArea.java @@ -0,0 +1,82 @@ +package com.github.ipk2015.coding2017.minijvm.engine; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; +import com.github.ipk2015.coding2017.minijvm.loader.ClassFileLoader; +import com.github.ipk2015.coding2017.minijvm.method.Method; + + + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + className = className.replace('.', File.separatorChar); + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + ClassFile clz = this.findClassFile(className); + Method method = clz.getMethod(methodName, paramAndReturnType); + if(null == method){ + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + return method; + } + + + public Method getMethod(MethodRefInfo methodRef){ + ClassFile classFile = this.findClassFile(methodRef.getClassName()); + Method method = classFile.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + if(null == method){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + return method; + + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MiniJVM.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MiniJVM.java new file mode 100644 index 0000000000..45174b341f --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/engine/MiniJVM.java @@ -0,0 +1,30 @@ +package com.github.ipk2015.coding2017.minijvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.github.ipk2015.coding2017.minijvm.loader.ClassFileLoader; + + + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileLoader.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileLoader.java index 2f854174dd..0f6e9ed144 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileLoader.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileLoader.java @@ -28,12 +28,10 @@ public class ClassFileLoader { 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){ + if(codes != null && codes.length>0){ return codes; } } @@ -53,7 +51,7 @@ private byte[] loadClassFile(String clzFileName) { return IOUtils.toByteArray(new FileInputStream(f)); } catch (IOException e) { - e.printStackTrace(); +// e.printStackTrace(); return null; } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileParser.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileParser.java index b12e564b88..1c77ba1bfe 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileParser.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileParser.java @@ -164,7 +164,7 @@ private void meetUTF8Info(ConstantPool pool,ByteCodeIterator iter){ private void parseInterfaces(ByteCodeIterator iter) { int interfaceCount = iter.nextUNToInt(2); - System.out.println("interfaceCount:" + interfaceCount); +// System.out.println("interfaceCount:" + interfaceCount); // TODO : 如果实现了interface, 这里需要解析 } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java index b8a3d7dca2..ff4df81b1c 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java @@ -1,5 +1,8 @@ package com.github.ipk2015.coding2017.minijvm.method; +import java.util.ArrayList; +import java.util.List; + import com.github.ipk2015.coding2017.minijvm.attr.AttributeInfo; import com.github.ipk2015.coding2017.minijvm.attr.CodeAttr; import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; @@ -84,4 +87,62 @@ public String toString() { buffer.append(this.codeAttr.toString(pool)); return buffer.toString(); } + private String getParamAndReturnType(){ + UTF8Info nameAndTypeInfo = (UTF8Info)this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + public List getParameterList(){ + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first+1, last); + + List paramList = new ArrayList(); + + if((null == param) || "".equals(param)){ + return paramList; + } + + while(!param.equals("")){ + + int pos = 0; + // 这是一个对象类型 + if(param.charAt(pos) == 'L'){ + + int end = param.indexOf(";"); + + if(end == -1){ + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos+1,end)); + + pos = end + 1; + + } + else if(param.charAt(pos) == 'I'){ + // int + paramList.add("I"); + pos ++; + + } + else if(param.charAt(pos) == 'F'){ + // float + paramList.add("F"); + pos ++; + + } else{ + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } } diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java index 213046188c..a39c797c26 100644 --- a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java @@ -47,7 +47,7 @@ public class ClassFileloaderTest { // String className = "com.coderising.jvm.test.EmployeeV1"; String className = "EmployeeV1";//老师的class文件单独放在这里,只有类名 - clzFile = loader.loadClass(className); + clzFile = loader.loadClass(FULL_QUALIFIED_CLASS_NAME); clzFile.print(); } @@ -79,9 +79,7 @@ public void testClassFileLength() { ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path3); - String className = "EmployeeV1"; - - byte[] byteCodes = loader.readBinaryCode(className); + byte[] byteCodes = loader.readBinaryCode(FULL_QUALIFIED_CLASS_NAME); // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 Assert.assertEquals(1056, byteCodes.length); @@ -93,8 +91,7 @@ public void testClassFileLength() { public void testMagicNumber(){ ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path3); - String className = "EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); + byte[] byteCodes = loader.readBinaryCode(FULL_QUALIFIED_CLASS_NAME); byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; @@ -137,7 +134,7 @@ public void testConstantPool(){ ConstantPool pool = clzFile.getConstantPool(); - System.out.println(""+pool.getSize()); + System.out.println("pool size:"+pool.getSize()); Assert.assertEquals(53, pool.getSize()); { diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/MiniJVMTest.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..16019f78ce --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/MiniJVMTest.java @@ -0,0 +1,43 @@ +package com.github.ipk2015.coding2017.minijvm.test; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.github.ipk2015.coding2017.minijvm.engine.MiniJVM; + +public class MiniJVMTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test() { + MiniJVM jvm = new MiniJVM(); + String[] classPaths = new String[3]; + classPaths[0] = ClassFileloaderTest.path1; + classPaths[1] = ClassFileloaderTest.path2; + classPaths[2] = ClassFileloaderTest.path3; + String className = "com.coderising.jvm.test.EmployeeV1"; + try { + jvm.run(classPaths, className); + Assert.assertEquals(0,0); + } catch (IOException e) { + // TODO Auto-generated catch block + + e.printStackTrace(); + Assert.assertEquals(0,1); + } + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coderising2017/array/ArrayUtil.java b/group24/315863321/src/main/java/com/johnChnia/coderising2017/array/ArrayUtil.java index 3126dafc53..53a0305753 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coderising2017/array/ArrayUtil.java +++ b/group24/315863321/src/main/java/com/johnChnia/coderising2017/array/ArrayUtil.java @@ -1,6 +1,6 @@ package com.johnChnia.coderising2017.array; -import com.johnChnia.coding2017.basic.Queue; +import com.johnChnia.coding2017.basic.queue.Queue; import com.johnChnia.coding2017.basic.ArrayList; diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/ArrayList.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/ArrayList.java index 80bb60298e..1d48b259f8 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/ArrayList.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/ArrayList.java @@ -1,11 +1,13 @@ package com.johnChnia.coding2017.basic; import java.util.Arrays; +import java.util.Iterator; +import java.util.NoSuchElementException; /** * Created by john on 2017/3/8. * - * @// TODO: 2017/4/1 实现Iterator 接口 + * @// TODO: 学会多线程后,实现Iterator 的 remove 方法 */ public class ArrayList implements List { @@ -138,8 +140,32 @@ public int size() { return size; } + @Override + public Iterator iterator() { + return new Itr(); + } - /** + + private class Itr implements Iterator { + int cursor = 0; + @Override + public boolean hasNext() { + return cursor != size; + } + + @Override + public E next() { + int i = cursor; + if (i >= size) { + throw new NoSuchElementException(); + } + Object[] elementData = ArrayList.this.elementData; + cursor = i + 1; + return (E) elementData[i]; + } + } + + /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the double length of list. */ @@ -148,6 +174,25 @@ private void grow() { 2 * elementData.length); } + public boolean contains(Object o) { + Itr itr = new Itr(); + if (o == null) { + while (itr.hasNext()) { + if (itr.next() == null) { + return true; + } + } + + } else { + while (itr.hasNext()) { + if (itr.next().equals(o)) { + return true; + } + } + } + return false; + } + public String toString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("["); diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/BinarySearchTree.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/BinarySearchTree.java index 48d3e41b12..a574b04794 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/BinarySearchTree.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/BinarySearchTree.java @@ -1,5 +1,7 @@ package com.johnChnia.coding2017.basic; +import com.johnChnia.coding2017.basic.queue.Queue; + /** * Created by john on 2017/3/13. */ diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/List.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/List.java index 6d5a8b01df..7a399de95f 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/List.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/List.java @@ -1,16 +1,23 @@ package com.johnChnia.coding2017.basic; +import java.util.Iterator; + /** * Created by john on 2017/3/12. */ -public interface List { - public void add(E o); +public interface List extends Iterable{ + void add(E o); + + void add(int index, E o); + + E get(int index); + + E remove(int index); - public void add(int index, E o); + int size(); - public E get(int index); + Iterator iterator(); - public E remove(int index); + boolean contains(Object o); - public int size(); } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Queue.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Queue.java deleted file mode 100644 index 4d8449a8eb..0000000000 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Queue.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.johnChnia.coding2017.basic; - -import java.util.NoSuchElementException; - -/** - * Created by john on 2017/3/10. - * @// TODO: 2017/4/1 实现Iterator - */ -public class Queue { - - private ArrayList arrayList; - - /** - * Constructs an queue using 10 capacity of ArrayList. - */ - public Queue() { - arrayList = new ArrayList<>(); - } - - - /** - * Inserts the specified element into this queue.returning - * {@code true} upon success. - * if no space is currently available. - * - * @param element the element to add - * @return {@code true} - */ - public boolean add(E element) { - arrayList.add(element); - return true; - } - - /** - * Retrieves and removes the head of this queue,throws an exception - * if this queue is empty. - * - * @return the head of this queue - * @throws NoSuchElementException if this queue is empty - */ - public E remove() { - if (arrayList.empty()) - throw new NoSuchElementException(emptyMsg()); - return arrayList.remove(0); - - } - - - /** - * Retrieves, but does not remove, the head of this queue, - * or returns {@code null} if this queue is empty. - * - * @return the head of this queue, or {@code 0} if this queue is empty - */ - public Object peek() { - if (arrayList.empty()) - return 0; - return arrayList.get(0); - } - - - public String toString() { - return arrayList.toString(); - } - - /** - * Returns the number of elements in this queue. - * - * @return the number of elements in this queue. - */ - public int size() { - return arrayList.size(); - } - - /** - * Constructs an NoSuchElementException detail message. - * Of the many possible refactorings of the error handling code, - * this "outlining" performs best with both server and client VMs. - */ - private String emptyMsg() { - return "Size: " + size(); - } - - public boolean empty() { - return arrayList.size() == 0; - } -} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LinkedList.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LinkedList.java index 10f7edd0a6..4359918e74 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LinkedList.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LinkedList.java @@ -2,12 +2,13 @@ import com.johnChnia.coding2017.basic.List; +import java.util.Iterator; import java.util.NoSuchElementException; /** * Created by john on 2017/3/9. * - * @// TODO: 2017/4/1 支持Iterator + * @// TODO: 学会多线程后,实现Iterator 的 remove 方法 */ public class LinkedList implements List { @@ -223,6 +224,40 @@ public int size() { return size; } + @Override + public Iterator iterator() { + return new Itr(); + } + + @Override + public boolean contains(Object o) { + return false; + } + + private class Itr implements Iterator { + /** + * Index of element to be returned by subsequent call to next. + */ + int cursor = 0; + + + @Override + public boolean hasNext() { + return cursor != size(); + } + + @Override + public E next() { + int i = cursor; + if (i >= size) { + throw new NoSuchElementException(); + } + E next = get(i); + cursor = i + 1; + return next; + } + } + private void checkElementIndex(int index) { if (!isElementIndex(index)) { throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/CircleQueue.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..4fbe2ee11e --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/CircleQueue.java @@ -0,0 +1,104 @@ +package com.johnChnia.coding2017.basic.queue; + +/** + * Created by john on 2017/5/6. + * + * NOTE:循环队列下一个为(i+1)%N,上一个为(i+N-1)%N + */ +public class CircleQueue { + private int rear = -1; + private int front = -1; + private Object[] array; + private static final int DEFAULTCAPACITY = 10; + + + /** + * 构造一个空的循环队列 + */ + public CircleQueue() { + array = new Object[DEFAULTCAPACITY]; + } + + /** + * 根据传进来的容量构造循环队列 + * + * @param capacity 队列容量 + */ + public CircleQueue(int capacity) { + array = new Object[capacity]; + } + + /** + * 循环队列长度 + * + * @return 队列长度 + */ + public int size() { + return array.length; + } + + /** + * 判断队列是否已经满了 + * + * @return 如果队列满的话返回true,否则返回false + */ + public boolean isFull() { + if ((rear + 1) % size() == front) { + return true; + } + return false; + } + + /** + * 判断队列是否为空 + * + * @return 如果队列为空返回true,否则返回false + */ + public boolean isEmpty() { + if (rear == -1 && front == -1) { + return true; + } + return false; + } + + /** + * 入队操作 + */ + public void enQueue(int item) throws Exception { + if (isFull()) { + throw new Exception("队列已满"); + } else if (isEmpty()) { + rear++; + front = rear; + array[rear] = item; + } else { + rear = (rear + 1) % size(); + array[rear] = item; + } + } + + /** + * 出队操作 + */ + public void deQueue() throws Exception { + if (isEmpty()) { + throw new Exception("队列为空"); + } else if (front == rear) { + front = -1; + rear = -1; + } else { + front = (front + 1) % size(); + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (int i = 0; i <= size() - 1; i++) { + sb.append(array[i]); + sb.append(", "); + } + sb.append(")"); + return sb.toString(); + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Josephus.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..942b11cf68 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Josephus.java @@ -0,0 +1,31 @@ +package com.johnChnia.coding2017.basic.queue; + + +import com.johnChnia.coding2017.basic.ArrayList; +import com.johnChnia.coding2017.basic.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * 参考 http://interactivepython.org/courselib/static/pythonds/BasicDS/SimulationHotPotato.html + * + * @author john + */ +public class Josephus { + + public static List execute(int n, int m) { + ArrayList arrayList = new ArrayList<>(); + Queue queue = new Queue<>(); + for (int i = 0; i < n; i++) { + queue.add(i); + } + while (queue.size() > 1) { + for (int i = 0; i < m - 1; i++) { + queue.add(queue.remove()); + } + arrayList.add(queue.remove()); + } + return arrayList; + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/JosephusTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..ec71728b3e --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.johnChnia.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, ]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Queue.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Queue.java new file mode 100644 index 0000000000..4d82ad0c92 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/Queue.java @@ -0,0 +1,89 @@ +package com.johnChnia.coding2017.basic.queue; + +import com.johnChnia.coding2017.basic.ArrayList; + +import java.util.NoSuchElementException; + +/** + * Created by john on 2017/3/10. + * @// TODO: 2017/4/1 实现Iterator + */ +public class Queue { + + private ArrayList arrayList; + + /** + * Constructs an queue using 10 capacity of ArrayList. + */ + public Queue() { + arrayList = new ArrayList<>(); + } + + + /** + * Inserts the specified element into this queue.returning + * {@code true} upon success. + * if no space is currently available. + * + * @param element the element to add + * @return {@code true} + */ + public boolean add(E element) { + arrayList.add(element); + return true; + } + + /** + * Retrieves and removes the head of this queue,throws an exception + * if this queue is empty. + * + * @return the head of this queue + * @throws NoSuchElementException if this queue is empty + */ + public E remove() { + if (arrayList.empty()) + throw new NoSuchElementException(emptyMsg()); + return arrayList.remove(0); + + } + + + /** + * Retrieves, but does not remove, the head of this queue, + * or returns {@code null} if this queue is empty. + * + * @return the head of this queue, or {@code 0} if this queue is empty + */ + public Object peek() { + if (arrayList.empty()) + return 0; + return arrayList.get(0); + } + + + public String toString() { + return arrayList.toString(); + } + + /** + * Returns the number of elements in this queue. + * + * @return the number of elements in this queue. + */ + public int size() { + return arrayList.size(); + } + + /** + * Constructs an NoSuchElementException detail message. + * Of the many possible refactorings of the error handling code, + * this "outlining" performs best with both server and client VMs. + */ + private String emptyMsg() { + return "Size: " + size(); + } + + public boolean empty() { + return arrayList.size() == 0; + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacks.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..3fa8bb82fa --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,71 @@ +package com.johnChnia.coding2017.basic.queue; + + +import com.johnChnia.coding2017.basic.stack.Stack; + +/** + * Created by john on 2017/5/6. + * + * 参考:https://leetcode.com/articles/implement-queue-using-stacks/ + */ + +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + + + public QueueWithTwoStacks() { + stack1 = new Stack(); // 队列 + stack2 = new Stack(); + } + + + public boolean isEmpty() { + if (stack1.empty()) { + return true; + } + return false; + } + + + public int size() { + if (stack1.empty()) { + return -1; + } + return stack1.size(); + } + + + /** + * 如果stack1为空,则直接加到stack1中,如果不为空,首先遍历stack1中元素全放入stack2中,再把item加入 + * stack1中,最后再遍历stack2中元素重新放回stack1中。 + * + * @param item 入队值 + */ + public void enQueue(E item) { + while (!stack1.empty()) { + stack2.push(stack1.pop()); + } + stack1.push(item); + while (!stack2.empty()) { + stack1.push(stack2.pop()); + } + } + + /** + * 出队列操作 + * + * @return 如果队列为空就返回null,否则根据先进先出原则返回元素。 + */ + public E deQueue() { + if (isEmpty()) { + return null; + } + return stack1.pop(); + } + + public String toString() { + return stack1.toString(); + } +} + diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/QuickMinStack.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..a7031bf81e --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/QuickMinStack.java @@ -0,0 +1,72 @@ +package com.johnChnia.coding2017.basic.stack; + +/** + * Created by john on 2017/5/7. + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * 参考:http://www.programcreek.com/2014/02/leetcode-min-stack-java/ + * + * @author john + */ + + +public class QuickMinStack { + + private static class Elem { + int value; + int min; + Elem next; + + Elem(int value, int min) { + this.value = value; + this.min = min; + } + } + + private Elem top; + + + public QuickMinStack() { + + } + + + public void push(int data) { + if (top == null) { + Elem e = new Elem(data, data); + top = e; + } else { + Elem temp = new Elem(data, Math.min(data, top.min)); + temp.next = top; + top = temp; + } + } + + public int pop() { + if (top == null) { + return -1; + } else { + Elem temp = top.next; + top.next = null; + top = temp; + return top.value; + } + } + + public int findMin() { + if (top == null) { + return -1; + } + return top.min; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + while (top != null) { + sb.append(top.value); + sb.append(","); + top = top.next; + } + return sb.toString(); + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueues.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..156d042158 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,33 @@ +package com.johnChnia.coding2017.basic.stack; + +import com.johnChnia.coding2017.basic.queue.Queue; + +/** + * Created by john on 2017/5/7. + */ +public class StackWithTwoQueues { + + Queue queue1 = new Queue<>(); + Queue queue2 = new Queue<>(); + + public void push(int data) { + while (!queue1.empty()) { + queue2.add(queue1.remove()); + } + queue1.add(data); + while (!queue2.empty()) { + queue1.add(queue2.remove()); + } + } + + public int pop() { + if (!queue1.empty()) { + return queue1.remove(); + } + return -1; + } + + public String toString() { + return queue1.toString(); + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArray.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..75e6d15207 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,121 @@ +package com.johnChnia.coding2017.basic.stack; + +/** + * Created by john on 2017/5/7. + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + * @author john + */ +public class TwoStackInOneArray { + private Object[] data = new Object[4]; + private int pointer1 = -1; + private int pointer2 = data.length; + + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + ensureCapacityInternal(); + data[++pointer1] = o; + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() throws Exception { + if (pointer1 == -1) { + throw new Exception("栈1中没有元素"); + } else { + return data[pointer1--]; + } + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() throws Exception { + if (pointer1 == -1) { + throw new Exception("栈1中没有元素"); + } else { + return data[pointer1]; + } + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + ensureCapacityInternal(); + data[--pointer2] = o; + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + if (pointer2 == data.length) { + return null; + } else { + return data[pointer2++]; + } + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + if (pointer2 == data.length) { + return null; + } else { + return data[pointer2]; + } + } + + /** + * 如果栈1的指针和栈2的指针之差为1的话,那么就需要扩容。 + */ + private void ensureCapacityInternal() { + if (pointer2 - pointer1 == 1) { + grow(); + } + } + + private void grow() { + Object[] data2 = new Object[data.length * 2]; + System.arraycopy(data, 0, data2, 0, pointer1 + 1); //复制栈1值到data2 + int desPosForStack2 = data2.length - pointer2; + System.arraycopy(data, pointer2, data2, desPosForStack2, pointer2); // 复制栈2值到data2 + data = data2; + pointer2 = desPosForStack2; // 调整栈2指针位置 + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("("); + for (int i = 0; i <= pointer1; i++) { + sb.append(data[i]); + sb.append(", "); + } + for (int j = pointer2; j < data.length; j++) { + sb.append(data[j]); + sb.append(", "); + } + sb.append(")"); + return sb.toString(); + } + +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java index e47a8841da..3eb4a38819 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixExprTest.java @@ -8,45 +8,49 @@ public class InfixExprTest { - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testEvaluate() { - //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); - { - InfixExpr expr = new InfixExpr("2+3*4+5"); - Assert.assertEquals(19.0, expr.evaluate(), 0.001f); - } - { - InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); - Assert.assertEquals(100.0, expr.evaluate(), 0.001f); - } - - { - InfixExpr expr = new InfixExpr("3*20/2"); - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } - - { - InfixExpr expr = new InfixExpr("20/2*3"); - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } - - { - InfixExpr expr = new InfixExpr("10-30+50"); - Assert.assertEquals(30, expr.evaluate(), 0.001f); - } - { - InfixExpr expr = new InfixExpr("10-2*3+50"); - Assert.assertEquals(54, expr.evaluate(), 0.001f); - } - - } + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + { + InfixExpr expr = new InfixExpr("2+3*4+5"); + Assert.assertEquals(19.0, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*(3+50)"); + Assert.assertEquals(-96, expr.evaluate(), 0.001f); + } + + } } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java index e361815f02..1efa28721f 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/InfixToPostfix.java @@ -8,6 +8,10 @@ /*** * Rule: + * 1、如果栈不为空且操作符的优先级比栈顶高且不是(、【、{,则弹出栈顶,并且放到Expr中 + * 2、如果为(、[、{ 则压入栈顶 + * 3、如果为)、]、}且栈不为空,且栈顶不为(、[、{,则弹出栈顶,并且放到Expr中,最后弹出(、[、{ + * 4、遍历剩下的operator,加入到Expr中 */ public class InfixToPostfix { @@ -21,11 +25,19 @@ public static List convert(String expr) { if (token.isNumber()) { list.add(token); } else if (token.isOperator()) { - while (!stack.empty() && !token.hasHigherPriority(stack.peek())) { - list.add(stack.pop()); + while (!stack.empty() + && !token.isOpeningParentheses() + && !token.hasHigherPriority(stack.peek())) { + list.add(stack.pop()); } stack.push(token); - + } else if (token.isOpeningParentheses()) { + stack.push(token); + } else if (token.isClosingParentheses()) { + while (!stack.empty() && !stack.peek().isOpeningParentheses()) { + list.add(stack.pop()); + } + stack.pop(); } } while (!stack.empty()) { diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java index f87a210587..3f99cdf609 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/Token.java @@ -6,45 +6,60 @@ 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 int getIntValue() { - return Integer.valueOf(value).intValue(); - } - 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; - } - - + public static final List OPERATORS = Arrays.asList("+", "-", "*", "/"); + public static final List OPENINGPARENTHESES = Arrays.asList("(", "[", "{"); + public static final List CLOSINGPARENTHESES = Arrays.asList(")", "]", "}"); + private static final Map priorities = new HashMap<>(); + static { + priorities.put("+", 1); + priorities.put("-", 1); + priorities.put("*", 2); + priorities.put("/", 2); + priorities.put("(", 0); + priorities.put("[", 0); + priorities.put("{", 0); + } + + static final int OPERATOR = 1; + static final int NUMBER = 2; + static final int PARENTHESES = 3; + 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 int getIntValue() { + return Integer.valueOf(value).intValue(); + } + + 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; + } + + public boolean isOpeningParentheses() { + return OPENINGPARENTHESES.contains(this.value); + } + + public boolean isClosingParentheses() { + return CLOSINGPARENTHESES.contains(this.value); + } } \ No newline at end of file diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java index b9c8b80444..e66e4ff8c0 100644 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/expr/TokenParser.java @@ -30,6 +30,10 @@ public List parse(String expr) { tokens.add(t); i = nextOperatorIndex; + } else if (isParentheses(c)) { + Token t = new Token(Token.PARENTHESES, String.valueOf(c)); + tokens.add(t); + i++; } else { System.out.println("char :[" + c + "] is not number or operator,ignore"); i++; @@ -55,4 +59,9 @@ private boolean isOperator(char c) { String sc = String.valueOf(c); return Token.OPERATORS.contains(sc); } + + private boolean isParentheses(char c) { + String sc = String.valueOf(c); + return Token.OPENINGPARENTHESES.contains(sc) || Token.CLOSINGPARENTHESES.contains(sc); + } } diff --git a/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java b/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java index a300edafc7..47ac60b253 100644 --- a/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java +++ b/group24/315863321/src/main/java/jvm/loader/ClassFileLoader.java @@ -3,54 +3,112 @@ import com.johnChnia.coding2017.basic.ArrayList; import com.johnChnia.coding2017.basic.List; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import java.io.*; /** - * @// TODO: 2017/4/20 改成 try... with...resource - * @// TODO: 2017/4/20 close inputstream - * @// TODO: 2017/4/20 修改TreeInfo直接返回File + * Created by john on 2017/4/27. */ public class ClassFileLoader { private List clzPaths = new ArrayList(); public byte[] readBinaryCode(String className) { - for (int i = 0; i < clzPaths.size(); i++) { - // 找到指定类文件 - Directory.TreeInfo treeInfo = Directory.walk(clzPaths.get(i), className); - if (treeInfo.files.size() > 0) { - try { - FileInputStream fis = new FileInputStream(treeInfo.files.get(0)); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); // 自动增长 - byte[] buff = new byte[1024]; - int len; - while ((len = fis.read(buff)) != -1) { - bos.write(buff, 0, len); - } - return bos.toByteArray(); - } catch (Exception e) { - e.printStackTrace(); - } + 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) { - clzPaths.add(path); + if(this.clzPaths.contains(path)){ + return; + } + + this.clzPaths.add(path); } public String getClassPath() { - StringBuilder sb = new StringBuilder(); - for (int index = 0; index < clzPaths.size(); index++) { - sb.append(clzPaths.get(index)); - sb.append(";"); + return StringUtils.join(this.clzPaths,";"); + + } + + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i arrayList2; private ArrayList arrayList3; private ArrayList arrayList4; - private ArrayList arrayList5; + private ArrayList arrayList5; @Before public void setUp() throws Exception { @@ -23,6 +23,7 @@ public void setUp() throws Exception { arrayList2 = new ArrayList<>(3); arrayList3 = new ArrayList<>(3); arrayList4 = new ArrayList<>(3); + arrayList5 = new ArrayList<>(); } @Test @@ -58,5 +59,14 @@ public void testRemoveElementByIndex() { assertThat(arrayList4.size(), equalTo(5)); } - + @Test + public void testIterator() { + for (int i = 0; i < 6; i++) { + arrayList5.add(i); + } + for (int i: + arrayList5) { + System.out.println(i); + } + } } diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/QueueTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/QueueTest.java index 191c6f568d..22f17c4327 100644 --- a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/QueueTest.java +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/QueueTest.java @@ -1,5 +1,6 @@ package com.johnChnia.coding2017.basic; +import com.johnChnia.coding2017.basic.queue.Queue; import org.junit.Before; import org.junit.Test; diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/CircleQueueTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..98a15c5c06 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/CircleQueueTest.java @@ -0,0 +1,38 @@ +package com.johnChnia.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by john on 2017/5/6. + */ +public class CircleQueueTest { + + CircleQueue cq1; + + @Before + public void setUp() throws Exception { + cq1 = new CircleQueue(); + } + + @After + public void tearDown() throws Exception { + + + } + + @Test + public void testEnQueueAndDeQueue() throws Exception { + for (int i = 0; i < 10; i++) { + cq1.enQueue(i); + } + cq1.deQueue(); + cq1.deQueue(); + cq1.enQueue(100); + cq1.enQueue(120); + Assert.assertEquals("(100, 120, 2, 3, 4, 5, 6, 7, 8, 9, )", cq1.toString()); + } + +} \ No newline at end of file diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacksTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..9c9d482513 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,37 @@ +package com.johnChnia.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by john on 2017/5/6. + */ +public class QueueWithTwoStacksTest { + QueueWithTwoStacks qwts; + + @Before + public void setUp() throws Exception { + qwts = new QueueWithTwoStacks<>(); + } + + @After + public void tearDown() throws Exception { + + + } + + @Test + public void testEnQueueAndDeQueue() throws Exception { + for (int i = 0; i < 10; i++) { + qwts.enQueue(i); + } + qwts.deQueue(); + qwts.deQueue(); + qwts.deQueue(); + Assert.assertEquals("3→4→5→6→7→8→9", qwts.toString()); + } + + +} \ No newline at end of file diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/QuickMinStackTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..232f988db2 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/QuickMinStackTest.java @@ -0,0 +1,53 @@ +package com.johnChnia.coding2017.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by john on 2017/5/7. + */ +public class QuickMinStackTest { + QuickMinStack quickMinStack1; + QuickMinStack quickMinStack2; + QuickMinStack quickMinStack3; + @Before + public void setUp() throws Exception { + quickMinStack1 = new QuickMinStack(); + quickMinStack2 = new QuickMinStack(); + quickMinStack3 = new QuickMinStack(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void testPush() throws Exception { + for (int i = 0; i < 4; i++) { + quickMinStack1.push(i); + } + Assert.assertEquals("3,2,1,0,", quickMinStack1.toString()); + } + + @Test + public void testPop() throws Exception { + for (int i = 0; i < 4; i++) { + quickMinStack2.push(i); + } + quickMinStack2.pop(); + Assert.assertEquals("2,1,0,", quickMinStack2.toString()); + } + + @Test + public void testFindMin() throws Exception { + for (int i = 0; i < 4; i++) { + quickMinStack3.push(i); + } + quickMinStack3.pop(); + Assert.assertEquals(0, quickMinStack3.findMin()); + } + +} \ No newline at end of file diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueuesTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..d051b349d1 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,34 @@ +package com.johnChnia.coding2017.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by john on 2017/5/7. + */ +public class StackWithTwoQueuesTest { + StackWithTwoQueues stq; + @Before + public void setUp() throws Exception { + stq = new StackWithTwoQueues(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void testPushAndPop() throws Exception { + for (int i = 0; i < 6; i++) { + stq.push(i); + } + Assert.assertEquals("[5, 4, 3, 2, 1, 0, ]", stq.toString()); + stq.pop(); + Assert.assertEquals("[4, 3, 2, 1, 0, ]", stq.toString()); + } + + +} \ No newline at end of file diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArrayTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..115c610b59 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,48 @@ +package com.johnChnia.coding2017.basic.stack; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by john on 2017/5/7. + */ +public class TwoStackInOneArrayTest { + TwoStackInOneArray twoStackInOneArray; + + @Before + public void setUp() throws Exception { + twoStackInOneArray = new TwoStackInOneArray(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void testPushAndPopAndPeek() throws Exception { + twoStackInOneArray.push1(0); + twoStackInOneArray.push1(1); + twoStackInOneArray.push2(2); + twoStackInOneArray.push2(3); + twoStackInOneArray.push1(4); + twoStackInOneArray.push1(5); + twoStackInOneArray.push2(6); + twoStackInOneArray.push2(7); + twoStackInOneArray.push2(8); + Assert.assertEquals("(0, 1, 4, 5, 8, 7, 6, 3, 2, )", + twoStackInOneArray.toString()); + twoStackInOneArray.pop1(); + twoStackInOneArray.pop2(); + Assert.assertEquals("(0, 1, 4, 7, 6, 3, 2, )", + twoStackInOneArray.toString()); + + Assert.assertEquals(4, + twoStackInOneArray.peek1()); + Assert.assertEquals(7, + twoStackInOneArray.peek2()); + } + +} \ No newline at end of file diff --git a/group24/448641125/src/com/donaldy/basic/stack/QuickMinStack.java b/group24/448641125/src/com/donaldy/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..8699c6ffec --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/QuickMinStack.java @@ -0,0 +1,59 @@ +package com.donaldy.basic.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ + + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Stack; + +/** + * 不改变栈的本身性质, + * 在其基础上添加findMin, + * findMin是找到最小的值,而不是返回的同时把元素弹出栈。 + */ +public class QuickMinStack { + + ArrayList arrayList = new ArrayList(); + Stack stack = new Stack<>(); + + public void push(int data){ + + this.stack.push(data); + + this.arrayList.add(data); + + sort(); + + } + + private void sort() { + Collections.sort(this.arrayList); + } + + public int pop(){ + + int oldData = this.stack.pop(); + + this.arrayList.remove(new Integer(oldData)); + + return oldData; + } + + public int findMin(){ + + if (this.arrayList.isEmpty()) { + throw new IndexOutOfBoundsException("stack is empty."); + } + + return this.arrayList.get(0); + } + + + +} diff --git a/group24/448641125/src/com/donaldy/basic/stack/QuickMinStackTest.java b/group24/448641125/src/com/donaldy/basic/stack/QuickMinStackTest.java new file mode 100644 index 0000000000..5da8e23bb9 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/QuickMinStackTest.java @@ -0,0 +1,31 @@ +package com.donaldy.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/5/4. + */ +public class QuickMinStackTest { + + @Test + public void test() { + + QuickMinStack qmStack = new QuickMinStack(); + + int [] intArr = {13, 2, 6, 23, 12, 1, 1, 5}; + + for (int i = 0; i < intArr.length; ++i) { + qmStack.push(intArr[i]); + } + + Assert.assertEquals(5, qmStack.pop()); + Assert.assertEquals(1, qmStack.pop()); + + Assert.assertEquals(1, qmStack.findMin()); + Assert.assertEquals(1, qmStack.pop()); + + Assert.assertEquals(2, qmStack.findMin()); + + } +} diff --git a/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueues.java b/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..3cf4e6cc9e --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,52 @@ +package com.donaldy.basic.stack; + + +import com.donaldy.basic.queue.Queue; + +public class StackWithTwoQueues { + + Queue queue = new Queue<>(); + Queue opQueue = new Queue<>(); + int size = 0; + + public void push(int data) { + + this.queue.enQueue(data); + this.size ++; + + } + + public int pop() { + + if (this.size <= 0 ) { + throw new IndexOutOfBoundsException("size : " + this.size); + } + + int cnt = this.size; + + int element; + + while (!this.queue.isEmpty()) { + + if (cnt == 1) { + break; + } + + this.opQueue.enQueue(this.queue.deQueue()); + + cnt --; + } + + int oldData = this.queue.deQueue(); + + while (!this.opQueue.isEmpty()) { + this.queue.enQueue(this.opQueue.deQueue()); + } + + this.size --; + + return oldData; + } + + +} diff --git a/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueuesTest.java b/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..f14aa88c51 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/StackWithTwoQueuesTest.java @@ -0,0 +1,25 @@ +package com.donaldy.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/5/4. + */ +public class StackWithTwoQueuesTest { + + @Test + public void test() { + + StackWithTwoQueues stack = new StackWithTwoQueues(); + + for (int i = 1; i <= 10; ++i) { + stack.push(i); + } + + for (int i = 10; i >= 1; --i) { + Assert.assertEquals(i, stack.pop()); + } + + } +} diff --git a/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArray.java b/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..83e760ba15 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,122 @@ +package com.donaldy.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底, + * 压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + + Object[] data = new Object[10]; + + /** + * 0, 10用来存储指针, + * 用于判断 栈是否为空 + */ + int pointer1 = 0; + int pointer2= 9; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + ensureCapacity(); + + this.data[++ this.pointer1] = o; + + } + + /** + * 扩容后,pointer1指针不变,pointer2指针要改变 + * 注意复制 + */ + private void ensureCapacity() { + + if (this.pointer1 + 1 == this.pointer2 || this.pointer1 == this.pointer2 + 1) { + + int newCapacity = this.data.length * 2 + 1; + + Object[] newDataArray = new Object[newCapacity]; + + System.arraycopy(this.data, 1, newDataArray, 1, this.pointer1); + + int pointer2Len = this.data.length - 1 - this.pointer2; + + System.arraycopy(this.data, this.pointer2, newDataArray, + newCapacity - pointer2Len - 1, pointer2Len); + + this.pointer2 = newCapacity - pointer2Len - 1; + + this.data = newDataArray; + } + + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1() { + + if (this.pointer1 <= 0 || this.pointer1 >= this.data.length) { + throw new IndexOutOfBoundsException("size : " + this.pointer1); + } + + return this.data[this.pointer1 --]; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + + if (this.pointer1 <= 0 || this.pointer1 >= this.data.length) { + throw new IndexOutOfBoundsException("size : " + this.pointer1); + } + + return this.data[this.pointer1]; + } + + + + + /** + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + ensureCapacity(); + System.out.println("push : " + o); + this.data[-- this.pointer2] = o; + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + + if (this.pointer2 >= this.data.length || this.pointer2 <= 0) { + throw new IndexOutOfBoundsException("size : " + this.pointer2); + } + + return this.data[this.pointer2 ++]; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if (this.pointer2 >= this.data.length || this.pointer2 <= 0) { + throw new IndexOutOfBoundsException("size : " + this.pointer2); + } + + return this.data[this.pointer2]; + } + +} diff --git a/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArrayTest.java b/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..b85d606891 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/stack/TwoStackInOneArrayTest.java @@ -0,0 +1,62 @@ +package com.donaldy.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/5/4. + */ +public class TwoStackInOneArrayTest { + + @Test + public void test() { + + //第二个栈为空 + TwoStackInOneArray stack = new TwoStackInOneArray(); + + for (int i = 1; i <= 10; ++i) { + stack.push1(i); + Assert.assertEquals(i, stack.peek1()); + } + + for (int i = 10; i >= 2; --i) { + Assert.assertEquals(i, stack.pop1()); + } + + //第一个栈为空 + stack = new TwoStackInOneArray(); + + for (int i = 1; i <= 10; ++i) { + stack.push2(i); + Assert.assertEquals(i, stack.peek2()); + } + + for (int i = 10; i >= 2; --i) { + Assert.assertEquals(i, stack.pop2()); + } + + + //两个栈 + stack = new TwoStackInOneArray(); + + for (int i = 1; i <= 4; ++i) { + stack.push1(i); + stack.push2(i); + } + + stack.push1(5); + + Assert.assertEquals(5, stack.peek1()); + Assert.assertEquals(4, stack.peek2()); + + for (int i = 5; i >= 1; --i) { + Assert.assertEquals(i, stack.pop1()); + } + + for (int i = 4; i >= 1; --i) { + Assert.assertEquals(i, stack.pop2()); + } + + } + +} diff --git a/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeNode.java b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..c6e1db078d --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeNode.java @@ -0,0 +1,35 @@ +package com.donaldy.basic.tree; + +public class BinaryTreeNode { + + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(T data){ + this.data=data; + } + public T getData() { + return data; + } + public void setData(T data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtil.java b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtil.java new file mode 100644 index 0000000000..82ef6e4620 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtil.java @@ -0,0 +1,158 @@ +package com.donaldy.basic.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + preOrder(root, result); + + return result; + } + + private static void preOrder(BinaryTreeNode root, List result) { + + if (root == null) { + return ; + } + + result.add(root.getData()); + + preOrder(root.getLeft(), result); + + preOrder(root.getRight(), result); + + } + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + inOrder(root, result); + + return result; + } + + private static void inOrder(BinaryTreeNode root, List result) { + + if (root == null) { + return ; + } + + inOrder(root.getLeft(), result); + + result.add(root.getData()); + + inOrder(root.getRight(), result); + + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + postOrder(root, result); + + return result; + } + + + private static void postOrder(BinaryTreeNode root, List result) { + + if (root == null) { + return ; + } + + postOrder(root.getLeft(), result); + + postOrder(root.getRight(), result); + + result.add(root.getData()); + + } + + /** + * 用非递归的方式实现对二叉树的前序遍历 + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + + Stack treeStack = new Stack<>(); + + while (root != null || !treeStack.isEmpty()) { + + while (root != null) { + + result.add(root.getData()); + + treeStack.push(root); + + root = root.getLeft(); + } + + root = treeStack.pop(); + + root = root.getRight(); + + + } + + return result; + } + + + /** + * 用非递归的方式实现对二叉树的中序遍历 + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + + Stack treeStack = new Stack<>(); + + while (root != null || !treeStack.isEmpty()) { + + while (root != null) { + + treeStack.push(root); + + root = root.getLeft(); + + } + + root = treeStack.pop(); + + result.add(root.getData()); + + root = root.getRight(); + + } + + return result; + } + +} diff --git a/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtilTest.java b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..48fae655f9 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/tree/BinaryTreeUtilTest.java @@ -0,0 +1,75 @@ +package com.donaldy.basic.tree; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class BinaryTreeUtilTest { + + BinaryTreeNode root = null; + @Before + public void setUp() throws Exception { + root = new BinaryTreeNode(1); + root.setLeft(new BinaryTreeNode(2)); + root.setRight(new BinaryTreeNode(5)); + root.getLeft().setLeft(new BinaryTreeNode(3)); + root.getLeft().setRight(new BinaryTreeNode(4)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + + + } + @Test + public void testInOrderVisit() { + + + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[3, 2, 4, 1, 5]", result.toString()); + + } + + @Test + public void testPostOrderVisit() { + + + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[3, 4, 2, 5, 1]", result.toString()); + + } + + + @Test + public void testInOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[3, 2, 6, 4, 7, 1, 5]", result.toString()); + + } + @Test + public void testPreOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 6, 7, 5]", result.toString()); + + } +} diff --git a/group24/448641125/src/com/donaldy/basic/tree/FileList.java b/group24/448641125/src/com/donaldy/basic/tree/FileList.java new file mode 100644 index 0000000000..e349450d4e --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/tree/FileList.java @@ -0,0 +1,27 @@ +package com.donaldy.basic.tree; + +import java.io.File; + +public class FileList { + + public void list(File f) { + + System.out.println(f.getName() + " : "); + + for (File file : f.listFiles()) { + + System.out.println(file.getName()); + + if (file.isDirectory()) { + + list(file); + + } + + } + + + } + + +} diff --git a/group24/448641125/src/com/donaldy/basic/tree/FileListTest.java b/group24/448641125/src/com/donaldy/basic/tree/FileListTest.java new file mode 100644 index 0000000000..80a8b29dbb --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/tree/FileListTest.java @@ -0,0 +1,22 @@ +package com.donaldy.basic.tree; + +import org.junit.Test; + +import java.io.File; + +/** + * Created by DonaldY on 2017/5/11. + */ +public class FileListTest { + + @Test + public void test() { + + FileList fileList = new FileList(); + + fileList.list(new File("D:\\computer\\SoftwareEngineering\\软件工程讲稿(第三版)")); + + } + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java index 9122f3690a..854a0e2e75 100644 --- a/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java +++ b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java @@ -104,7 +104,7 @@ public String toString(ConstantPool pool) { StringBuilder buffer = new StringBuilder(); //buffer.append("Code:").append(code).append("\n"); for(int i=0;i codeMap = new HashMap(); - + static{ codeMap.put("01", "aconst_null"); - + codeMap.put("BB", "new"); codeMap.put("37", "lstore"); codeMap.put("B7", "invokespecial"); @@ -28,61 +62,61 @@ public abstract class ByteCodeCommand { 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; } @@ -93,31 +127,19 @@ public void setOffset(int offset) { protected ConstantInfo getConstantInfo(int index){ return this.getClassFile().getConstantPool().getConstantInfo(index); } - + protected ConstantPool getConstantPool(){ return this.getClassFile().getConstantPool(); } - - - + + + public String getOpCode() { return opCode; } public abstract int getLength(); - - - - - public String toString(){ - - StringBuffer buffer = new StringBuffer(); - buffer.append(this.opCode); - - return buffer.toString(); - } - public abstract String toString(ConstantPool pool); - + public String getReadableCodeText(){ String txt = codeMap.get(opCode); if(txt == null){ @@ -127,4 +149,4 @@ public String getReadableCodeText(){ } public abstract void execute(StackFrame frame,ExecutionResult result); -} +} \ No newline at end of file diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java b/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java index b43e0d3a06..ce793bb637 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/CommandParser.java @@ -71,7 +71,7 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { cmds.add(cmd); } else if (invokevirtual.equals(opCode)) { - InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile, opCode); + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, opCode); cmd.setOprand1(iter.next2CharAsInt()); cmd.setOprand2(iter.next2CharAsInt()); diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java index 6644fe958d..cdfba64252 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetFieldCmd.java @@ -2,7 +2,9 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; @@ -13,15 +15,23 @@ public GetFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } @Override - public void execute(StackFrame frame, ExecutionResult result) { - - + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + + } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java index 7b4cc9896f..18ff35be32 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/GetStaticFieldCmd.java @@ -6,6 +6,8 @@ import com.donaldy.jvm.constant.FieldRefInfo; import com.donaldy.jvm.constant.UTF8Info; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.Heap; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; @@ -17,15 +19,24 @@ public GetStaticFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } - - @Override - public void execute(StackFrame frame, ExecutionResult result) { - - + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + //TODO 处理非System.out的情况 } - } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java index b646011143..517906329f 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeSpecialCmd.java @@ -4,7 +4,9 @@ import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.MethodRefInfo; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.MethodArea; import com.donaldy.jvm.engine.StackFrame; +import com.donaldy.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -15,15 +17,30 @@ public InvokeSpecialCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } - @Override - public void execute(StackFrame frame, ExecutionResult result) { - + public void execute(StackFrame frame,ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + + } + } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java index 8b51e481af..f0b59093a6 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/InvokeVirtualCmd.java @@ -1,9 +1,13 @@ package com.donaldy.jvm.cmd; import com.donaldy.jvm.clz.ClassFile; -import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.MethodRefInfo; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.JavaObject; +import com.donaldy.jvm.engine.MethodArea; import com.donaldy.jvm.engine.StackFrame; +import com.donaldy.jvm.method.Method; + public class InvokeVirtualCmd extends TwoOperandCmd { @@ -13,14 +17,69 @@ public InvokeVirtualCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsMethod(pool); + return super.getOperandAsMethod(); } + private boolean isSystemOutPrintlnMethod(String className, String methodName){ + return "java/io/PrintStream".equals(className) + && "println".equals(methodName); + } @Override - public void execute(StackFrame frame, ExecutionResult result) { + public void execute(StackFrame frame,ExecutionResult result) { + + //先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if(isSystemOutPrintlnMethod(className,methodName)){ + JavaObject jo = (JavaObject)frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + //注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while(currentClassName != null){ + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), + methodRefInfo.getParamAndReturnType()); + if(m != null){ + + break; + + } else{ + //查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if(m == null){ + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java index d55d8ef409..cf2d49ab1f 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/LdcCmd.java @@ -5,6 +5,8 @@ import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.constant.StringInfo; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.Heap; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -14,9 +16,9 @@ public LdcCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + ConstantInfo info = getConstantInfo(this.getOperand()); String value = "TBD"; if(info instanceof StringInfo){ @@ -27,11 +29,22 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } - - @Override - public void execute(StackFrame frame, ExecutionResult result) { - - + public void execute(StackFrame frame,ExecutionResult result){ + + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + } - } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java index 2a30581935..237c5928dc 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NewObjectCmd.java @@ -1,8 +1,11 @@ package com.donaldy.jvm.cmd; import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ClassInfo; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.Heap; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -12,15 +15,26 @@ public NewObjectCmd(ClassFile clzFile, String opCode){ } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsClassInfo(pool); + return super.getOperandAsClassInfo(); } - @Override - public void execute(StackFrame frame, ExecutionResult result) { - - + public void execute(StackFrame frame,ExecutionResult result){ + + int index = this.getIndex(); + + ClassInfo info = (ClassInfo)this.getConstantInfo(index); + + String clzName = info.getClassName(); + + //在Java堆上创建一个实例 + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + + } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java index c664210eda..32ea5853ee 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/NoOperandCmd.java @@ -3,6 +3,8 @@ import com.donaldy.jvm.clz.ClassFile; import com.donaldy.jvm.constant.ConstantPool; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.Heap; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -12,21 +14,133 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equals(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equals(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equals(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equals(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equals(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equals(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equals(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } public int getLength(){ return 1; } - @Override - public void execute(StackFrame frame, ExecutionResult result) { - - - } - - } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java index 9bf85ba44f..cb9e60e27b 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/PutFieldCmd.java @@ -1,8 +1,12 @@ package com.donaldy.jvm.cmd; import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ClassInfo; import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.FieldRefInfo; +import com.donaldy.jvm.constant.NameAndTypeInfo; import com.donaldy.jvm.engine.ExecutionResult; +import com.donaldy.jvm.engine.JavaObject; import com.donaldy.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -12,16 +16,29 @@ public PutFieldCmd(ClassFile clzFile,String opCode) { } @Override - public String toString(ConstantPool pool) { + public String toString() { - return super.getOperandAsField(pool); + return super.getOperandAsField(); } - - @Override - public void execute(StackFrame frame, ExecutionResult result) { + public void execute(StackFrame frame,ExecutionResult result) { + + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } - } } diff --git a/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java b/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java index 1d38c8ed3f..3c62fd93e0 100644 --- a/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java +++ b/group24/448641125/src/com/donaldy/jvm/cmd/TwoOperandCmd.java @@ -39,14 +39,14 @@ public int getIndex(){ return index; } - protected String getOperandAsClassInfo(ConstantPool pool){ + protected String getOperandAsClassInfo(){ int index = getIndex(); String codeTxt = getReadableCodeText(); - ClassInfo info = (ClassInfo)pool.getConstantInfo(index); + ClassInfo info = (ClassInfo)getConstantInfo(index); return this.getOffset()+":"+this.getOpCode()+" "+ codeTxt +" "+ info.getClassName(); } - protected String getOperandAsMethod(ConstantPool pool){ + protected String getOperandAsMethod(){ int index = getIndex(); String codeTxt = getReadableCodeText(); ConstantInfo constInfo = this.getConstantInfo(index); @@ -54,7 +54,7 @@ protected String getOperandAsMethod(ConstantPool pool){ return this.getOffset()+":"+this.getOpCode()+" " + codeTxt +" "+ info.toString(); } - protected String getOperandAsField(ConstantPool pool){ + protected String getOperandAsField(){ int index = getIndex(); String codeTxt = getReadableCodeText(); diff --git a/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java b/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java index c90cc8fc65..ea6340e976 100644 --- a/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java +++ b/group24/448641125/src/com/donaldy/jvm/engine/ExecutionResult.java @@ -48,9 +48,6 @@ public int getNextCmdOffset() { public void setNextCmdOffset(int nextCmdOffset) { this.nextCmdOffset = nextCmdOffset; } - - - - + } diff --git a/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java b/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java index 1fb57626b9..e18323a4d6 100644 --- a/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java +++ b/group24/448641125/src/com/donaldy/jvm/engine/ExecutorEngine.java @@ -19,17 +19,71 @@ public ExecutorEngine() { } public void execute(Method mainMethod){ - - - + + StackFrame mainFrame = StackFrame.create(mainMethod); + + stack.push(mainFrame); + + while (!stack.empty()) { + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + //函数栈帧来了。。。 + if (result.isPauseAndRunNewFrame()) { + + Method nextMethod = result.getNextMethod(); + + StackFrame nextFrame = StackFrame.create(nextMethod); + + nextFrame.setCallerFrame(frame); + + setupFunctionCallParams(frame, nextFrame); + + stack.push(nextFrame); + } else { + + //认为其执行完了 + stack.pop(); + + } + } + + } - - - + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { - - - + + Method nextMethod = nextFrame.getMethod(); + + + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + + nextFrame.setLocalVariableTable(params); + } } diff --git a/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java b/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java index fea5102cd0..470b3044d2 100644 --- a/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java +++ b/group24/448641125/src/com/donaldy/jvm/engine/MethodArea.java @@ -52,17 +52,37 @@ public ClassFile findClassFile(String className){ return clzFile; } - - + + public Method getMethod(String className, String methodName, String paramAndReturnType){ - - return null; + + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if(m == null){ + + throw new RuntimeException("method can't be found : \n" + + "class: " + className + + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; } - - - public Method getMethod(MethodRefInfo methodRef){ - - return null; - + + + public Method getMethod(MethodRefInfo methodRef){ + + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if(m == null){ + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + } } diff --git a/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java b/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java index 30f19e0d8c..b444a6668b 100644 --- a/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java +++ b/group24/448641125/src/com/donaldy/jvm/engine/MiniJVM.java @@ -21,8 +21,10 @@ public void run(String[]classPaths , String className) throws FileNotFoundExcept ExecutorEngine engine = new ExecutorEngine(); className = className.replace(".", "/"); - + + //装载main方法 engine.execute(methodArea.getMainMethod(className)); + } } diff --git a/group24/448641125/src/com/donaldy/jvm/engine/StackFrame.java b/group24/448641125/src/com/donaldy/jvm/engine/StackFrame.java index 73b510e140..56c4f9c3f7 100644 --- a/group24/448641125/src/com/donaldy/jvm/engine/StackFrame.java +++ b/group24/448641125/src/com/donaldy/jvm/engine/StackFrame.java @@ -5,19 +5,20 @@ import java.util.Stack; import com.donaldy.jvm.cmd.ByteCodeCommand; +import com.donaldy.jvm.cmd.InvokeVirtualCmd; import com.donaldy.jvm.method.Method; public class StackFrame { - + private List localVariableTable = new ArrayList(); private Stack oprandStack = new Stack(); - + int index = 0; - + private Method m = null; - + private StackFrame callerFrame = null; - + public StackFrame getCallerFrame() { return callerFrame; } @@ -26,34 +27,34 @@ public void setCallerFrame(StackFrame callerFrame) { this.callerFrame = callerFrame; } - - - + + + public static StackFrame create(Method m){ - - StackFrame frame = new StackFrame( m ); - + + StackFrame frame = new StackFrame( m ); + return frame; } - - private StackFrame(Method m) { + + private StackFrame(Method m) { this.m = m; - + } - - - + + + public JavaObject getLocalVariableValue(int index){ return this.localVariableTable.get(index); } - + public Stack getOprandStack(){ return this.oprandStack; } - + public int getNextCommandIndex(int offset){ - + ByteCodeCommand [] cmds = m.getCodeAttr().getCmds(); for(int i=0;i values){ - this.localVariableTable = values; + this.localVariableTable = values; } - + public void setLocalVariableValue(int index, JavaObject jo){ //问题: 为什么要这么做?? if(this.localVariableTable.size()-1 < index){ @@ -83,13 +122,13 @@ public void setLocalVariableValue(int index, JavaObject jo){ } } this.localVariableTable.set(index, jo); - - + + } - + public Method getMethod(){ return m; } - + } diff --git a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java index b0229c7435..ea14b12360 100644 --- a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java +++ b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java @@ -125,10 +125,11 @@ private ConstantPool parseConstantPool(ByteCodeIterator iter) { nameType.setIndex2(iter.nextU2ToInt()); pool.addConstantInfo(nameType); } else { - throw new RuntimeException("the constant pool tag" + tag); + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet."); } } + System.out.println("Finished reading Constant pool "); return pool; } diff --git a/group24/448641125/src/com/donaldy/jvm/method/Method.java b/group24/448641125/src/com/donaldy/jvm/method/Method.java index 8720da21b7..c7c7df816c 100644 --- a/group24/448641125/src/com/donaldy/jvm/method/Method.java +++ b/group24/448641125/src/com/donaldy/jvm/method/Method.java @@ -7,6 +7,8 @@ import com.donaldy.jvm.constant.UTF8Info; import com.donaldy.jvm.loader.ByteCodeIterator; +import java.util.ArrayList; +import java.util.List; public class Method { @@ -56,22 +58,18 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ int attribCount = iter.nextU2ToInt(); - /*System.out.println("name = " + clzFile.getConstantPool().getUTF8String(nameIndex) - + ", desc = " + clzFile.getConstantPool().getUTF8String(descIndex));*/ - Method m = new Method(clzFile, accessFlag, nameIndex, descIndex); - //attribCount == 1 for( int j = 1; j <= attribCount; j++){ int attrNameIndex = iter.nextU2ToInt(); - /*System.out.println("attrNameIndex : " + attrNameIndex);*/ + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); - /*System.out.println("attrName : " + attrName);*/ + iter.back(2); if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ - /*System.out.println("j : " + j );*/ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); m.setCodeAttr(codeAttr); } else{ @@ -144,4 +142,61 @@ public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + private String getParamAndReturnType() { + UTF8Info nameAndTypeInfo = (UTF8Info) this.getClzFile() + .getConstantPool().getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList() { + + //e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + + //e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first + 1, last); + + List paramList = new ArrayList<>(); + + if ((null == param) || "".equals(param)) { + return paramList; + } + + while (!param.equals("")) { + int pos = 0; + + //这是一个对象类型 + if (param.charAt(pos) == 'L') { + int end = param.indexOf(";"); + + if (end == -1) { + throw new RuntimeException("can't find the ; fro a object type"); + } + + paramList.add(param.substring(pos+ 1, end)); + + pos = end + 1; + } + else if (param.charAt(pos) == 'I') { + //int + paramList.add("I"); + pos ++; + } + else if (param.charAt(pos) == 'F') { + //float + paramList.add("F"); + pos ++; + } else { + throw new RuntimeException("the param has unsupported type : " + param); + } + + param = param.substring(pos); + } + + return paramList; + } } diff --git a/group24/448641125/src/com/donaldy/jvm/test/MinJVMTest.java b/group24/448641125/src/com/donaldy/jvm/test/MinJVMTest.java new file mode 100644 index 0000000000..7936da4dfc --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/test/MinJVMTest.java @@ -0,0 +1,31 @@ +package com.donaldy.jvm.test; + +import com.donaldy.jvm.engine.MiniJVM; +import org.junit.Test; + +/** + * Created by DonaldY on 2017/4/27. + */ +public class MinJVMTest { + + static final String PATH = "D:\\tools\\Code\\Y_Repository\\coding2017\\group24\\448641125\\out\\production" + + "\\448641125\\"; + + @Test + public void testMain() throws Exception { + /** + * 1.加载类 + * -工具:ClassFileLoader + * -目的地:方法区(MethodArea) + * 2.获取类的main方法 + * -从方法区寻找 + * 3.执行main方法的字节码 + * -字节码指令(Command对象) + * -栈帧(StackFrame) + * -堆(Heap) + */ + String [] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/EmployeeV1.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/EmployeeV1.java new file mode 100644 index 0000000000..e6bc33f6b0 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coding.mini_jvm.src.com.coderising.jvm; + +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/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java index eb7dafa79d..fd60d0ea7b 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/BiPushCmd.java @@ -2,6 +2,10 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.Heap; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -15,7 +19,13 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } - - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java index b44d66c880..d22bd332ba 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -3,6 +3,8 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantInfo; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; import java.util.HashMap; import java.util.Map; @@ -123,5 +125,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java index 5801068cb0..113f8d7702 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.FieldRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -15,7 +19,13 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRefInfo.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + frame.getOprandStack().push(jo.getFieldValue(fieldName)); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java index e577d1b56c..dfcd905c52 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -3,6 +3,11 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.FieldRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.Heap; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -17,4 +22,20 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRefInfo.getFieldName(); + String className = fieldRefInfo.getClassName(); + String fieldType = fieldRefInfo.getFieldType(); + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } +// JavaObject jo = Heap.getInstance().newObject(className); +// frame.getOprandStack().push(jo); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java index 2900bb2c60..c402bfbba9 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -3,6 +3,11 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.MethodRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.MethodArea; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { @@ -17,6 +22,17 @@ public String toString(ConstantPool pool) { return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + if (methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")) { + return; + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java index ff7f0fdf14..fe95c356c7 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -3,6 +3,12 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.MethodRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.MethodArea; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { @@ -12,11 +18,25 @@ public InvokeVirtualCmd(ClassFile clzFile,String opCode) { @Override public String toString(ConstantPool pool) { - return super.getOperandAsMethod(pool); } - - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + String methodName = methodRefInfo.getMethodName(); + String className = methodRefInfo.getClassName(); + if ("java/io/PrintStream".equals(className) && "println".equals(methodName)) { + JavaObject jo = frame.getOprandStack().pop(); + System.out.println("***********"+jo.toString()+"***********"); + + frame.getOprandStack().pop(); + return; + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java index abaeae3a9e..63492570ee 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/LdcCmd.java @@ -5,6 +5,9 @@ import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantInfo; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; import com.coding.mini_jvm.src.com.coderising.jvm.constant.StringInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -26,5 +29,19 @@ public String toString(ConstantPool pool) { return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; } - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassFile clzFile = this.getClassFile(); + ConstantInfo info = (ConstantInfo)clzFile.getConstantPool().getConstantInfo(this.getOperand()); + String value = "TBD"; + if (info instanceof StringInfo) { + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + frame.getOprandStack().push(jo); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java index db90b82a35..40c5008a9d 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NewObjectCmd.java @@ -1,7 +1,12 @@ package com.coding.mini_jvm.src.com.coderising.jvm.cmd; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ClassInfo; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.Heap; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class NewObjectCmd extends TwoOperandCmd{ @@ -15,5 +20,12 @@ public String toString(ConstantPool pool) { return super.getOperandAsClassInfo(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassInfo clzInfo = (ClassInfo) clzFile.getConstantPool().getConstantInfo(getIndex()); + JavaObject jo = Heap.getInstance().newObject(clzInfo.getClassName()); + frame.getOprandStack().push(jo); + } + + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java index 3cd045f6d3..afbbd6248e 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/NoOperandCmd.java @@ -3,6 +3,9 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -15,8 +18,37 @@ public String toString(ConstantPool pool) { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } - - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + if (CommandParser.astore_1.equals(this.getOpCode())) { + JavaObject jo = frame.getOprandStack().pop(); + frame.setLocalVariableValue(1, jo); + } else if (CommandParser.aload_0.equals(this.getOpCode())) { + JavaObject jo = frame.getLocalVariableValue(0); + frame.getOprandStack().push(jo); + } else if (CommandParser.aload_1.equals(this.getOpCode())) { + JavaObject jo = frame.getLocalVariableValue(1); + frame.getOprandStack().push(jo); + } else if (CommandParser.iload_1.equals(this.getOpCode())) { + JavaObject jo = frame.getLocalVariableValue(1); + frame.getOprandStack().push(jo); + } else if (CommandParser.iload_2.equals(this.getOpCode())) { + JavaObject jo = frame.getLocalVariableValue(2); + frame.getOprandStack().push(jo); + } else if (CommandParser.istore_1.equals(this.getOpCode())) { + JavaObject jo = frame.getOprandStack().pop(); + frame.setLocalVariableValue(1, jo); + } else if (CommandParser.voidreturn.equals(this.getOpCode())) { + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + } else if (CommandParser.dup.equals(this.getOpCode())) { + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + } else { + throw new RuntimeException("this operator ["+this.getOpCode()+"] not support yet"); + } + } + + public int getLength(){ return 1; } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java index 6f6ecd0eb1..894e8ed53b 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/cmd/PutFieldCmd.java @@ -3,6 +3,11 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.constant.ConstantPool; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.FieldRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.NameAndTypeInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.ExecutionResult; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.JavaObject; +import com.coding.mini_jvm.src.com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -16,5 +21,15 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRefInfo.getNameAndTypeIndex()); + String fieldName = nameAndTypeInfo.getName(); + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + objectRef.setFieldValue(fieldName, fieldValue); + } + } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutionResult.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..81c353dd32 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,57 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + + +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutorEngine.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..3ada1ae371 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,56 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + + +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Stack; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod) { + stack.push(StackFrame.create(mainMethod)); + while (!stack.isEmpty()) { + //1 执行栈帧 + StackFrame frame = stack.peek(); + ExecutionResult executionResult = frame.execute(); + if (executionResult.isPauseAndRunNewFrame()) { + Method method = executionResult.getNextMethod(); + StackFrame nextFrame = StackFrame.create(method); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame, nextFrame); + stack.push(nextFrame); + } else { + stack.pop(); + } + } + + } + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + Method method = nextFrame.getMethod(); + List params = method.getParameterList(); + int paramNum = params.size(); + if (!method.isStatic()) { + paramNum++; + } + List args = new ArrayList<>(); + while (paramNum > 0) { + args.add(currentFrame.getOprandStack().pop()); + paramNum--; + } + Collections.reverse(args); + nextFrame.setLocalVariableTable(args); + } + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/Heap.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..2da0ef9e6b --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/JavaObject.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..471bd874d1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MethodArea.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..5abaa40308 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,71 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.MethodRefInfo; +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; +import com.coding.mini_jvm.src.com.coderising.jvm.method.Method; + +import java.util.HashMap; +import java.util.Map; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) { + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + ClassFile classFile = findClassFile(className); + Method method = classFile.getMethod(methodName, paramAndReturnType); + if (method == null) { + throw new RuntimeException("method "+methodName+ "can't found"); + } + return method; + } + + + public Method getMethod(MethodRefInfo methodRef){ + return getMethod(methodRef.getClassName(), + methodRef.getMethodName(), methodRef.getParamAndReturnType()); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MiniJVM.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..164943f694 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,29 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.engine; + +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + + +public class MiniJVM { + + public void run(String[] classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + public static StackFrame create(Method m) { + + StackFrame frame = new StackFrame(m); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i 0) { + ExecutionResult result = new ExecutionResult(); + + while (index < commands.length){ + ByteCodeCommand command = commands[index]; + System.out.println("\t " + command.toString(this.getMethod().getClzFile().getConstantPool())); + command.execute(this, result); + if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } + else if (result.isExitCurrentFrame()) { + return result; + } + else if (result.isRunNextCmd()) { + index++; + } + else if (result.isJump()) { + int offset = result.getNextCmdOffset(); + index = this.getNextCommandIndex(offset); + } else { + index++; + } + } + return result; + } + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + } + + + + + public void setLocalVariableTable(List values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java index 452f6bce7d..db2d2ff467 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -2,10 +2,7 @@ import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; import java.util.List; @@ -13,9 +10,11 @@ public class ClassFileLoader { + private ClassLoader classLoader; + private static final String CLASS_FILE_SUFFIX = ".class"; - private List clzPaths = new ArrayList(); - + private static List clzPaths = new ArrayList(); + public byte[] readBinaryCode(String className) { String classPath = getClassPath(); String[] paths = classPath.split(File.pathSeparator); @@ -42,6 +41,7 @@ private byte[] loadClassFile(String clzFileName) { e.printStackTrace(); return null; } + } public void addClassPath(String path) { @@ -49,8 +49,10 @@ public void addClassPath(String path) { return; } clzPaths.add(path); + + } - + public String getClassPath(){ @@ -69,4 +71,38 @@ public ClassFile loadClass(String className) { ClassFileParser classFileParser = new ClassFileParser(); return classFileParser.parse(data); } + +// public static void main(String[] args) { +// +// +// System.out.println(System.getProperty("java.library.path")); +// System.out.println(System.getProperty("java.class.path")); +// System.out.println(System.getProperty("java.home")); +//// System.getProperty("java.class.path"); +//// System.getProperty("java.class.path"); +//// System.getProperty("java.class.path"); +//// System.getProperty("java.class.path"); +// +// } + + private class MyClassLoader extends ClassLoader { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + String filename = name.substring(name.lastIndexOf(".")+1) + ".class"; + try { + InputStream is = getClass().getResourceAsStream(filename); + if (is == null) { + return super.loadClass(name); + } + + byte[] b = new byte[is.available()]; + is.read(b); + return defineClass(name, b, 0, b.length); + } catch (IOException e) { + e.printStackTrace(); + } + + return super.loadClass(name); + } + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java index b848e6b515..d00ec4ac1c 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/method/Method.java @@ -4,8 +4,12 @@ import com.coding.mini_jvm.src.com.coderising.jvm.attr.CodeAttr; import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; import com.coding.mini_jvm.src.com.coderising.jvm.cmd.ByteCodeCommand; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.UTF8Info; import com.coding.mini_jvm.src.com.coderising.jvm.loader.ByteCodeIterator; +import java.util.ArrayList; +import java.util.List; + public class Method { private int accessFlag; @@ -66,4 +70,46 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + public List getParameterList() { + String desc = clzFile.getConstantPool().getUTF8String(descriptorIndex); + int startIndex = desc.indexOf("(") + 1; + int endIndex = desc.lastIndexOf(")") ; + String paramStr = desc.substring(startIndex, endIndex); + List params = new ArrayList<>(); + if ("".equals(paramStr)) { + return params; + } + int pos = 0; + int length = paramStr.length(); + while (pos < length) { + if ('L' == paramStr.charAt(pos) || '['== paramStr.charAt(pos)) { + for (int i = pos; i < length; i++) { + if (paramStr.charAt(i) == ';') { + params.add(paramStr.substring(pos, i)); + pos = ++i; + break; + } + } + } else if ('I' == paramStr.charAt(pos)) { + params.add("int"); + pos++; + } else if ('F' == paramStr.charAt(pos)) { + params.add("float"); + pos++; + } else { + throw new RuntimeException("not impl param type ["+ paramStr.charAt(pos) +"] yet"); + } + } + return params; + } + + public boolean isStatic() { + return (accessFlag & 0x0004) != 0; + } + + public String getName() { + UTF8Info utf8Info = (UTF8Info)clzFile.getConstantPool().getConstantInfo(nameIndex); + return utf8Info.getValue(); + } } diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java index e10e7885ba..96920a9c68 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/print/SimpleVistor.java @@ -10,47 +10,44 @@ public class SimpleVistor implements ConstantInfo.Visitor { private Formatter formatter = new Formatter(System.out); private String format = " = %-20s %-20s %-100s\n"; - private static final String HASH_KEY = "#"; - private static final String DOUBLE_SLASH = "// "; - private static final String DOT = "."; - private static final String COLON = ":"; @Override public void visitClassInfo(ClassInfo info) { formatter.format(format, "Class", - HASH_KEY + info.getUtf8Index(), - DOUBLE_SLASH + info.getClassName()); + "#" + info.getUtf8Index(), + "// " + info.getClassName()); } @Override public void visitFieldRef(FieldRefInfo info) { NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo)info.getConstantInfo(info.getNameAndTypeIndex()); formatter.format(format, "Fieldref", - HASH_KEY + info.getClassInfoIndex() + DOT + HASH_KEY + info.getNameAndTypeIndex(), - DOUBLE_SLASH + info.getClassName() + DOT + nameAndTypeInfo.getName() + COLON + nameAndTypeInfo.getTypeInfo()); + "#" + info.getClassInfoIndex() + "." + "#" + info.getNameAndTypeIndex(), + "// " + info.getClassName() + "." + nameAndTypeInfo.getName() + ":" + nameAndTypeInfo.getTypeInfo()); } @Override public void visitMethodRef(MethodRefInfo info) { formatter.format(format, "Methodref", - HASH_KEY + info.getClassInfoIndex() + DOT + HASH_KEY + info.getNameAndTypeIndex(), - DOUBLE_SLASH + info.getClassName() + DOT + info.getMethodName()); + "#" + info.getClassInfoIndex() + "." + "#" + info.getNameAndTypeIndex(), + "// " + info.getClassName() + "." + info.getMethodName()); } @Override public void visitNameAndType(NameAndTypeInfo info) { formatter.format(format, "NameAndType", - HASH_KEY + info.getIndex1() + COLON + HASH_KEY + info.getIndex2(), - DOUBLE_SLASH + info.getName() + COLON + info.getTypeInfo()); + "#" + info.getIndex1() + ":" + "#" + info.getIndex2(), + "// " + info.getName() + ":" + info.getTypeInfo()); } @Override public void visitString(StringInfo info) { - formatter.format(format, "String", HASH_KEY + info.getIndex(), DOUBLE_SLASH + info.toString()); + formatter.format(format, "String", "#" + info.getIndex(), "// " + info.toString()); } @Override public void visistUTF8(UTF8Info info) { formatter.format(format, "Utf8", info.getValue(), ""); } + } diff --git a/group24/494800949/src/main/java/com/coding/week8/CircleQueue.java b/group24/494800949/src/main/java/com/coding/week8/CircleQueue.java new file mode 100644 index 0000000000..06f73cad5b --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week8/CircleQueue.java @@ -0,0 +1,70 @@ +package com.coding.week8; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + private int size; + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return size == 0; + } + + public int size() { + return size; + } + + + + public void enQueue(E data) { + if (data == null) { + throw new IllegalArgumentException("data can't be null"); + } + elementData[rear] = data; + size++; + if ((rear = (rear + 1) % elementData.length) == front) { + doubleCapacity(); + } + } + + private void doubleCapacity() { + int oldCapacity = elementData.length; + int newCapacity = oldCapacity << 1; + Object[] elementDataNew = new Object[newCapacity]; + if (newCapacity < 0) { + throw new RuntimeException("capacitity is too big"); + } + System.arraycopy(elementData, rear, elementDataNew, 0, oldCapacity - rear ); + System.arraycopy(elementData, 0, elementDataNew, front, front ); + elementData = elementDataNew; + front = 0; + rear = oldCapacity; + } + + public E deQueue() { + if (size == 0) + return null; + @SuppressWarnings("unchecked") + E e = (E)elementData[front]; + //let gc work + elementData[front] = null; + //下标越界处理 + front = ++front % elementData.length; + size--; + return e; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week8/Josephus.java b/group24/494800949/src/main/java/com/coding/week8/Josephus.java new file mode 100644 index 0000000000..8b17a17ebb --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week8/Josephus.java @@ -0,0 +1,41 @@ +package com.coding.week8; + +import java.util.ArrayList; +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 queue = new CircleQueue(); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + List list = new ArrayList<>(); + int j = 1; + /* + 循环将队首的元素弹出, + 若j=m则当前元素放入集合,j=1 + 若j0) { + Integer r = queue.deQueue(); + if (j == m) { + list.add(r); + j = 1; + } else if (j < m) { + queue.enQueue(r); + j++; + } + } + return list; + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/week8/QueueWithTwoStacks.java b/group24/494800949/src/main/java/com/coding/week8/QueueWithTwoStacks.java new file mode 100644 index 0000000000..fa30ad36f6 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week8/QueueWithTwoStacks.java @@ -0,0 +1,58 @@ +package com.coding.week8; + +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() && stack2.isEmpty(); + } + + + + public int size() { + return stack1.size() + stack2.size(); + } + + + + public void enQueue(E item) { + if(item == null){ + throw new RuntimeException("item cant be null"); + } + stack1.push(item); + } + + public E deQueue() { + if (isEmpty()) { + throw new RuntimeException("no data in queue"); + } + + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + return stack2.pop(); + } + + + + } + diff --git a/group24/494800949/src/main/java/com/coding/week9/QuickMinStack.java b/group24/494800949/src/main/java/com/coding/week9/QuickMinStack.java new file mode 100644 index 0000000000..7aea9e57be --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week9/QuickMinStack.java @@ -0,0 +1,45 @@ +package com.coding.week9; + + +//import java.util.Stack; + + +import java.util.ArrayList; +import java.util.List; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + List elements = new ArrayList<>(); + private int minNumIndex = 0; + + private boolean isSmaller(int data) { + if (elements.isEmpty()) { + return true; + } + if (data < elements.get(minNumIndex)) { + return true; + } + return false; + } + public void push(int data) { + elements.add(data); + if (isSmaller(data)) { + minNumIndex = elements.size() - 1; + } + + } + + public int pop() { + return elements.remove(elements.size() - 1); + } + + public int findMin() { + return elements.get(minNumIndex); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week9/StackWithTwoQueues.java b/group24/494800949/src/main/java/com/coding/week9/StackWithTwoQueues.java new file mode 100644 index 0000000000..f55bad77ca --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week9/StackWithTwoQueues.java @@ -0,0 +1,38 @@ +package com.coding.week9; + + +import com.coding.week8.CircleQueue; + +public class StackWithTwoQueues { + private CircleQueue queue1 = new CircleQueue<>(); + private CircleQueue queue2 = new CircleQueue<>(); + + public void push(int data) { + if (queue1.isEmpty()) { + queue1.enQueue(data); + } else { + queue2.enQueue(data); + } + } + + public int pop() { + if (queue1.isEmpty() && queue2.isEmpty()) { + throw new RuntimeException("stack is empty"); + } + if (queue2.isEmpty()) { + while (queue1.size() > 1) { + queue2.enQueue(queue1.deQueue()); + } + return queue1.deQueue(); + } else { + while (queue2.size() > 1) { + queue1.enQueue(queue2.deQueue()); + } + return queue2.deQueue(); + } + + + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/week9/TwoStackInOneArray.java b/group24/494800949/src/main/java/com/coding/week9/TwoStackInOneArray.java new file mode 100644 index 0000000000..1d7d613452 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week9/TwoStackInOneArray.java @@ -0,0 +1,102 @@ +package com.coding.week9; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + private int pos1 = 0; + private int pos2 = data.length - 1; + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if (o == null) { + throw new RuntimeException("data can not be null"); + } + data[pos1++] = o; + if (pos1 == pos2) { + doubleCapacity(); + } + } + + private void doubleCapacity(){ + int oldCapacity = data.length; + int newCapacity = oldCapacity << 1; + if (newCapacity < 0) { + throw new RuntimeException("capacity is too large"); + } + Object[] dataNew = new Object[newCapacity]; + System.arraycopy(data, 0, dataNew, 0, pos1); + int moveNum = oldCapacity - pos2; + int newPos2 = newCapacity - moveNum; + System.arraycopy(data, pos2, dataNew, newPos2, moveNum); + pos2 = newPos2; + data = dataNew; + } + + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if (pos1 == 0) { + throw new RuntimeException("stack1 is empty"); + } + Object e = data[--pos1]; + data[pos1] = null; + return e; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if (pos1 == 0) { + return null; + } + return data[pos1 - 1]; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if (o == null) { + throw new RuntimeException("data can not be null"); + } + data[pos2--] = o; + if (pos1 == pos2) { + doubleCapacity(); + } + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if (pos2 == data.length - 1) { + throw new RuntimeException("stack2 is empty"); + } + Object e = data[++pos2]; + data[pos2] = null; + return e; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if (pos2 == data.length - 1) { + return null; + } + return data[pos2 + 1]; + } + +} diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/MiniJVMTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..53694f30a4 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/MiniJVMTest.java @@ -0,0 +1,32 @@ +package com.coding.mini_jvm.test; + +import com.coding.mini_jvm.src.com.coderising.jvm.engine.MiniJVM; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class MiniJVMTest { + + // static final String PATH = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\answer\\bin"; +// static String PATH = "H:\\sourceCode\\coding2017\\group24\\494800949"; + static String PATH = "H:\\sourceCode\\coding2017\\group24\\494800949\\build\\classes\\main"; + static String PATH1 = "D:\\Java\\jdk1.8.0_25\\lib\\rt.jar"; + static String PATH2 = "D:\\Java\\jdk1.8.0_25\\jre\\lib\\rt"; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception { + String[] classPaths = {PATH, PATH1, PATH2}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coding.mini_jvm.src.com.coderising.jvm.EmployeeV1"); + + } + +} diff --git a/group24/494800949/src/test/java/com/coding/week8/CircleQueueTest.java b/group24/494800949/src/test/java/com/coding/week8/CircleQueueTest.java new file mode 100644 index 0000000000..239599e125 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week8/CircleQueueTest.java @@ -0,0 +1,55 @@ +package com.coding.week8; + + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/3 0003. + */ +public class CircleQueueTest { + private CircleQueue queue; + + @Before + public void setup(){ + queue = new CircleQueue<>(); + + } + @Test + public void testIsEmpty() throws Exception { + Assert.assertTrue(queue.isEmpty()); + queue.enQueue(10); + Assert.assertTrue(!queue.isEmpty()); + } + + @Test + public void testSize() throws Exception { + queue.enQueue(10); + queue.enQueue(2); + Assert.assertEquals(queue.size(), 2); + queue.deQueue(); + Assert.assertEquals(queue.size(), 1); + } + + @Test + public void testEnQueue() throws Exception { + for (int i = 0; i < 11; i++) { + queue.enQueue(i*i); + } + Assert.assertEquals((int)queue.deQueue(), 0); + Assert.assertEquals((int)queue.deQueue(), 1); + Assert.assertEquals((int)queue.deQueue(), 4); + Assert.assertEquals((int)queue.deQueue(), 9); + Assert.assertEquals((int)queue.deQueue(), 16); + Assert.assertEquals((int)queue.deQueue(), 25); + Assert.assertEquals((int)queue.deQueue(), 36); + Assert.assertEquals((int)queue.deQueue(), 49); + Assert.assertEquals((int)queue.deQueue(), 64); + Assert.assertEquals((int)queue.deQueue(), 81); + Assert.assertEquals((int)queue.deQueue(), 100); + Assert.assertEquals(queue.deQueue(), null); + } + + +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week8/JosephusTest.java b/group24/494800949/src/test/java/com/coding/week8/JosephusTest.java new file mode 100644 index 0000000000..9fa029f027 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week8/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.week8; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group24/494800949/src/test/java/com/coding/week8/QueueWithTwoStacksTest.java b/group24/494800949/src/test/java/com/coding/week8/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..86ae2b57c9 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week8/QueueWithTwoStacksTest.java @@ -0,0 +1,31 @@ +package com.coding.week8; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/6 0006. + */ +public class QueueWithTwoStacksTest { + + private QueueWithTwoStacks queue; + + @Before + public void setup(){ + queue = new QueueWithTwoStacks<>(); + } + @Test + public void testEnQueue() throws Exception { + queue.enQueue(1); + queue.enQueue(5); + queue.enQueue(8); + + Assert.assertEquals((int) queue.deQueue(), 1); + queue.enQueue(10); + Assert.assertEquals((int) queue.deQueue(), 5); + Assert.assertEquals((int) queue.deQueue(), 8); + Assert.assertEquals((int)queue.deQueue(), 10); + + } +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week9/QuickMinStackTest.java b/group24/494800949/src/test/java/com/coding/week9/QuickMinStackTest.java new file mode 100644 index 0000000000..a88ae6208f --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week9/QuickMinStackTest.java @@ -0,0 +1,20 @@ +package com.coding.week9; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/7 0007. + */ +public class QuickMinStackTest { + + @Test + public void testFindMin() throws Exception { + QuickMinStack quickMinStack = new QuickMinStack(); + quickMinStack.push(10); + quickMinStack.push(9); + quickMinStack.push(100); + quickMinStack.push(19); + Assert.assertEquals(quickMinStack.findMin(), 9); + } +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week9/StackWithTwoQueuesTest.java b/group24/494800949/src/test/java/com/coding/week9/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..0d7913883e --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week9/StackWithTwoQueuesTest.java @@ -0,0 +1,29 @@ +package com.coding.week9; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/7 0007. + */ +public class StackWithTwoQueuesTest { + + + + + @Test + public void testPush() throws Exception { + StackWithTwoQueues stackWithTwoQueues = new StackWithTwoQueues(); + stackWithTwoQueues.push(1); + stackWithTwoQueues.push(2); + stackWithTwoQueues.push(3); + stackWithTwoQueues.push(4); + stackWithTwoQueues.push(5); + Assert.assertEquals(stackWithTwoQueues.pop(), 5); + Assert.assertEquals(stackWithTwoQueues.pop(), 4); + Assert.assertEquals(stackWithTwoQueues.pop(), 3); + Assert.assertEquals(stackWithTwoQueues.pop(), 2); + Assert.assertEquals(stackWithTwoQueues.pop(), 1); + } + +} \ No newline at end of file diff --git a/group24/494800949/src/test/java/com/coding/week9/TwoStackInOneArrayTest.java b/group24/494800949/src/test/java/com/coding/week9/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..b3481715ec --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week9/TwoStackInOneArrayTest.java @@ -0,0 +1,43 @@ +package com.coding.week9; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/7 0007. + */ +public class TwoStackInOneArrayTest { + + private TwoStackInOneArray stackInOneArray; + + @Before + public void setup(){ + stackInOneArray = new TwoStackInOneArray(); + } + @Test + public void testPush1() throws Exception { + stackInOneArray.push1(10); + stackInOneArray.push1(20); + stackInOneArray.push1(30); + stackInOneArray.push1(88); + stackInOneArray.push1(30); + stackInOneArray.push1(99); + stackInOneArray.push2(100); + stackInOneArray.push2(90); + stackInOneArray.push2(80); + stackInOneArray.push2(77); + stackInOneArray.push2(66); + Assert.assertEquals(stackInOneArray.peek1(), 99); + Assert.assertEquals(stackInOneArray.pop1(), 99); + Assert.assertEquals(stackInOneArray.pop1(), 30); + + Assert.assertEquals(stackInOneArray.peek2(), 66); + Assert.assertEquals(stackInOneArray.pop2(), 66); + Assert.assertEquals(stackInOneArray.pop2(), 77); + Assert.assertEquals(stackInOneArray.pop2(), 80); + Assert.assertEquals(stackInOneArray.pop2(), 90); + } + + +} \ No newline at end of file diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/CircleQueue.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..11baf8fbba --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/CircleQueue.java @@ -0,0 +1,101 @@ +package com.github.wdn.coding2017.basic.queue; + +import java.util.Arrays; + +/** + * Created by Administrator on 2017/5/2 0002. + */ +public class CircleQueue { + private final static int DEFAULT_SIZE = 10; + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + //队头 + private int front = 0; + //队尾 + private int rear = 0; + private int size = 0; + + public static void main(String[] args) { + CircleQueue queue = new CircleQueue<>(9); + for (int i = 0; i < 5; i++) { + queue.enQueue(i); + } + System.out.println(Arrays.toString(queue.elementData)); + System.out.println("size"+queue.size); + for (int i = 0; i < 3; i++) { + if(!queue.isEmpty()){ + System.out.println(queue.deQueue()); + } + } + System.out.println(Arrays.toString(queue.elementData)); + System.out.println("size"+queue.size); + for (int i = 0; i < 5; i++) { + queue.enQueue(i); + } + System.out.println(Arrays.toString(queue.elementData)); + System.out.println("size"+queue.size); + for (int i = 0; i < 2; i++) { + if(!queue.isEmpty()){ + System.out.println(queue.deQueue()); + } + } + System.out.println(Arrays.toString(queue.elementData)); + System.out.println("size"+queue.size); + for (int i = 6; i < 9; i++) { + queue.enQueue(i); + } + System.out.println(queue.front); + System.out.println(queue.rear); + System.out.println(Arrays.toString(queue.elementData)); + System.out.println("size"+queue.size); + while (!queue.isEmpty()){ + System.out.print(queue.deQueue()); + } + System.out.println(""); + System.out.println(queue.front); + System.out.println(queue.rear); + System.out.println(queue.isEmpty()); + } + public CircleQueue(){ + + } + public CircleQueue(int defaultSize){ + elementData = new Object[defaultSize]; + } + public boolean isEmpty() { + return size==0;//front==rear && elementData[front]==null; + } + + public int size() { + return size; + } + + public void enQueue(E data) { + if(size==elementData.length){ + throw new RuntimeException("queue is full"); + } + + elementData[rear] = data; + size++; + if(rear==elementData.length-1){ + rear=0; + }else { + rear++; + } + } + + public E deQueue() { + if(isEmpty()){ + throw new RuntimeException("queue is empty"); + } + E result = (E)elementData[front]; + elementData[front]=null; + size--; + if(front==elementData.length-1){ + front=0; + }else { + front++; + } + return result; + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/Josephus.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/Josephus.java new file mode 100644 index 0000000000..01116c9d05 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/Josephus.java @@ -0,0 +1,38 @@ +package com.github.wdn.coding2017.basic.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/5/2 0002. + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * @author liuxin + * + */ +public class Josephus { + private static CircleQueue queue; + private static void init(int n){ + queue = new CircleQueue<>(n); + for (int i = 0; i < n; i++) { + queue.enQueue(i); + } + } + public static List execute(int n, int m){ + init(n); + List result = new ArrayList<>(n); + int start = 1;//从1开始数 + while (!queue.isEmpty()){ + if(start==m){ + result.add(queue.deQueue()); + start = 1; + }else{ + queue.enQueue(queue.deQueue()); + start++; + } + } + return result; + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/JosephusTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..e913f84846 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/JosephusTest.java @@ -0,0 +1,28 @@ +package com.github.wdn.coding2017.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/5/2 0002. + */ +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/QueueWithTwoStacks.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..f7d244f4cf --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,57 @@ +package com.github.wdn.coding2017.basic.queue; + +import java.util.Stack; + +/** + * Created by Administrator on 2017/5/2 0002. + * 用两个栈来实现一个队列 + */ +public class QueueWithTwoStacks { + private Stack stack1; + private Stack stack2; + private int size; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return size==0; + } + + public int size() { + return size; + } + + public void enQueue(E item) { + stack1.push(item); + size++; + } + + public E deQueue() { + if (stack2.isEmpty()){ + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + size--; + return stack2.pop(); + } + + public static void main(String[] args) { + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + for (int i = 0; i < 10; i++) { + queue.enQueue(i); + } + for (int i = 0; i < 5; i++) { + System.out.print(queue.deQueue()); + } + for (int i = 10; i < 20; i++) { + queue.enQueue(i); + } + while (!queue.isEmpty()){ + System.out.println(queue.deQueue()); + } + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/QuickMinStack.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..642a75c90a --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/QuickMinStack.java @@ -0,0 +1,60 @@ +package com.github.wdn.coding2017.basic.stack; + +import java.util.*; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * Created by Administrator on 2017/5/6 0006. + */ +public class QuickMinStack { + private Stack stack = new Stack<>(); + private Map minIndexMap = new HashMap<>(); + private List minIndexs = new ArrayList<>(); + + public static void main(String[] args) { + QuickMinStack quickMinStack = new QuickMinStack(); + //int[] ints = {5,4,3,2,1,0}; + int[] ints = {4,1,2,5,3,0}; + for (int i = 0; i < ints.length; i++) { + quickMinStack.push(ints[i]); + } + quickMinStack.status(); + while (!quickMinStack.isEmpty()){ + System.out.print("min:"+quickMinStack.findMin()); + System.out.println(" pop:"+quickMinStack.pop()); + } + } + public void push(E data){ + stack.push(data); + if(minIndexs.size()==0){ + minIndexMap.put(0,data); + minIndexs.add(0); + }else { + if(findMin().compareTo(data)>0){ + minIndexMap.put(stack.size()-1,data); + minIndexs.add(stack.size()-1); + } + } + } + public E pop(){ + E min = findMin(); + E result = stack.peek(); + if(min==result){ + minIndexMap.remove(minIndexs.get(minIndexs.size()-1)); + minIndexs.remove(minIndexs.size()-1); + } + return stack.pop(); + } + public E findMin(){ + return minIndexMap.get(minIndexs.get(minIndexs.size()-1)); + } + public boolean isEmpty(){ + return stack.isEmpty(); + } + public void status(){ + System.out.println(stack); + System.out.println(minIndexs); + System.out.println(minIndexMap); + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackWithTwoQueues.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..0a7fe2176c --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,57 @@ +package com.github.wdn.coding2017.basic.stack; + + +import com.github.wdn.coding2017.basic.Queue; + +/** + * Created by Administrator on 2017/5/6 0006. + */ +public class StackWithTwoQueues { + Queue queue1 = new Queue(); + Queue queue2 = new Queue(); + + public static void main(String[] args) { + StackWithTwoQueues stack = new StackWithTwoQueues<>(); + for (int i = 0; i < 5; i++) { + stack.push(i); + } + for (int i = 0; i < 3; i++) { + System.out.println(stack.pop()); + } + System.out.println(""); + for (int i = 0; i < 5; i++) { + stack.push(i); + } + while (!stack.isEmpty()) { + System.out.println(stack.pop()); + } + } + public void push(E data){ + if(queue1.isEmpty()){ + queue2.enQueue(data); + }else{ + queue1.enQueue(data); + } + } + public E pop(){ + if(isEmpty()){ + throw new RuntimeException("stack is empty"); + } + if(queue1.isEmpty()){ + int len = queue2.size(); + for (int i = 0; i < len-1; i++) { + queue1.enQueue(queue2.deQueue()); + } + return (E)queue2.deQueue(); + }else{ + int len = queue1.size(); + for (int i = 0; i < len-1; i++) { + queue2.enQueue(queue1.deQueue()); + } + return (E)queue1.deQueue(); + } + } + public boolean isEmpty(){ + return queue1.isEmpty() && queue2.isEmpty(); + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/TwoStackInOneArray.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..935611d9c8 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,73 @@ +package com.github.wdn.coding2017.basic.stack; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底, + * 压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * Created by Administrator on 2017/5/6 0006. + */ +public class TwoStackInOneArray { + private Object[] ints = new Object[10]; + private int head1 = -1; + private int head2 = ints.length; + + public static void main(String[] args) { + TwoStackInOneArray stack = new TwoStackInOneArray(); + for (int i = 11; i > 0; i--) { + stack.push2(i); + } + for (int i = 0; i < 8; i++) { + stack.push1(i); + } + stack.pop1(); + for (int i = 0; i < 4; i++) { + stack.push1(i); + } + + System.out.println(Arrays.toString(stack.ints)); + } + public void push1(Object data){ + if(head1+1=0 && ints[head2-1]==null){ + ints[--head2] = data; + }else{ + grow(); + ints[--head2] = data; + } + } + public Object pop1(){ + if(head1<0){ + throw new RuntimeException("stack1 is empty"); + } + Object result = ints[head1]; + ints[head1] = null; + head1--; + return result; + } + public Object pop2(){ + if(head2>=ints.length){ + throw new RuntimeException("stack2 is empty"); + } + Object result = ints[head2]; + ints[head2] = null; + head2++; + return result; + } + public void grow(){ + Object[] newArr = new Object[ints.length * 2]; + System.arraycopy(ints,0,newArr,0,head1+1); + System.arraycopy(ints, head2, newArr, newArr.length-(ints.length-head2), ints.length-head2); + head2 = newArr.length-(ints.length-head2); + ints = newArr; + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExpr.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExpr.java index 3a8f013b78..cc20a975cc 100644 --- a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExpr.java +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExpr.java @@ -3,44 +3,17 @@ import com.github.wdn.coding2017.basic.Stack; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; /** * Created by Administrator on 2017/4/13 0013. */ public class InfixExpr { private String expr; - private static Map priorityMap = new HashMap(); - static{ - priorityMap.put("+",1); - priorityMap.put("-",1); - priorityMap.put("*",2); - priorityMap.put("/",2); - } + public InfixExpr(String expr) { this.expr = expr; } - public float calculate(float a,float b,String operator) throws IllegalAccessException { - float result; - switch (operator) { - case "+": - result = a+b; - break; - case "-": - result = a-b; - break; - case "*": - result = a*b; - break; - case "/": - result = a/b; - break; - default: - throw new IllegalAccessException(); - } - return result; - } + public float evaluate() { try { String[] numArr = expr.split("[+|\\-|*|/]"); @@ -52,14 +25,14 @@ public float evaluate() { for (int i = 0; i < operators.length; i++) { int number = Integer.parseInt(numArr[i + 1]); String operator = operators[i].toString(); - if (!operatorStack.isEmpty() && priorityMap.get(operatorStack.peek()) < priorityMap.get(operator)) { - float currentResult = calculate(Integer.parseInt(numStack.pop().toString()), number, operator); + if (!operatorStack.isEmpty() && Operator.compare(operatorStack.peek().toString(),operator)<0) { + float currentResult = Operator.calculate(Integer.parseInt(numStack.pop().toString()), number, operator); numStack.push(currentResult); - } else if(!operatorStack.isEmpty() && priorityMap.get(operatorStack.peek()) >= priorityMap.get(operator)){ + } else if(!operatorStack.isEmpty() && Operator.compare(operatorStack.peek().toString(),operator)>=0){ float b = Float.parseFloat(numStack.pop().toString()); float a = Float.parseFloat(numStack.pop().toString()); String currentOperator = operatorStack.pop().toString(); - float result = calculate(a, b, currentOperator); + float result = Operator.calculate(a, b, currentOperator); numStack.push(result); numStack.push(number); operatorStack.push(operator); @@ -72,7 +45,7 @@ public float evaluate() { float b = Float.parseFloat(numStack.pop().toString()); float a = Float.parseFloat(numStack.pop().toString()); String operator = operatorStack.pop().toString(); - float result = calculate(a, b, operator); + float result = Operator.calculate(a, b, operator); numStack.push(result); } return Float.parseFloat(numStack.pop().toString()); @@ -81,10 +54,4 @@ public float evaluate() { } return 0; } - - public static void main(String[] args) { - InfixExpr infixExpr = new InfixExpr("2+3*4+5"); - float r = infixExpr.evaluate(); - System.out.println(r); - } } diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixToPostfix.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..e3b5541cbc --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,59 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +import com.github.wdn.coding2017.basic.Stack; + +import java.util.Arrays; + +/** + * Created by Administrator on 2017/5/1 0001. + */ +public class InfixToPostfix { + public static String convert(String expr) { + //"3*20+12*5-40/2"==100 + //3 20*12 5*+ 40 2/- + try { + String[] numArr = expr.split("[+|\\-|*|/]"); + String[] operatorArr = expr.split("\\d+\\d*"); + Object[] operators = Arrays.stream(operatorArr).filter(x -> !"".equals(x.trim())).toArray(); + Stack numStack = new Stack(); + Stack operatorStack = new Stack(); + numStack.push(numArr[0]); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < operators.length; i++) { + int number = Integer.parseInt(numArr[i + 1]); + String operator = operators[i].toString(); + if (!operatorStack.isEmpty() && Operator.compare(operatorStack.peek().toString(),operator)<0) { + String currentResult = numStack.pop()+" "+number+operator; + numStack.push(currentResult); + } else if(!operatorStack.isEmpty() && Operator.compare(operatorStack.peek().toString(),operator)>=0){ + Object b = numStack.pop(); + Object a = numStack.pop(); + String currentOperator = operatorStack.pop().toString(); + String result = a+" "+b+currentOperator; + numStack.push(result); + numStack.push(number); + operatorStack.push(operator); + }else { + numStack.push(number); + operatorStack.push(operator); + } + } + while (!operatorStack.isEmpty()) { + Object b = numStack.pop(); + Object a = numStack.pop(); + String operator = operatorStack.pop().toString(); + String result = a+" "+b+operator; + numStack.push(result); + } + return numStack.pop().toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + public static void main(String[] args) { + String s = InfixToPostfix.convert("3*20+12*5-40/2"); + System.out.println(s); + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/Operator.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/Operator.java new file mode 100644 index 0000000000..4eb0ebc449 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/Operator.java @@ -0,0 +1,44 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Administrator on 2017/4/18 0018. + */ +public class Operator { + private static Map priorityMap = new HashMap(); + static{ + priorityMap.put("+",1); + priorityMap.put("-",1); + priorityMap.put("*",2); + priorityMap.put("/",2); + } + public static int compare(String a, String b){ + int result = priorityMap.get(a)-priorityMap.get(b); + return result == 0 ? 0 : result > 0 ? 1 : -1; + } + public static boolean isOperator(char o){ + return o=='+' || o=='-'|| o=='*'|| o=='/'; + } + public static float calculate(float a,float b,String operator) throws IllegalAccessException { + float result; + switch (operator) { + case "+": + result = a+b; + break; + case "-": + result = a-b; + break; + case "*": + result = a*b; + break; + case "/": + result = a/b; + break; + default: + throw new IllegalAccessException(); + } + return result; + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExpr.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..4851d4e6c7 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,44 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +import java.util.Arrays; +import java.util.List; +import java.util.Stack; + +public class PostfixExpr { +String expr = null; + + public PostfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + try{ + Stack stack = new Stack(); + char[] exprArr = expr.toCharArray(); + String numStr=""; + for (int i = 0; i < exprArr.length; i++) { + char c = exprArr[i]; + if(!Operator.isOperator(c) && c!=' '){ + numStr = numStr+c; + continue; + } + if(!"".equals(numStr)){ + stack.push(numStr); + numStr=""; + } + if (Operator.isOperator(c)) { + String first = stack.pop().toString(); + String second = stack.pop().toString(); + float result = Operator.calculate(Float.parseFloat(second), Float.parseFloat(first), c+""); + stack.push(result); + } + } + return Float.parseFloat(stack.pop().toString()); + } catch (Exception e) { + e.printStackTrace(); + } + return 0.0f; + } + + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExprTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..d14577f34f --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PostfixExprTest.java @@ -0,0 +1,46 @@ +package com.github.wdn.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); + } + { + //10-2*3+50 + PostfixExpr expr = new PostfixExpr("3 20 *12 5*+ 40 2/-"); + Assert.assertEquals(100, expr.evaluate(),0.0f); + } + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExpr.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..0adc78b777 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,38 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +import java.util.Arrays; +import java.util.Stack; + +public class PrefixExpr { + String expr = null; + + public PrefixExpr(String expr) { + this.expr = expr; + } + public float evaluate() { + try { + Stack stack = new Stack(); + char[] exprArr = expr.toCharArray(); + String numStr=""; + for (int i = exprArr.length - 1; i >= 0; i--) { + char c = exprArr[i]; + if(!Operator.isOperator(c) && c!=' '){ + numStr = numStr+c; + continue; + } + if(!"".equals(numStr)){ + stack.push(numStr); + numStr=""; + } + if (Operator.isOperator(c)) { + float result = Operator.calculate(Float.parseFloat(stack.pop().toString()), Float.parseFloat(stack.pop().toString()), c+""); + stack.push(result); + } + } + return Float.parseFloat(stack.pop().toString()); + } catch (Exception e) { + e.printStackTrace(); + } + return 0; + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExprTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5629d9df60 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/PrefixExprTest.java @@ -0,0 +1,45 @@ +package com.github.wdn.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/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/CodeAttr.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/CodeAttr.java index 9400b629b2..0636e104ee 100644 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/CodeAttr.java +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/CodeAttr.java @@ -1,5 +1,12 @@ package com.github.wdn.coding2017.jvm.attr; +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.wdn.coding2017.jvm.cmd.CommandParser; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; +import com.github.wdn.coding2017.jvm.util.Util; + /** * Created by Administrator on 2017/4/12 0012. */ @@ -10,11 +17,45 @@ public class CodeAttr extends AttributeInfo { private LineNumberTable lineNumTable; private LocalVariableTable localVarTable; private StackMapTable stackMapTable; - public CodeAttr(int attributeNameIndex, int attributeLength, int maxStack, int maxLocals, String code) { + private ByteCodeCommand[] cmds; + public CodeAttr(int attributeNameIndex, int attributeLength, int maxStack, int maxLocals, String code,ByteCodeCommand[] commands) { super(attributeNameIndex, attributeLength); this.maxStack = maxStack; this.maxLocals = maxLocals; this.code = code; + this.cmds = commands; + } + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + int attributeNameIndex = iter.readU2ToInt(); + int attributeLength = iter.readU4ToInt(); + int maxStack = iter.readU2ToInt(); + int maxLocals = iter.readU2ToInt(); + String codeStr = iter.readCustomToString(iter.readU4ToInt()); + ByteCodeCommand[] cmds = CommandParser.parse(clzFile,codeStr); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex,attributeLength, maxStack, maxLocals, codeStr, cmds); + int ExceptionCount = iter.readU2ToInt(); + if (ExceptionCount > 0) { + throw new RuntimeException("方法有异常待解析"); + } + int codeAttributesCount = iter.readU2ToInt(); + for (int k = 0; k < codeAttributesCount; k++) { + int codeAttributeNameIndex = iter.readU2ToInt(); + String codeAttributeType = clzFile.getConstantPool().getConstantInfo(codeAttributeNameIndex).getValue(); + codeAttributeType = Util.hexString2String(codeAttributeType); + if ("LineNumberTable".equals(codeAttributeType)) { + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumTable(lineNumberTable); + } else if ("LocalVariableTable".equals(codeAttributeType)) { + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVarTable(localVariableTable); + }else if ("StackMapTable".equals(codeAttributeType)) { + StackMapTable stackMapTable = StackMapTable.parse(iter); + codeAttr.setStackMapTable(stackMapTable); + } else { + throw new RuntimeException("未知的Code附加属性类型" + codeAttributeType); + } + } + return codeAttr; } @Override public String toString(){ @@ -55,4 +96,8 @@ public void setLocalVarTable(LocalVariableTable localVarTable) { public void setStackMapTable(StackMapTable stackMapTable) { this.stackMapTable = stackMapTable; } + + public ByteCodeCommand[] getCmds() { + return cmds; + } } diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassFile.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassFile.java index 813c050a53..a9a58d375a 100644 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassFile.java +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassFile.java @@ -1,6 +1,8 @@ package com.github.wdn.coding2017.jvm.clz; import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.field.Field; +import com.github.wdn.coding2017.jvm.method.Method; import java.util.List; @@ -77,4 +79,8 @@ public List getMethods() { public void setMethods(List methods) { this.methods = methods; } + + public Method getMainMethod() { + return null; + } } diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Field.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Field.java deleted file mode 100644 index 8d557b10de..0000000000 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Field.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.github.wdn.coding2017.jvm.clz; - -import com.github.wdn.coding2017.jvm.constant.ConstantPool; -import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Administrator on 2017/4/10 0010. - */ -public class Field { - private AccessFlag accessFlag; // 例如是public , private 等等 - private int nameIndex; // 指向常量池的入口 - private int descriptorIndex; //指向常量池的入口 - private int attributesCount; // 该字段的属性有多少个 - private ConstantPool pool; - // attribute_info attributes[attributes_count]; //属性信息 - private Field(){ - } - public Field(ConstantPool pool){ - this.pool = pool; - } - public static Field parse(ByteCodeIterator iter){ - Field field = new Field(); - field.setAccessFlags(new AccessFlag(iter.readU2ToInt())); - field.setNameIndex(iter.readU2ToInt()); - field.setDescriptorIndex(iter.readU2ToInt()); - int attCount = iter.readU2ToInt(); - if(attCount>0){ - throw new RuntimeException("字段属性数量大于0"); - } - field.setAttributesCount(attCount); - return field; - } - public String toString(){ - return pool.getConstantInfo(nameIndex).getValue()+pool.getConstantInfo(descriptorIndex).getValue(); - } - public AccessFlag getAccessFlags() { - return accessFlag; - } - - public void setAccessFlags(AccessFlag accessFlags) { - this.accessFlag = accessFlags; - } - - public int getNameIndex() { - return nameIndex; - } - - public void setNameIndex(int nameIndex) { - this.nameIndex = nameIndex; - } - - public int getDescriptorIndex() { - return descriptorIndex; - } - - public void setDescriptorIndex(int descriptorIndex) { - this.descriptorIndex = descriptorIndex; - } - - public int getAttributesCount() { - return attributesCount; - } - - public void setAttributesCount(int attributesCount) { - this.attributesCount = attributesCount; - } - - public void setPool(ConstantPool pool) { - this.pool = pool; - } -} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Method.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Method.java deleted file mode 100644 index b6ace8ebce..0000000000 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Method.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.github.wdn.coding2017.jvm.clz; - -import com.github.wdn.coding2017.jvm.attr.*; -import com.github.wdn.coding2017.jvm.constant.ConstantPool; -import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; - -/** - * Created by Administrator on 2017/4/10 0010. - */ -public class Method { - private AccessFlag accessFlags; - private int nameIndex; - private int descriptorIndex; - private CodeAttr code; - //attributes[attributes_count]; - private ConstantPool pool; - public static Method parse(ConstantPool pool, ByteCodeIterator iter) { - Method method = new Method(); - method.setAccessFlags(new AccessFlag(iter.readU2ToInt())); - method.setNameIndex(iter.readU2ToInt()); - method.setDescriptorIndex(iter.readU2ToInt()); - int methodAttributesCount = iter.readU2ToInt(); - for (int j = 0; j < methodAttributesCount; j++) { - int methodAttributeNameIndex = iter.readU2ToInt(); - String methodAttributeType = pool.getConstantInfo(methodAttributeNameIndex).getValue(); - if (methodAttributeType.equals(AttributeInfo.CODE)) { - CodeAttr codeAttr = new CodeAttr(methodAttributeNameIndex, iter.readU4ToInt(), iter.readU2ToInt(), iter.readU2ToInt(), iter.readCustomToString(iter.readU4ToInt())); - int ExceptionCount = iter.readU2ToInt(); - if (ExceptionCount > 0) { - throw new RuntimeException("方法有异常待解析"); - } - int codeAttributesCount = iter.readU2ToInt(); - for (int k = 0; k < codeAttributesCount; k++) { - int codeAttributeNameIndex = iter.readU2ToInt(); - String codeAttributeType = pool.getConstantInfo(codeAttributeNameIndex).getValue(); - if ("LineNumberTable".equals(codeAttributeType)) { - LineNumberTable lineNumberTable = LineNumberTable.parse(iter); - codeAttr.setLineNumTable(lineNumberTable); - } else if ("LocalVariableTable".equals(codeAttributeType)) { - LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); - codeAttr.setLocalVarTable(localVariableTable); - }else if ("StackMapTable".equals(codeAttributeType)) { - StackMapTable stackMapTable = StackMapTable.parse(iter); - codeAttr.setStackMapTable(stackMapTable); - } else { - throw new RuntimeException("未知的Code附加属性类型" + codeAttributeType); - } - } - method.setCode(codeAttr); - } else { - throw new RuntimeException("未知的方法属性类型" + methodAttributeType); - } - } - return method; - } - @Override - public String toString(){ - StringBuffer stringBuffer = new StringBuffer(); - stringBuffer.append(pool.getConstantInfo(nameIndex).getValue()); - stringBuffer.append(pool.getConstantInfo(descriptorIndex).getValue()); - stringBuffer.append(code); - return stringBuffer.toString(); - } - public AccessFlag getAccessFlags() { - return accessFlags; - } - - public void setAccessFlags(AccessFlag accessFlags) { - this.accessFlags = accessFlags; - } - - public int getNameIndex() { - return nameIndex; - } - - public void setNameIndex(int nameIndex) { - this.nameIndex = nameIndex; - } - - public int getDescriptorIndex() { - return descriptorIndex; - } - - public void setDescriptorIndex(int descriptorIndex) { - this.descriptorIndex = descriptorIndex; - } - - public CodeAttr getCode() { - return code; - } - - public void setCode(CodeAttr code) { - this.code = code; - } - - public void setPool(ConstantPool pool) { - this.pool = pool; - } -} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/BiPushCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..915118d7ed --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/BiPushCmd.java @@ -0,0 +1,22 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class BiPushCmd extends OneOperandCmd { + + public BiPushCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); + } + + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/ByteCodeCommand.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..7de312abab --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/ByteCodeCommand.java @@ -0,0 +1,129 @@ +package com.github.wdn.coding2017.jvm.cmd; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantInfo; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +import java.util.HashMap; +import java.util.Map; + + + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + private static Map codeMap = new HashMap(); + + static{ + codeMap.put("01", "aconst_null"); + + codeMap.put("BB", "new"); + codeMap.put("37", "lstore"); + codeMap.put("B7", "invokespecial"); + codeMap.put("B6", "invokevirtual"); + codeMap.put("B4", "getfield"); + codeMap.put("B5", "putfield"); + codeMap.put("B2", "getstatic"); + + codeMap.put("2A", "aload_0"); + codeMap.put("2B", "aload_1"); + codeMap.put("2C", "aload_2"); + + codeMap.put("10", "bipush"); + codeMap.put("15", "iload"); + codeMap.put("1A", "iload_0"); + codeMap.put("1B", "iload_1"); + codeMap.put("1C", "iload_2"); + codeMap.put("1D", "iload_3"); + + codeMap.put("25", "fload_3"); + + codeMap.put("1E", "lload_0"); + + codeMap.put("24", "fload_2"); + codeMap.put("4C", "astore_1"); + + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + + codeMap.put("A7", "goto"); + + codeMap.put("B1", "return"); + codeMap.put("AC", "ireturn"); + codeMap.put("AE", "freturn"); + + codeMap.put("03", "iconst_0"); + codeMap.put("04", "iconst_1"); + + codeMap.put("3C", "istore_1"); + codeMap.put("3D", "istore_2"); + + codeMap.put("59", "dup"); + + codeMap.put("60", "iadd"); + codeMap.put("84", "iinc"); + + codeMap.put("12", "ldc"); + } + + + + + + protected ByteCodeCommand(ClassFile clzFile, String opCode){ + this.clzFile = clzFile; + this.opCode = opCode; + } + + protected ClassFile getClassFile() { + return clzFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + protected ConstantInfo getConstantInfo(int index){ + return this.getClassFile().getConstantPool().getConstantInfo(index); + } + + protected ConstantPool getConstantPool(){ + return this.getClassFile().getConstantPool(); + } + + + + public String getOpCode() { + return opCode; + } + + public abstract int getLength(); + + + + + public String toString(){ + + StringBuffer buffer = new StringBuffer(); + buffer.append(this.opCode); + + return buffer.toString(); + } + public abstract String toString(ConstantPool pool); + + public String getReadableCodeText(){ + String txt = codeMap.get(opCode); + if(txt == null){ + return opCode; + } + return txt; + } + + //public abstract void execute(StackFrame frame,FrameResult result); +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/CommandParser.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..efb8e123b6 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/CommandParser.java @@ -0,0 +1,129 @@ +package com.github.wdn.coding2017.jvm.cmd; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/4/21 0021. + */ +public class CommandParser { + public static final String nop = "00"; + 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) { + List cmdList = new ArrayList<>(); + CommandIterator commandIterator = new CommandIterator(codes); + while (commandIterator.hasNext()) { + String cmdCode = commandIterator.read2ToString(); + cmdCode = cmdCode.toUpperCase(); + if (cmdCode.equals(new_object)) { + NewObjectCmd cmd = new NewObjectCmd(clzFile, cmdCode); + cmd.setOprand1(commandIterator.read2ToInt()); + cmd.setOprand2(commandIterator.read2ToInt()); + cmdList.add(cmd); + }else if (cmdCode.equals(invokespecial)) { + InvokeSpecialCmd cmd = new InvokeSpecialCmd(clzFile,cmdCode); + cmd.setOprand1(commandIterator.read2ToInt()); + cmd.setOprand2(commandIterator.read2ToInt()); + cmdList.add(cmd); + } else if (getstatic.equals(cmdCode)) { + GetStaticFieldCmd cmd = new GetStaticFieldCmd(clzFile, cmdCode); + cmd.setOprand1(commandIterator.read2ToInt()); + cmd.setOprand2(commandIterator.read2ToInt()); + cmdList.add(cmd); + } else if (putfield.equals(cmdCode)) { + PutFieldCmd cmd = new PutFieldCmd(clzFile, cmdCode); + cmd.setOprand1(commandIterator.read2ToInt()); + cmd.setOprand2(commandIterator.read2ToInt()); + cmdList.add(cmd); + } else if (ldc.equals(cmdCode)) { + LdcCmd cmd = new LdcCmd(clzFile, cmdCode); + cmd.setOperand(commandIterator.read2ToInt()); + cmdList.add(cmd); + } else if (bipush.equals(cmdCode)) { + BiPushCmd cmd = new BiPushCmd(clzFile, cmdCode); + cmd.setOperand(commandIterator.read2ToInt()); + cmdList.add(cmd); + } else if (invokevirtual.equals(cmdCode)) { + InvokeVirtualCmd cmd = new InvokeVirtualCmd(clzFile, cmdCode); + cmd.setOprand1(commandIterator.read2ToInt()); + cmd.setOprand2(commandIterator.read2ToInt()); + cmdList.add(cmd); + }else if (dup.equals(cmdCode) || aload_0.equals(cmdCode) || aload_1.equals(cmdCode) || aload_2.equals(cmdCode) + || iload_1.equals(cmdCode) || iload_2.equals(cmdCode) || iload_3.equals(cmdCode) + || fload_3.equals(cmdCode) || voidreturn.equals(cmdCode) || astore_1.equals(cmdCode)) { + + NoOperandCmd cmd = new NoOperandCmd(clzFile, cmdCode); + cmdList.add(cmd); + }else{ + throw new RuntimeException("未知的指令类型:"+cmdCode); + } + } + calcuateOffset(cmdList); + ByteCodeCommand[] result = new ByteCodeCommand[cmdList.size()]; + cmdList.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{ + private String codes; + int offset = 0; + public CommandIterator(String codes){ + this.codes = codes; + } + public boolean hasNext(){ + return offset < codes.length(); + } + public int read2ToInt(){ + String s = this.read2ToString(); + return Integer.valueOf(s, 16).intValue(); + } + public String read2ToString(){ + String result = codes.substring(offset,offset+2); + offset+=2; + return result; + } + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetFieldCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..87339a7cc1 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetFieldCmd.java @@ -0,0 +1,22 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetStaticFieldCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..c866c4060d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/GetStaticFieldCmd.java @@ -0,0 +1,20 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeSpecialCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ee1079b127 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeSpecialCmd.java @@ -0,0 +1,22 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeVirtualCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..758bfc8733 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/InvokeVirtualCmd.java @@ -0,0 +1,22 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/LdcCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..fda05c9ab1 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/LdcCmd.java @@ -0,0 +1,30 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantInfo; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.constant.StringInfo; + +public class LdcCmd extends OneOperandCmd { + + public LdcCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + String value = "TBD"; + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + value = strInfo.toString(); + } + + return this.getOffset()+":"+this.getOpCode()+" " + this.getReadableCodeText() + " "+ value; + + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NewObjectCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..fa974d3caf --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NewObjectCmd.java @@ -0,0 +1,18 @@ +package com.github.wdn.coding2017.jvm.cmd; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +/** + * Created by Administrator on 2017/4/21 0021. + */ +public class NewObjectCmd extends TwoOperandCmd { + public NewObjectCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return null; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NoOperandCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..9504d1b718 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/NoOperandCmd.java @@ -0,0 +1,24 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class NoOperandCmd extends ByteCodeCommand{ + + public NoOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } + + @Override + public String toString(ConstantPool pool) { + return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); + } + + + + public int getLength(){ + return 1; + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/OneOperandCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..400a70d54d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/OneOperandCmd.java @@ -0,0 +1,28 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; + +public abstract class OneOperandCmd extends ByteCodeCommand { + + private int operand; + + public OneOperandCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + public int getOperand() { + + return this.operand; + } + + public void setOperand(int oprand1) { + this.operand = oprand1; + + } + public int getLength(){ + return 2; + } + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/PutFieldCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..d53680c73b --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/PutFieldCmd.java @@ -0,0 +1,20 @@ +package com.github.wdn.coding2017.jvm.cmd; + + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/TwoOperandCmd.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..5e2be67c7e --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/cmd/TwoOperandCmd.java @@ -0,0 +1,67 @@ +package com.github.wdn.coding2017.jvm.cmd; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.ClassInfo; +import com.github.wdn.coding2017.jvm.constant.ConstantInfo; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.constant.FieldRefInfo; +import com.github.wdn.coding2017.jvm.constant.MethodRefInfo; + +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/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutionResult.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..0637b52f78 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutionResult.java @@ -0,0 +1,57 @@ +package com.github.wdn.coding2017.jvm.engine; + + +import com.github.wdn.coding2017.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutorEngine.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..51feb78e2e --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/ExecutorEngine.java @@ -0,0 +1,35 @@ +package com.github.wdn.coding2017.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.github.wdn.coding2017.jvm.attr.CodeAttr; +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.wdn.coding2017.jvm.constant.MethodRefInfo; +import com.github.wdn.coding2017.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + + + + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + + + + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/Heap.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/Heap.java new file mode 100644 index 0000000000..5fb9effe59 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.github.wdn.coding2017.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/JavaObject.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..43c9e3130e --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/JavaObject.java @@ -0,0 +1,71 @@ +package com.github.wdn.coding2017.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MethodArea.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..7c3a85e80d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MethodArea.java @@ -0,0 +1,68 @@ +package com.github.wdn.coding2017.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.constant.MethodRefInfo; +import com.github.wdn.coding2017.jvm.loader.ClassFileLoader; +import com.github.wdn.coding2017.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + + return null; + } + + + public Method getMethod(MethodRefInfo methodRef){ + + return null; + + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MiniJVM.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..148dfdedb5 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/engine/MiniJVM.java @@ -0,0 +1,29 @@ +package com.github.wdn.coding2017.jvm.engine; +import com.github.wdn.coding2017.jvm.loader.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + + + public static StackFrame create(Method m){ + + StackFrame frame = new StackFrame( m ); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + + } + + + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOprandStack(){ + return this.oprandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + + } + + public Method getMethod(){ + return m; + } + + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/field/Field.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/field/Field.java new file mode 100644 index 0000000000..b4303d823d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/field/Field.java @@ -0,0 +1,72 @@ +package com.github.wdn.coding2017.jvm.field; + +import com.github.wdn.coding2017.jvm.clz.AccessFlag; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; + +/** + * Created by Administrator on 2017/4/10 0010. + */ +public class Field { + private AccessFlag accessFlag; // 例如是public , private 等等 + private int nameIndex; // 指向常量池的入口 + private int descriptorIndex; //指向常量池的入口 + private int attributesCount; // 该字段的属性有多少个 + private ConstantPool pool; + // attribute_info attributes[attributes_count]; //属性信息 + private Field(){ + } + public Field(ConstantPool pool){ + this.pool = pool; + } + public static Field parse(ByteCodeIterator iter){ + Field field = new Field(); + field.setAccessFlags(new AccessFlag(iter.readU2ToInt())); + field.setNameIndex(iter.readU2ToInt()); + field.setDescriptorIndex(iter.readU2ToInt()); + int attCount = iter.readU2ToInt(); + if(attCount>0){ + throw new RuntimeException("字段属性数量大于0"); + } + field.setAttributesCount(attCount); + return field; + } + public String toString(){ + return pool.getConstantInfo(nameIndex).getValue()+pool.getConstantInfo(descriptorIndex).getValue(); + } + public AccessFlag getAccessFlags() { + return accessFlag; + } + + public void setAccessFlags(AccessFlag accessFlags) { + this.accessFlag = accessFlags; + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + public int getAttributesCount() { + return attributesCount; + } + + public void setAttributesCount(int attributesCount) { + this.attributesCount = attributesCount; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ByteCodeIterator.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ByteCodeIterator.java index dc4c1c0b54..7ec5b0802c 100644 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ByteCodeIterator.java +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ByteCodeIterator.java @@ -3,6 +3,7 @@ import com.github.wdn.coding2017.jvm.util.Util; +import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; public class ByteCodeIterator { @@ -31,12 +32,15 @@ public int readU4ToInt(){ public String readU4ToString(){ return Util.byteToHexString(new byte[]{bytes[index++],bytes[index++],bytes[index++],bytes[index++]}); } + public void back(int back){ + index -=back; + } public String readCustomToString(int len){ - byte[] b = new byte[len]; + byte[] tmp = new byte[len]; + for (int i = 0; i < len; i++) { - b[i] = bytes[index++]; + tmp[i] = bytes[index++]; } - return new String(b); - //return Util.byteToHexString(b); + return Util.byteToHexString(tmp); } } diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileParser.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileParser.java index 22d2e5bcd7..0abef3ec29 100644 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileParser.java +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileParser.java @@ -2,6 +2,8 @@ import com.github.wdn.coding2017.jvm.clz.*; import com.github.wdn.coding2017.jvm.constant.*; +import com.github.wdn.coding2017.jvm.field.Field; +import com.github.wdn.coding2017.jvm.method.Method; import java.util.ArrayList; import java.util.List; @@ -22,15 +24,15 @@ public ClassFile parse(byte[] codes) { classFile.setClassIndex(parseClassIndex(iter)); parseInterface(iter); classFile.setFields(parseField(iter)); - classFile.setMethods(parseMethod(iter)); + classFile.setMethods(parseMethod(classFile,iter)); return classFile; } - private List parseMethod(ByteCodeIterator iter) { + private List parseMethod(ClassFile classFile,ByteCodeIterator iter) { int methodCount = iter.readU2ToInt(); List methods = new ArrayList<>(methodCount); for (int i = 0; i < methodCount; i++) { - Method method = Method.parse(pool, iter); + Method method = Method.parse(classFile, iter); method.setPool(pool); methods.add(method); } diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/method/Method.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/method/Method.java new file mode 100644 index 0000000000..a741c83142 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/method/Method.java @@ -0,0 +1,84 @@ +package com.github.wdn.coding2017.jvm.method; + +import com.github.wdn.coding2017.jvm.attr.*; +import com.github.wdn.coding2017.jvm.clz.AccessFlag; +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.cmd.ByteCodeCommand; +import com.github.wdn.coding2017.jvm.constant.ConstantPool; +import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; +import com.github.wdn.coding2017.jvm.util.Util; + +/** + * Created by Administrator on 2017/4/10 0010. + */ +public class Method { + private AccessFlag accessFlags; + private int nameIndex; + private int descriptorIndex; + private CodeAttr codeAttr; + //attributes[attributes_count]; + private ConstantPool pool; + public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { + Method method = new Method(); + method.setAccessFlags(new AccessFlag(iter.readU2ToInt())); + method.setNameIndex(iter.readU2ToInt()); + method.setDescriptorIndex(iter.readU2ToInt()); + int methodAttributesCount = iter.readU2ToInt(); + for (int j = 0; j < methodAttributesCount; j++) { + int methodAttributeNameIndex = iter.readU2ToInt(); + String methodAttributeType = clzFile.getConstantPool().getConstantInfo(methodAttributeNameIndex).getValue(); + methodAttributeType = Util.hexString2String(methodAttributeType); + iter.back(2); + if (methodAttributeType.equals(AttributeInfo.CODE)) { + method.setCodeAttr(CodeAttr.parse(clzFile,iter)); + } else { + throw new RuntimeException("未知的方法属性类型" + methodAttributeType); + } + } + return method; + } + @Override + public String toString(){ + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(pool.getConstantInfo(nameIndex).getValue()); + stringBuffer.append(pool.getConstantInfo(descriptorIndex).getValue()); + stringBuffer.append(codeAttr); + return stringBuffer.toString(); + } + public AccessFlag getAccessFlags() { + return accessFlags; + } + + public void setAccessFlags(AccessFlag accessFlags) { + this.accessFlags = accessFlags; + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr codeAttr) { + this.codeAttr = codeAttr; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/util/Util.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/util/Util.java index 1e54f24a79..69845ef659 100644 --- a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/util/Util.java +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/util/Util.java @@ -16,9 +16,22 @@ public static String byteToHexString(byte[] codes ){ String strHex = Integer.toHexString(value); if(strHex.length()< 2){ strHex = "0" + strHex; - } + } buffer.append(strHex); } return buffer.toString(); } + public static String hexString2String(String src) { + String temp = ""; + for (int i = 0; i < src.length() / 2; i++) { + temp = temp + + (char) Integer.valueOf(src.substring(i * 2, i * 2 + 2), + 16).byteValue(); + } + return temp; + } + + public static void main(String[] args) { + System.out.println(Util.hexString2String("436f6465")); + } } 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/com/coderising/jvm/test/EmployeeV1.class b/group24/75939388/learning2017/resources/classes/com/coderising/jvm/test/EmployeeV1.class new file mode 100644 index 0000000000..c6c3c4a415 Binary files /dev/null and b/group24/75939388/learning2017/resources/classes/com/coderising/jvm/test/EmployeeV1.class differ 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/ArrayList.java deleted file mode 100644 index 8ae862da33..0000000000 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/ArrayList.java +++ /dev/null @@ -1,115 +0,0 @@ -package basic.dataStructure; - -/** - * Created by macvi on 2017/4/2. - */ -public class ArrayList implements List { - private int size = 10; - //每次扩容的长度,默认为10 - private int extendSize = 10; - - private Object[] data = new Object[size]; - - public ArrayList(Object o) { - this.add(o); - } - - public ArrayList(){} - - public void add(Object o) { - if (this.size() == this.size) { - this.size += extendSize; - Object[] newData = new Object[this.size]; - System.arraycopy(this.data, 0, newData, 0, this.data.length); - this.data = newData; - } - - for (int i = 0; i < this.data.length; i++) { - if (data[i] == null) { - data[i] = o; - break; - } else continue; - } - } - - public void add(int index, Object o) { - if (index > this.size() || index < 0) { - throw new IndexOutOfBoundsException(); - } - - if(this.size() == this.size){ - this.size += extendSize; - } - - Object[] newData = new Object[this.size]; - - System.arraycopy(this.data, 0, newData, 0, index); - newData[index] = o; - System.arraycopy(this.data, index, newData, index + 1, this.size() - index); - - this.data = newData; - } - - public Object get(int index) { - if(index > this.size() || index < 0){ - throw new IndexOutOfBoundsException(); - } - for(int i = 0; i < this.size(); i ++){ - if(index == i){ - return this.data[i]; - } - } - - return null; - } - - public Object remove(int index) { - if(index > this.size() || index < 0){ - throw new IndexOutOfBoundsException(); - } - - Object[] newData = new Object[this.size]; - Object removed = this.get(index); - - System.arraycopy(this.data, 0, newData, 0, index); - System.arraycopy(this.data, index + 1, newData, index, this.size() - index); - this.data = newData; - return removed; - } - - public int size() { - int size = 0; - for(Object obj : this.data){ - if(obj != null){ - size += 1; - } - } - - return size; - } - - public boolean contains(Object obj){ - for(int i = 0; i < this.size(); i++){ - if(obj == this.get(i)){ - return true; - } - } - - return false; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - for(Object obj : data){ - if(obj != null){ - sb.append(obj.toString()).append(","); - }else { -// sb.append("null,"); - continue; - } - } - - return sb.toString(); - } -} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java deleted file mode 100644 index 5050ae3c95..0000000000 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/BinaryTreeNode.java +++ /dev/null @@ -1,58 +0,0 @@ -package basic.dataStructure; - -/** - * Created by macvi on 2017/4/4. - */ -public class BinaryTreeNode { - private int data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - private BinaryTreeNode(){} - - public BinaryTreeNode(int data){ - this.data = data; - this.left = null; - this.right = null; - } - - public void setData(int data){ - BinaryTreeNode node = new BinaryTreeNode(data); - if(compareTo(data)){ - if(this.left == null){ - this.left = node; - }else{ - this.left.setData(data); - } - }else{ - if(this.right == null){ - this.right = node; - }else{ - this.right.setData(data); - } - } - } - - public int getData(){ - return data; - } - - private boolean compareTo(int d) { - System.out.println("data=" + this.data + ", d=" + d); - return this.data > d; - } - - private StringBuffer dataStr = new StringBuffer(); - private int index = 0; -// public String toString(BinaryTreeNode node) { -// while (node.left != null || node.right != null){ -// dataStr.append(index + "层,数据=").append(node.data).append("|"); -// if(node.left != null){ -// dataStr.append(node.left.data) -// } -// index ++; -// } -// -// return dataStr.toString(); -// } -} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java deleted file mode 100644 index 3ac85ad37b..0000000000 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/LinkedList.java +++ /dev/null @@ -1,341 +0,0 @@ -package basic.dataStructure; - -/** - * Created by macvi on 2017/4/3. - */ -public class LinkedList implements List { - private Node head; - - public LinkedList() { - this.head = new Node(); - } - - public void add(Object o) { - if (this.head.data == null) { - this.head = new Node(o, null); - } else { - Node temp = this.head; - while (temp.next != null) { - temp = temp.next; - } - temp.next = new Node(o, null); - } - } - - public void add(int index, Object o) { - if (index > this.size() || index < 0) { - throw new IndexOutOfBoundsException(); - } - - if(index == 0){ - Node newNode = new Node(o, this.head); - this.head = newNode; - return; - } - - if(index == this.size()){ - this.add(o); - return; - } - - Node before = getNode(index - 1); - Node next = getNode(index); - Node newNode = new Node(o, next); - before.next = newNode; - - } - - private Node getNode(int index) { - int i = 0; - Node temp = this.head; - while (temp.data != null) { - if (index == i) { - return temp; - } - - if (temp.next != null) { - temp = temp.next; - } else break; - - i++; - } - - return null; - } - - public Object get(int index) { - if (index > this.size() || index < 0) { - throw new IndexOutOfBoundsException(); - } - - return this.getNode(index).data; - } - - public Object remove(int index) { - if(index > this.size() || index < 0){ - throw new IndexOutOfBoundsException(); - } - - Object removed = get(index); - - Node before = getNode(index - 1); - Node next = getNode(index + 1); - before.next = next; - - return removed; - } - - public int size() { - int size = 0; - Node temp = this.head; - while (temp.data != null) { - size++; - if (temp.next != null) { - temp = temp.next; - } else break; - } - - return size; - } - - public void asList(Object[] array){ - LinkedList list = new LinkedList(); - for(int i = 0; i < array.length; i++){ - list.add(array[i]); - } - - this.head = list.head; - } - - public Object[] toArray(LinkedList list){ - int size = list.size(); - Object[] arr = new Object[size]; - for(int i = 0; i < size; i++){ - arr[i] = list.get(i); - } - - return arr; - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - Node temp = this.head; - while (temp.data != null) { - sb.append(temp.data.toString()).append(","); - if (temp.next != null) { - temp = temp.next; - } else break; - } - - return sb.toString(); - } - - private static class Node { - Object data; - Node next; - - public Node() {} - - public Node(Object obj, Node next) { - this.data = obj; - this.next = next; - } - - } - - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - int size = this.size(); - - if(size == 1){ - return; - } - - Object[] data = new Object[size]; - for(int i = 0; i < size; i++){ - data[i] = this.get(i); - } - - this.head = new Node(); - - for(int i = size - 1; i >= 0; i--){ - this.add(data[i]); - } - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - int size = this.size(); - int index = this.size()/2; - ArrayList al = new ArrayList(); - for(int i = index; i < size; i++){ - al.add(this.get(i)); - } - - this.head = new Node(); - - for(int i = 0; i < al.size(); i++){ - this.add(al.get(i)); - } - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * @param i - * @param length - */ - public void remove(int i, int length){ - for(int j = i; j < i + length; j++){ - this.remove(i); - } - } - /** - * 假定当前链表和listB均包含已升序排列的整数 - * 从当前链表中取出那些listB所指定的元素 - * 例如当前链表 = 11->101->201->301->401->501->601->701 - * listB = 1->3->4->6 - * 返回的结果应该是[101,301,401,601] - * @param list - */ - public int[] getElements(LinkedList list){ - int size = list.size(); - int[] arr = new int[size]; - for(int i = 0; i < size; i++){ - int index = (Integer) list.get(i); - arr[i] = (Integer) this.get(index); - } - - return arr; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在listB中出现的元素 - - * @param list - */ - - public void subtract(LinkedList list){ - Object[] arr1 = toArray(this); - Object[] arr2 = toArray(list); - for(int i = 0; i < arr2.length; i++){ - arr1 = ArrayUtil.remove(arr1, arr2[i]); - } - - asList(arr1); - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - int size = this.size(); - ArrayList indexList = new ArrayList(); - ArrayList valueList = new ArrayList(); - for(int i = 0; i < size; i ++){ - int valueI = (Integer)this.get(i); - int index = 0; - for(int j = i + 1; j < size; j++){ - if(valueList.contains(valueI)){ - continue; - } - int valueJ = (Integer) this.get(j); - if(valueJ == valueI){ - index++; - } - - if(index > 0){ - indexList.add(j); - valueList.add(valueJ); - } - } - } - - Object[] arr = new Object[size]; - for(int i = 0; i < size; i++){ - arr[i] = indexList.contains(i) ? false : this.get(i); - } - - ArrayUtil au = new ArrayUtil(); - arr = au.remove(arr, false); - - asList(arr); - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max){ - int size = this.size(); - int[] range = new int[max - min]; - int index = 0; - for(int i = 0; i < size; i++){ - int value = (Integer) this.get(i); - if(value > min && value < max){ - range[index] = value; - index++; - } - } - - Object[] arr = new Object[size]; - for(int i = 0; i < size; i++){ - arr[i] = this.get(i); - } - - for(int i = 0; i < range.length; i++){ - arr = ArrayUtil.remove(arr, range[i]); - } - - asList(arr); - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList intersection( LinkedList list){ - //组合成新的链表 - int listSize = list.size(); - for(int i = 0 ; i < listSize; i ++){ - this.add(list.get(i)); - } - - //转化成数组 - int size = this.size(); - int[] arr = new int[size]; - for(int i = 0; i < size; i++){ - arr[i] = (Integer)this.get(i); - } - //排序 - for(int i = 0; i < size - 1; i ++){ - for(int j = 0; j < size - i - 1; j ++){ - if(arr[j] >= arr[j + 1]){ - int temp = arr[j]; - arr[j] = arr[j + 1]; - arr[j + 1] = temp; - } - } - } - - //组装 - LinkedList li = new LinkedList(); - for(int i = 0; i < size; i ++){ - li.add(arr[i]); - } - return li; - } -} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java deleted file mode 100644 index 36ca7e9647..0000000000 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Queue.java +++ /dev/null @@ -1,72 +0,0 @@ -package basic.dataStructure; - -/** - * Created by macvi on 2017/4/4. - */ -public class Queue { - private Object[] data; - - private int size = 10; - - private int extendedSize = 10; - - public Queue(){ - this.data = new Object[size]; - } - - public Queue(Object o){ - this.data = new Object[size]; - data[0] = o; - } - - public void enQueue(Object o){ - //被添加的位置 - int index = this.size(); - if(this.size() == this.size){ - this.size += extendedSize; - Object[] newData = new Object[this.size]; - System.arraycopy(this.data, 0, newData, 0, index); - newData[index] = o; - this.data = newData; - }else{ - this.data[index] = o; - } - } - - public Object deQueue(){ - Object[] newData = new Object[this.size]; - Object d = this.data[0]; - System.arraycopy(this.data, 1, newData, 0, this.size - 1); - this.data = newData; - - return d; - } - - public Object peek(){ - return this.data[0]; - } - - public boolean isEmpty(){ - return peek() == null; - } - - public int size(){ - int size = 0; - for(Object obj : this.data){ - size += obj == null ? 0 : 1; - } - - return size; - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - for(Object obj : this.data){ - if(obj != null){ - sb.append(obj.toString()).append(","); - }else break; - } - return sb.toString(); - } -} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java deleted file mode 100644 index bea16033fa..0000000000 --- a/group24/75939388/learning2017/src/main/java/basic/dataStructure/Stack.java +++ /dev/null @@ -1,41 +0,0 @@ -package basic.dataStructure; - -/** - * Created by macvi on 2017/4/4. - */ -public class Stack { - - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - this.elementData.add(o); - } - - public Object pop(){ - int index = elementData.size() - 1; - Object obj = elementData.remove(index); - - return obj; - } - - public Object peek(){ - int index = elementData.size() - 1; - return elementData.get(index); - } - public boolean isEmpty(){ - return peek() == null; - } - public int size(){ - return elementData.size(); - } - - @Override - public String toString() { - StringBuffer sb = new StringBuffer(); - for(int i = this.size() - 1; i >= 0; i--){ - sb.append(elementData.get(i).toString()).append(","); - } - - return sb.toString(); - } -} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java new file mode 100644 index 0000000000..246641cb4a --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/array/ArrayList.java @@ -0,0 +1,117 @@ +package basic.dataStructure.array; + +import basic.dataStructure.List; + +/** + * Created by macvi on 2017/4/2. + */ +public class ArrayList implements List { + private int size = 10; + //每次扩容的长度,默认为10 + private int extendSize = 10; + + private Object[] data = new Object[size]; + + public ArrayList(Object o) { + this.add(o); + } + + public ArrayList(){} + + public void add(Object o) { + if (this.size() == this.size) { + this.size += extendSize; + Object[] newData = new Object[this.size]; + System.arraycopy(this.data, 0, newData, 0, this.data.length); + this.data = newData; + } + + for (int i = 0; i < this.data.length; i++) { + if (data[i] == null) { + data[i] = o; + break; + } else continue; + } + } + + public void add(int index, Object o) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + if(this.size() == this.size){ + this.size += extendSize; + } + + Object[] newData = new Object[this.size]; + + System.arraycopy(this.data, 0, newData, 0, index); + newData[index] = o; + System.arraycopy(this.data, index, newData, index + 1, this.size() - index); + + this.data = newData; + } + + public Object get(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + for(int i = 0; i < this.size(); i ++){ + if(index == i){ + return this.data[i]; + } + } + + return null; + } + + public Object remove(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + + Object[] newData = new Object[this.size]; + Object removed = this.get(index); + + System.arraycopy(this.data, 0, newData, 0, index); + System.arraycopy(this.data, index + 1, newData, index, this.size() - index); + this.data = newData; + return removed; + } + + public int size() { + int size = 0; + for(Object obj : this.data){ + if(obj != null){ + size += 1; + } + } + + return size; + } + + public boolean contains(Object obj){ + for(int i = 0; i < this.size(); i++){ + if(obj == this.get(i)){ + return true; + } + } + + return false; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(Object obj : data){ + if(obj != null){ + sb.append(obj.toString()).append(","); + }else { +// sb.append("null,"); + continue; + } + } + + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeNode.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeNode.java new file mode 100644 index 0000000000..b2b96c0349 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeNode.java @@ -0,0 +1,104 @@ +package basic.dataStructure.binaryTree; + +/** + * Created by macvi on 2017/4/4. + */ +public class BinaryTreeNode { +// private T data; +// private BinaryTreeNode left; +// private BinaryTreeNode right; +// private BinaryTreeNode before; +// +// private BinaryTreeNode(){} +// +// public BinaryTreeNode(T data){ +// this.data = data; +// this.left = null; +// this.right = null; +// } +// +// public void setData(int data){ +// BinaryTreeNode node = new BinaryTreeNode(data); +// if(compareTo(data)){ +// if(this.left == null){ +// this.left = node; +// }else{ +// this.left.setData(data); +// } +// }else{ +// if(this.right == null){ +// this.right = node; +// }else{ +// this.right.setData(data); +// } +// } +// } +// +// public BinaryTreeNode getLeft() { +// return left; +// } +// +// public void setLeft(BinaryTreeNode left) { +// this.left = left; +// } +// +// public BinaryTreeNode getRight() { +// return right; +// } +// +// public void setRight(BinaryTreeNode right) { +// this.right = right; +// } +// +// public T getData(){ +// return data; +// } +// +// private boolean compareTo(int d) { +// System.out.println("data=" + this.data + ", d=" + d); +// return (Integer)this.data > d; +// } +// +// private StringBuffer dataStr = new StringBuffer(); +// private int index = 0; +//// public String toString(BinaryTreeNode node) { +//// while (node.left != null || node.right != null){ +//// dataStr.append(index + "层,数据=").append(node.data).append("|"); +//// if(node.left != null){ +//// dataStr.append(node.left.data) +//// } +//// index ++; +//// } +//// +//// return dataStr.toString(); +//// } + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(T data){ + this.data=data; + } + public T getData() { + return data; + } + public void setData(T data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeUtil.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeUtil.java new file mode 100644 index 0000000000..182785b346 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/BinaryTreeUtil.java @@ -0,0 +1,120 @@ +package basic.dataStructure.binaryTree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + preOrder(root, result); + + return result; + } + + private static void preOrder(BinaryTreeNode tree, List result){ + if(tree == null) return; + result.add(tree.getData()); + + preOrder(tree.getLeft(), result); + preOrder(tree.getRight(), result); + } + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + inOrder(root, result); + return result; + } + + private static void inOrder(BinaryTreeNode tree, List result){ + if(tree == null) return; + + inOrder(tree.getLeft(), result); + result.add(tree.getData()); + inOrder(tree.getRight(), result); + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + postOrder(root, result); + return result; + } + + private static void postOrder(BinaryTreeNode tree, List result){ + if(tree == null) return; + + postOrder(tree.getLeft(), result); + postOrder(tree.getRight(), result); + result.add(tree.getData()); + } + + /** + * 用非递归的方式实现对二叉树的前序遍历 + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + List result = new ArrayList(); + Stack buffer = new Stack(); + BinaryTreeNode tmp = root; + while(tmp != null){ + //遍历这一排的左边节点,右边节点入栈缓存 + BinaryTreeNode node = tmp; + while(node != null){ + result.add(node.getData()); + if(node.getRight() != null) buffer.add(node.getRight()); + node = node.getLeft(); + } + + //遍历右边 + //栈中没有节点则表示遍历结束 + if (buffer.isEmpty()) break; + + tmp = buffer.pop(); + } + + return result; + } + /** + * 用非递归的方式实现对二叉树的中序遍历 + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + List result = new ArrayList(); + Stack buffer = new Stack(); + + BinaryTreeNode tmp = root; + while (tmp != null || !buffer.isEmpty()){ + while(tmp != null){ + buffer.push(tmp); + tmp = tmp.getLeft(); + } + + tmp = buffer.pop(); + result.add(tmp.getData()); + tmp = tmp.getRight(); + } + return result; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/FileList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/FileList.java new file mode 100644 index 0000000000..7d7af85490 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/binaryTree/FileList.java @@ -0,0 +1,10 @@ +package basic.dataStructure.binaryTree; + +import java.io.File; + +public class FileList { + public void list(File f) { + } + + +} 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/LinkedList.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LinkedList.java new file mode 100644 index 0000000000..aa19b4cef5 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/linkedList/LinkedList.java @@ -0,0 +1,345 @@ +package basic.dataStructure.linkedList; + +import basic.dataStructure.ArrayUtil; +import basic.dataStructure.List; +import basic.dataStructure.array.ArrayList; + +/** + * Created by macvi on 2017/4/3. + */ +public class LinkedList implements List { + private Node head; + + public LinkedList() { + this.head = new Node(); + } + + public void add(Object o) { + if (this.head.data == null) { + this.head = new Node(o, null); + } else { + Node temp = this.head; + while (temp.next != null) { + temp = temp.next; + } + temp.next = new Node(o, null); + } + } + + public void add(int index, Object o) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + if(index == 0){ + Node newNode = new Node(o, this.head); + this.head = newNode; + return; + } + + if(index == this.size()){ + this.add(o); + return; + } + + Node before = getNode(index - 1); + Node next = getNode(index); + Node newNode = new Node(o, next); + before.next = newNode; + + } + + private Node getNode(int index) { + int i = 0; + Node temp = this.head; + while (temp.data != null) { + if (index == i) { + return temp; + } + + if (temp.next != null) { + temp = temp.next; + } else break; + + i++; + } + + return null; + } + + public Object get(int index) { + if (index > this.size() || index < 0) { + throw new IndexOutOfBoundsException(); + } + + return this.getNode(index).data; + } + + public Object remove(int index) { + if(index > this.size() || index < 0){ + throw new IndexOutOfBoundsException(); + } + + Object removed = get(index); + + Node before = getNode(index - 1); + Node next = getNode(index + 1); + before.next = next; + + return removed; + } + + public int size() { + int size = 0; + Node temp = this.head; + while (temp.data != null) { + size++; + if (temp.next != null) { + temp = temp.next; + } else break; + } + + return size; + } + + public void asList(Object[] array){ + LinkedList list = new LinkedList(); + for(int i = 0; i < array.length; i++){ + list.add(array[i]); + } + + this.head = list.head; + } + + public Object[] toArray(LinkedList list){ + int size = list.size(); + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = list.get(i); + } + + return arr; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + Node temp = this.head; + while (temp.data != null) { + sb.append(temp.data.toString()).append(","); + if (temp.next != null) { + temp = temp.next; + } else break; + } + + return sb.toString(); + } + + private static class Node { + Object data; + Node next; + + public Node() {} + + public Node(Object obj, Node next) { + this.data = obj; + this.next = next; + } + + } + + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + int size = this.size(); + + if(size == 1){ + return; + } + + Object[] data = new Object[size]; + for(int i = 0; i < size; i++){ + data[i] = this.get(i); + } + + this.head = new Node(); + + for(int i = size - 1; i >= 0; i--){ + this.add(data[i]); + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:array = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int size = this.size(); + int index = this.size()/2; + ArrayList al = new ArrayList(); + for(int i = index; i < size; i++){ + al.add(this.get(i)); + } + + this.head = new Node(); + + for(int i = 0; i < al.size(); i++){ + this.add(al.get(i)); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + for(int j = i; j < i + length; j++){ + this.remove(i); + } + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public int[] getElements(LinkedList list){ + int size = list.size(); + int[] arr = new int[size]; + for(int i = 0; i < size; i++){ + int index = (Integer) list.get(i); + arr[i] = (Integer) this.get(index); + } + + return arr; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + Object[] arr1 = toArray(this); + Object[] arr2 = toArray(list); + for(int i = 0; i < arr2.length; i++){ + arr1 = ArrayUtil.remove(arr1, arr2[i]); + } + + asList(arr1); + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + int size = this.size(); + ArrayList indexList = new ArrayList(); + ArrayList valueList = new ArrayList(); + for(int i = 0; i < size; i ++){ + int valueI = (Integer)this.get(i); + int index = 0; + for(int j = i + 1; j < size; j++){ + if(valueList.contains(valueI)){ + continue; + } + int valueJ = (Integer) this.get(j); + if(valueJ == valueI){ + index++; + } + + if(index > 0){ + indexList.add(j); + valueList.add(valueJ); + } + } + } + + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = indexList.contains(i) ? false : this.get(i); + } + + ArrayUtil au = new ArrayUtil(); + arr = au.remove(arr, false); + + asList(arr); + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + int size = this.size(); + int[] range = new int[max - min]; + int index = 0; + for(int i = 0; i < size; i++){ + int value = (Integer) this.get(i); + if(value > min && value < max){ + range[index] = value; + index++; + } + } + + Object[] arr = new Object[size]; + for(int i = 0; i < size; i++){ + arr[i] = this.get(i); + } + + for(int i = 0; i < range.length; i++){ + arr = ArrayUtil.remove(arr, range[i]); + } + + asList(arr); + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + //组合成新的链表 + int listSize = list.size(); + for(int i = 0 ; i < listSize; i ++){ + this.add(list.get(i)); + } + + //转化成数组 + int size = this.size(); + int[] arr = new int[size]; + for(int i = 0; i < size; i++){ + arr[i] = (Integer)this.get(i); + } + //排序 + for(int i = 0; i < size - 1; i ++){ + for(int j = 0; j < size - i - 1; j ++){ + if(arr[j] >= arr[j + 1]){ + int temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } + + //组装 + LinkedList li = new LinkedList(); + for(int i = 0; i < size; i ++){ + li.add(arr[i]); + } + return li; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/CircleQueue.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/CircleQueue.java new file mode 100644 index 0000000000..d053474cf6 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/CircleQueue.java @@ -0,0 +1,82 @@ +package basic.dataStructure.queue; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + + private int capacity; + + //用数组来保存循环队列的元素 + private Object[] elementData; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public CircleQueue(){ + this.capacity = DEFAULT_SIZE; + elementData = new Object[DEFAULT_SIZE]; + } + + public CircleQueue(int capacity){ + this.capacity = capacity; + this.elementData = new Object[this.capacity]; + } + + public boolean isEmpty() { + boolean flag = true; + for(int i = 0; i < this.capacity; i++) { + if(elementData[i] != null){ + flag = false; + } + } + return flag; + } + + public boolean isFull(){ + return this.size() == this.capacity; + } + + public int size() { + int size = 0; + for(Object obj : elementData){ + if(obj == null){ + break; + } + size ++; + } + + return size; + } + + + + public void enQueue(E data) { + if(data == null){ + throw new RuntimeException("cannot put null object"); + } + + if(this.size() < this.capacity){ + elementData[this.rear] = data; + this.rear++; + }else{ + throw new RuntimeException("circle queue full"); + } + } + + public E deQueue() { + E data = (E)elementData[front]; + + Object[] arr = new Object[this.capacity]; + System.arraycopy(elementData, 1, arr, 0, this.size() - 1); + this.elementData = arr; + return data; + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Josephus.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Josephus.java new file mode 100644 index 0000000000..2cf142bd18 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Josephus.java @@ -0,0 +1,40 @@ +package basic.dataStructure.queue; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用Queue来实现Josephus问题 + * 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: + * N个人围成一圈(位置记为0到N-1), 并且从第一个人报数, 报到M的人会被杀死, + * 被杀死的人之后再从1开始报数,直到最后一个人留下来 + * 该方法返回一个List, 包含了被杀死人的次序 + * + * @author liuxin + */ +public class Josephus { + + public static List execute(int n, int m) { + Queue queue = new Queue(); + for(int i = 0; i < n; i++){ + queue.enQueue(i); + } + + int index = 0; + List list = new ArrayList(); + while (queue.isNotEmpty()){ + index ++; + + int num = (Integer)queue.deQueue(); + + if(index % m == 0){ + list.add(num); + }else{ + queue.enQueue(num); + } + } + + return list; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java new file mode 100644 index 0000000000..2654c101b0 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/Queue.java @@ -0,0 +1,76 @@ +package basic.dataStructure.queue; + +/** + * Created by macvi on 2017/4/4. + */ +public class Queue { + private Object[] data; + + private int size = 10; + + private int extendedSize = 10; + + public Queue(){ + this.data = new Object[size]; + } + + public Queue(Object o){ + this.data = new Object[size]; + data[0] = o; + } + + public void enQueue(Object o){ + //被添加的位置 + int index = this.size(); + if(this.size() == this.size){ + this.size += extendedSize; + Object[] newData = new Object[this.size]; + System.arraycopy(this.data, 0, newData, 0, index); + newData[index] = o; + this.data = newData; + }else{ + this.data[index] = o; + } + } + + public Object deQueue(){ + Object[] newData = new Object[this.size]; + Object d = this.data[0]; + System.arraycopy(this.data, 1, newData, 0, this.size - 1); + this.data = newData; + + return d; + } + + public Object peek(){ + return this.data[0]; + } + + public boolean isEmpty(){ + return peek() == null; + } + + public boolean isNotEmpty(){ + return !isEmpty(); + } + + public int size(){ + int size = 0; + for(Object obj : this.data){ + size += obj == null ? 0 : 1; + } + + return size; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(Object obj : this.data){ + if(obj != null){ + sb.append(obj.toString()).append(","); + }else break; + } + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/QueueWithTwoStacks.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..d199707025 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/queue/QueueWithTwoStacks.java @@ -0,0 +1,52 @@ +package basic.dataStructure.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() && stack1.isEmpty(); + } + + public int size() { + return stack1.size() + this.stack2.size(); + } + + + public void enQueue(E item) { + stack1.push(item); + } + + private void move(){ + while (!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + } + + public E deQueue() { + if(stack1.isEmpty()){ + throw new RuntimeException("queue is null"); + } + + if(stack2.isEmpty()){ + move(); + } + + return stack2.pop(); + } +} + diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/QuickMinStack.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/QuickMinStack.java new file mode 100644 index 0000000000..837863d873 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/QuickMinStack.java @@ -0,0 +1,82 @@ +package basic.dataStructure.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + private int defaultSize = 10; + private int extendSize = 10; + Object[] elements = new Object[defaultSize]; + + private int min = -1; + + private int size = 0; + public QuickMinStack(){} + + public boolean isEmpty(){ + boolean flag = false; + for(int i = 0; i < elements.length; i++){ + if(elements[i] != null){ + return false; + } + + flag = elements == null; + } + return flag; + } + + public void push(int data){ + if(isEmpty()){ + this.min = data; + }else{ + this.min = data < min ? data : min; + } + size ++; + elements[size - 1] = data; + if(size >= elements.length){ + extend(); + } + } + public int pop(){ + Integer d = (Integer)elements[size - 1]; + elements[size - 1] = null; + size--; + return d; + } + + public int findMin(){ + return this.min; + } + + public int size(){ + return this.size; + } + + private void extend(){ + int curSize = elements.length; + Object[] arr = new Object[curSize + extendSize]; + + System.arraycopy(elements, 0, arr, 0, curSize); + + this.elements = arr; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("["); + for(int i = size - 1; i >= 0; i--){ + sb.append(elements[i]); + if(i > 0){ + sb.append(","); + }else{ + sb.append("]"); + } + } + + return sb.toString(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java new file mode 100644 index 0000000000..ea83d96e2b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/Stack.java @@ -0,0 +1,55 @@ +package basic.dataStructure.stack; + +import basic.dataStructure.array.ArrayList; + +/** + * Created by macvi on 2017/4/4. + */ +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); + } + + public Object pop(){ + int index = elementData.size() - 1; + Object obj = elementData.remove(index); + + return obj; + } + + public Object peek(){ + int index = elementData.size() - 1; + return index == -1 ? null : elementData.get(index); + } + public boolean isEmpty(){ + return peek() == null; + } + public int size(){ + return elementData.size(); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for(int i = this.size() - 1; i >= 0; i--){ + 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/StackWithTwoQueues.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..6d7b46b930 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/StackWithTwoQueues.java @@ -0,0 +1,50 @@ +package basic.dataStructure.stack; + +import basic.dataStructure.queue.Queue; + +/** + * 用两个队列实现一个栈 + */ +public class StackWithTwoQueues { + + Queue queue1 = null; + Queue queue2 = null; + + private int data = -1; + + public StackWithTwoQueues(){ + queue1 = new Queue(); + queue2 = new Queue(); + } + public void push(int data) { + queue1.enQueue(data); + } + + public int pop() { + move(); + return this.data; + } + + + /** + * queue1是数据保存队列, queue2是缓存队列 + * 每次取之前将queue1的n-1个数据移动至queue2 + * 取出queue的最后一个数据即可 + */ + private void move(){ + if(queue2.isNotEmpty()){ + throw new RuntimeException("queue2 is not empty, operation aborted"); + } + + int size = queue1.size(); + for(int i = 0; i < size - 1; i++){ + queue2.enQueue(queue1.deQueue()); + } + + data = (Integer)queue1.deQueue(); + + for(int i = 0; i < size - 1; i++){ + queue1.enQueue(queue2.deQueue()); + } + } +} diff --git a/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/TwoStackInOneArray.java b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..3123b17760 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/TwoStackInOneArray.java @@ -0,0 +1,156 @@ +package basic.dataStructure.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底, + * 压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * + * @author liuxin + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private int index1 = 0; + private int index2 = 9; + + private int size1 = 0; + private int size2 = 0; + + /** + * 向第一个栈中压入元素 + * + * @param o + */ + public void push1(Object o) { + data[index1] = o; + this.index1++; + this.size1 += 1; + + if (size1 + size2 >= data.length) extend(); + } + + /** + * 从第一个栈中弹出元素 + * + * @return + */ + public Object pop1() { + int index = index1 - 1; + Object obj = data[index]; + //直接置空 + data[index] = null; + this.index1 = index; + this.size1--; + return obj; + } + + /** + * 获取第一个栈的栈顶元素 + * + * @return + */ + + public Object peek1() { + int index = index1 - 1; + Object obj = data[index]; + + return obj; + } + + /* + * 向第二个栈压入元素 + */ + public void push2(Object o) { + data[index2] = o; + index2--; + this.size2 += 1; + + if (size1 + size2 >= data.length) extend(); + } + + /** + * 从第二个栈弹出元素 + * + * @return + */ + public Object pop2() { + int index = index2 + 1; + Object obj = data[index]; + + data[index] = null; + this.index2 = index; + this.size2--; + return obj; + } + + /** + * 获取第二个栈的栈顶元素 + * + * @return + */ + + public Object peek2() { + int index = index2 + 1; + Object obj = data[index]; + return obj; + } + + public int size1() { + return this.size1; + } + + public int size2() { + return this.size2; + } + + /** + * 扩容 + */ + private void extend() { + int size = data.length; + int extendSize = 10; + Object[] extended = new Object[size + extendSize]; + + //stack1 + //因为指针在数据添加后已经加上了,所以要减回去 + for (int i = 0; i <= index1 - 1; i++) { + extended[i] = data[i]; + } + + //stack2 + //因为指针在添加后已经减掉了1,所以要加回去 + for (int i = index2 + 1; i <= size - 1; i++) { + int index = i + extendSize; + extended[index] = data[i]; + } + this.data = extended; + this.index2 += extendSize; + } + + @Override + public String toString() { + + StringBuilder sb = new StringBuilder(); + sb.append("stack1 -> ["); + for (int i = index1 - 1; i >= 0; i--) { + sb.append(data[i]); + if (i == 0) { + sb.append("]"); + } else { + sb.append(","); + } + } + + sb.append("\nstack2 -> ["); + int length = data.length; + for (int i = index2 + 1; i < length; i++) { + sb.append(data[i]); + if (i == length - 1){ + sb.append("]"); + } else { + sb.append(","); + } + } + return sb.toString(); + } +} \ No newline at end of file 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..52b4b7f62b --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/basic/dataStructure/stack/expr/InfixToPostfix.java @@ -0,0 +1,74 @@ +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(); + } + } + } + + //处理运算符: + // 遍历:缓存非空且栈顶是一个运算符且缓存栈顶的运算符的优先级不低于t的优先级,则将栈顶运算符直接入结果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/designPattern/decorator/Beverage.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/Beverage.java new file mode 100644 index 0000000000..e68e2e7b82 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/Beverage.java @@ -0,0 +1,23 @@ +package designPattern.decorator; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public abstract class Beverage { + public static final int TALL = 0; + public static final int GRANDE = 1; + public static final int VENTI = 2; + + + public String description = ""; + public static int size = TALL; + + public String getDescription(){ + return description; + } + + public abstract double cost(); + + public abstract int size(); +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/CondimentDecorator.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/CondimentDecorator.java new file mode 100644 index 0000000000..dca6ade059 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/CondimentDecorator.java @@ -0,0 +1,9 @@ +package designPattern.decorator; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public abstract class CondimentDecorator extends Beverage { + public abstract String getDescription(); +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/DarkRoast.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/DarkRoast.java new file mode 100644 index 0000000000..2c39efecf9 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/DarkRoast.java @@ -0,0 +1,24 @@ +package designPattern.decorator.beverages; + +import designPattern.decorator.Beverage; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class DarkRoast extends Beverage { + + public DarkRoast(){ + description = "Dark Roast"; + } + + @Override + public double cost() { + return 0.99; + } + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Decaf.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Decaf.java new file mode 100644 index 0000000000..bb4f757ad4 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Decaf.java @@ -0,0 +1,24 @@ +package designPattern.decorator.beverages; + +import designPattern.decorator.Beverage; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class Decaf extends Beverage { + + public Decaf(){ + description = "Decaf"; + } + + @Override + public double cost() { + return 1.99; + } + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Espresso.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Espresso.java new file mode 100644 index 0000000000..dca41cc66c --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/Espresso.java @@ -0,0 +1,24 @@ +package designPattern.decorator.beverages; + +import designPattern.decorator.Beverage; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class Espresso extends Beverage { + + public Espresso(){ + description = "Espresso"; + } + + public double cost() { + return 1.99d; + } + + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/HouseBlend.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/HouseBlend.java new file mode 100644 index 0000000000..8b296aa3cf --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/beverages/HouseBlend.java @@ -0,0 +1,23 @@ +package designPattern.decorator.beverages; + +import designPattern.decorator.Beverage; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class HouseBlend extends Beverage { + + public HouseBlend(){ + description = "House Blend"; + } + + public double cost() { + return 0.89; + } + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Mocha.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Mocha.java new file mode 100644 index 0000000000..799399332f --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Mocha.java @@ -0,0 +1,31 @@ +package designPattern.decorator.condiments; + +import designPattern.decorator.Beverage; +import designPattern.decorator.CondimentDecorator; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class Mocha extends CondimentDecorator { + Beverage beverage; + + public Mocha(Beverage beverage){ + this.beverage = beverage; + + this.description += this.beverage.description + ", Mocha"; + } + + public String getDescription() { + return this.description; + } + + public double cost() { + return 0.2 + beverage.cost(); + } + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Soy.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Soy.java new file mode 100644 index 0000000000..ec4873c914 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Soy.java @@ -0,0 +1,31 @@ +package designPattern.decorator.condiments; + +import designPattern.decorator.Beverage; +import designPattern.decorator.CondimentDecorator; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class Soy extends CondimentDecorator { + Beverage beverage; + + public Soy(Beverage beverage){ + this.beverage = beverage; + + this.description += this.beverage.description + ", Soy"; + } + + public String getDescription() { + return this.description; + } + + public double cost() { + return 0.15 + beverage.cost(); + } + + @Override + public int size() { + return 0; + } +} diff --git a/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Whip.java b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Whip.java new file mode 100644 index 0000000000..7b8cce87af --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/designPattern/decorator/condiments/Whip.java @@ -0,0 +1,31 @@ +package designPattern.decorator.condiments; + +import designPattern.decorator.Beverage; +import designPattern.decorator.CondimentDecorator; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class Whip extends CondimentDecorator { + Beverage beverage; + + public Whip(Beverage beverage){ + this.beverage = beverage; + + this.description += beverage.description + ", "; + } + + public String getDescription() { + return this.description; + } + + public double cost() { + return 0.1 + beverage.cost(); + } + + @Override + public int size() { + return 0; + } +} 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..12b79cbeda --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/BiPushCmd.java @@ -0,0 +1,30 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.Heap; +import miniJVM.engine.JavaObject; +import miniJVM.engine.StackFrame; + +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(); + } + + public void execute(StackFrame frame, ExecutionResult result){ + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOperandStack().push(jo); + } + +} 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..cab59f8d67 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/ByteCodeCommand.java @@ -0,0 +1,156 @@ +package miniJVM.cmd; + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantInfo; +import miniJVM.constant.ConstantPool; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.StackFrame; + +import java.util.HashMap; +import java.util.Map; + +public abstract class ByteCodeCommand { + + String opCode; + ClassFile clzFile; + private int offset; + + + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + + private 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, ExecutionResult 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..04febbd9bd --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetFieldCmd.java @@ -0,0 +1,33 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.FieldRefInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.JavaObject; +import miniJVM.engine.StackFrame; + +public class GetFieldCmd extends TwoOperandCmd { + + public GetFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String fieldName = fieldRefInfo.getFieldName(); + JavaObject jo = frame.getOperandStack().pop(); + JavaObject value = jo.getFieldValue(fieldName); + + frame.getOperandStack().push(value); + } + + +} 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..d7d2be35d3 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/GetStaticFieldCmd.java @@ -0,0 +1,39 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.FieldRefInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.Heap; +import miniJVM.engine.JavaObject; +import miniJVM.engine.StackFrame; + +public class GetStaticFieldCmd extends TwoOperandCmd { + + public GetStaticFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRefInfo = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + String className = fieldRefInfo.getClassName(); + String fieldName = fieldRefInfo.getFieldName(); + String fieldType = fieldRefInfo.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOperandStack().push(jo); + }else return; + } +} 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..0d409dd195 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeSpecialCmd.java @@ -0,0 +1,38 @@ +package miniJVM.cmd; + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.MethodRefInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.MethodArea; +import miniJVM.engine.StackFrame; +import miniJVM.method.Method; + +public class InvokeSpecialCmd extends TwoOperandCmd { + + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + if(methodRefInfo.getClassName().equals("java/lang/Object") + && methodRefInfo.getMethodName().equals("")){ + return ; + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + } +} 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..b48dab941f --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/InvokeVirtualCmd.java @@ -0,0 +1,65 @@ +package miniJVM.cmd; + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.MethodRefInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.JavaObject; +import miniJVM.engine.MethodArea; +import miniJVM.engine.StackFrame; +import miniJVM.method.Method; + +public class InvokeVirtualCmd extends TwoOperandCmd { + + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsMethod(pool); + } + + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo)this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + //不需要实现println方法 + if("java/io/PrintStream".equals(className) + && "println".equals(methodName)){ + JavaObject jo = frame.getOperandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------"+value+"----------------"); + + //假的对象,直接弹出无视掉 + frame.getOperandStack().pop(); + return; + } + + //不停的至父类寻找同名方法,即实现多态 + JavaObject jo = frame.getOperandStack().peek(); + MethodArea ma = MethodArea.getInstance(); + Method m = null; + String currentClassName = jo.getClassName(); + while(currentClassName != null){ + ClassFile currentClassFile = ma.findClassFile(currentClassName); + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), methodRefInfo.getParamAndReturnType()); + if(m != null){ + break; + } else{ + currentClassName = currentClassFile.getSuperClassName(); + } + } + if(m == null){ + throw new RuntimeException("no method find :" + methodRefInfo.toString()); + } + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(m); + } + +} 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..062d364e11 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/LdcCmd.java @@ -0,0 +1,43 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantInfo; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.StringInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.Heap; +import miniJVM.engine.StackFrame; + +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; + } + + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantInfo constantInfo = this.getConstantPool().getConstantInfo(this.getOperand()); + + if(constantInfo instanceof StringInfo){ + String value = constantInfo.toString(); + frame.getOperandStack().push(Heap.getInstance().newString(value)); + }else{ + throw new RuntimeException("process string info only"); + } + } +} 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..133b0a70a4 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NewObjectCmd.java @@ -0,0 +1,29 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ClassInfo; +import miniJVM.constant.ConstantPool; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.Heap; +import miniJVM.engine.StackFrame; + +public class NewObjectCmd extends TwoOperandCmd{ + + public NewObjectCmd(ClassFile clzFile, String opCode){ + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsClassInfo(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ClassInfo clazz = (ClassInfo) this.getConstantInfo(this.getIndex()); + String clazzName = clazz.getClassName(); + frame.getOperandStack().push(Heap.getInstance().newObject(clazzName)); + } +} 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..67583bca57 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/NoOperandCmd.java @@ -0,0 +1,139 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.Heap; +import miniJVM.engine.JavaObject; +import miniJVM.engine.StackFrame; + +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; + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + String opCode = this.getOpCode().toUpperCase(); + + if (ByteCodeCommand.aload_0.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.aload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.aload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.iload_1.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.fload_3.equals(opCode)) { + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.voidreturn.equals(opCode)) { + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if (ByteCodeCommand.ireturn.equals(opCode)) { + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOperandStack().pop(); + callerFrame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.freturn.equals(opCode)) { + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOperandStack().pop(); + callerFrame.getOperandStack().push(jo); + } else if (ByteCodeCommand.astore_1.equals(opCode)) { + + JavaObject jo = frame.getOperandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.dup.equals(opCode)) { + + JavaObject jo = frame.getOperandStack().peek(); + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.iconst_0.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.iconst_1.equals(opCode)) { + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOperandStack().push(jo); + + } else if (ByteCodeCommand.istore_1.equals(opCode)) { + + JavaObject jo = frame.getOperandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if (ByteCodeCommand.istore_2.equals(opCode)) { + + JavaObject jo = frame.getOperandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if (ByteCodeCommand.iadd.equals(opCode)) { + + JavaObject jo1 = frame.getOperandStack().pop(); + JavaObject jo2 = frame.getOperandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue() + jo2.getIntValue()); + + frame.getOperandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equals(opCode)) { + + frame.getOperandStack().push(null); + + } else { + throw new RuntimeException("unhandled operation code :" + opCode); + } + } +} 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..8fd272603f --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/OneOperandCmd.java @@ -0,0 +1,26 @@ +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 operand) { + this.operand = operand; + + } + 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..26ebffcab8 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/cmd/PutFieldCmd.java @@ -0,0 +1,37 @@ +package miniJVM.cmd; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.FieldRefInfo; +import miniJVM.constant.NameAndTypeInfo; +import miniJVM.engine.ExecutionResult; +import miniJVM.engine.JavaObject; +import miniJVM.engine.StackFrame; + +public class PutFieldCmd extends TwoOperandCmd { + + public PutFieldCmd(ClassFile clzFile, String opCode) { + super(clzFile,opCode); + } + + @Override + public String toString(ConstantPool pool) { + + return super.getOperandAsField(pool); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo) this.getConstantInfo(this.getIndex()); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) fieldRef.getConstantInfo(fieldRef.getNameAndTypeIndex()); + + String fieldName = nameAndTypeInfo.getName(); + + JavaObject fieldValue = frame.getOperandStack().pop(); + JavaObject objectRef = frame.getOperandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + } +} 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/engine/ExecutionResult.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/ExecutionResult.java new file mode 100644 index 0000000000..8ec03090f0 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/ExecutionResult.java @@ -0,0 +1,52 @@ +package miniJVM.engine; + + +import miniJVM.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/ExecutorEngine.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/ExecutorEngine.java new file mode 100644 index 0000000000..ca188113ed --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/ExecutorEngine.java @@ -0,0 +1,61 @@ +package miniJVM.engine; + + +import miniJVM.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + + public ExecutorEngine() {} + + public void execute(Method mainMethod){ + + StackFrame main = StackFrame.create(mainMethod); + stack.push(main); + + while(!stack.isEmpty()){ + + StackFrame currFrame = stack.peek(); + + ExecutionResult result = currFrame.execute(); + if(result.isPauseAndRunNewFrame()){ + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(currFrame); + setupFunctionCallParams(currFrame, nextFrame); + + stack.push(nextFrame); + }else{ + stack.pop(); + } + } + + } + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + Method nextMethod = nextFrame.getMethod(); + List paramList = nextMethod.getParammeterList(); + + int paramNum = paramList.size() + 1; + + List values = new ArrayList(); + while(paramNum > 0){ + values.add(currentFrame.getOperandStack().pop()); + paramNum--; + } + + List params = new ArrayList(); + for(int i = values.size() - 1; i >= 0; i --){ + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/Heap.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/Heap.java new file mode 100644 index 0000000000..5f981d3bf8 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/Heap.java @@ -0,0 +1,39 @@ +package miniJVM.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/JavaObject.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/JavaObject.java new file mode 100644 index 0000000000..68f2d76779 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/JavaObject.java @@ -0,0 +1,71 @@ +package miniJVM.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue){ + fieldValues.put(fieldName, fieldValue); + } + public JavaObject(int type){ + this.type = type; + } + public void setClassName(String className){ + this.className = className; + } + public void setStringValue(String value){ + stringValue = value; + } + public String getStringValue(){ + return this.stringValue; + } + public void setIntValue(int value) { + this.intValue = value; + } + public int getIntValue(){ + return this.intValue; + } + public int getType(){ + return type; + } + public JavaObject getFieldValue(String fieldName){ + return this.fieldValues.get(fieldName); + } + public String toString(){ + switch(this.getType()){ + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className +":"+ this.fieldValues; + case FLOAT : + return String.valueOf(this.floatValue); + default: + return null; + } + } + public String getClassName(){ + return this.className; + } + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/MethodArea.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/MethodArea.java new file mode 100644 index 0000000000..3cdb055d7f --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/MethodArea.java @@ -0,0 +1,67 @@ +package miniJVM.engine; + + +import miniJVM.clz.ClassFile; +import miniJVM.constant.MethodRefInfo; +import miniJVM.loader.ClassFileLoader; +import miniJVM.method.Method; + +import java.util.HashMap; +import java.util.Map; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea(){ + } + + public static MethodArea getInstance(){ + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader){ + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className){ + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + + public ClassFile findClassFile(String className){ + + if(map.get(className) != null){ + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + + public Method getMethod(String className, String methodName, String paramAndReturnType){ + return this.findClassFile(className).getMethod(methodName, paramAndReturnType); + } + + + public Method getMethod(MethodRefInfo methodRef){ + return this.getMethod(methodRef.getClassName(), methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/MiniJVM.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/MiniJVM.java new file mode 100644 index 0000000000..7d58098cc8 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/MiniJVM.java @@ -0,0 +1,29 @@ +package miniJVM.engine; + + +import miniJVM.loader.ClassFileLoader; + +import java.io.FileNotFoundException; +import java.io.IOException; + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException { + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i operands = new ArrayList(); + + public void push(JavaObject jo){ + operands.add(jo); + } + public JavaObject pop(){ + int index = size()-1; + JavaObject jo = (JavaObject)operands.get(index); + operands.remove(index); + return jo; + + } + public JavaObject top(){ + int index = size()-1; + return (JavaObject)operands.get(index); + } + public int size(){ + return operands.size(); + } +} diff --git a/group24/75939388/learning2017/src/main/java/miniJVM/engine/StackFrame.java b/group24/75939388/learning2017/src/main/java/miniJVM/engine/StackFrame.java new file mode 100644 index 0000000000..12620c62cb --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/engine/StackFrame.java @@ -0,0 +1,107 @@ +package miniJVM.engine; + + +import miniJVM.cmd.ByteCodeCommand; +import miniJVM.method.Method; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack operandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + + public static StackFrame create(Method m){ + StackFrame frame = new StackFrame(m); + + return frame; + } + + + private StackFrame(Method m) { + this.m = m; + } + + public JavaObject getLocalVariableValue(int index){ + return this.localVariableTable.get(index); + } + + public Stack getOperandStack(){ + return this.operandStack; + } + + public int getNextCommandIndex(int offset){ + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for(int i=0;i " + cmds[index].toString()); + cmds[index].execute(this, result); + + if(result.isRunNextCmd()){//执行下一个指令 -> index直接+1 + index++; + }else if(result.isPauseAndRunNewFrame()){//执行新的函数栈帧 -> index+1并返回该栈帧,保存index + index ++; + return result; + }else if(result.isExitCurrentFrame()){//退出当栈帧 -> 直接返回 + return result; + }else if(result.isJump()){//跳到另外的函数栈帧 -> 获取要跳至的index + index = getNextCommandIndex(result.getNextCmdOffset()); + }else index ++; + } + + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + } + + public void setLocalVariableTable(List values){ + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo){ + //问题: 为什么要这么做?? + if(this.localVariableTable.size()-1 < index){ + for(int i=this.localVariableTable.size(); i<=index; i++){ + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + } + + public Method getMethod(){ + return m; + } + + +} 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..ae29300ad9 --- /dev/null +++ b/group24/75939388/learning2017/src/main/java/miniJVM/method/Method.java @@ -0,0 +1,110 @@ +package miniJVM.method; + +import miniJVM.attr.CodeAttr; +import miniJVM.clz.ClassFile; +import miniJVM.cmd.ByteCodeCommand; +import miniJVM.constant.ConstantPool; +import miniJVM.constant.UTF8Info; + +import java.util.ArrayList; +import java.util.List; + +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 ByteCodeCommand[] getCmds() { + ByteCodeCommand[] cmds = this.getCodeAttr().getCmds(); + + return cmds; + } + + private String getParammeterAndReturnType(){ + return ((UTF8Info) this.clzFile.getConstantPool().getConstantInfo(this.descriptorIndex)).getValue(); + } + + public List getParammeterList(){ + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String parammeterTypeString = this.getParammeterAndReturnType(); + + int startPos = parammeterTypeString.indexOf("("); + int endPos = parammeterTypeString.indexOf(")"); + + String paramTypes = parammeterTypeString.substring(startPos + 1, endPos); + + List paramTypeList = new ArrayList(); + + while(!paramTypes.equals("")){ + int pos = 0; + + if(paramTypes.charAt(pos) == 'L'){ + int end = paramTypes.indexOf(";"); + if(end == -1){ + throw new RuntimeException("an object start with L not end with ; found"); + } + + paramTypeList.add(paramTypes.substring(pos, end)); + pos = end; + }else if(paramTypes.charAt(pos) == 'I'){ + paramTypeList.add("I"); + }else if(paramTypes.charAt(pos) == 'F'){ + paramTypeList.add("F"); + }else{ + throw new RuntimeException(paramTypes + " is not supported"); + } + pos++; + paramTypes = paramTypes.substring(pos); + } + + return paramTypeList; + } +} 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" + al.toString()); - } - - - @Test - public void testIndexAdd(){ - ArrayList al = new ArrayList(); - for(int i = 0; i < 17; i ++){ - al.add(i + ""); - } - - al.add(3, "xxoo"); - al.add(11, "abcd"); - al.add(0, "efgh"); - al.add(al.size(), "ijkl"); - - System.out.println("al.toString-->" + al.toString()); - System.out.println("size-->" + al.size()); - } - - @Test - public void testGet(){ - ArrayList al = new ArrayList(); - for(int i = 0; i < 18; i ++){ - al.add(i + "zxcd"); - } - - System.out.println("get-->" + al.get(13)); - } - - @Test - public void testRemove(){ - ArrayList al = new ArrayList(); - for(int i = 0; i < 18; i ++){ - al.add(i + ""); - } - System.out.println("size1-->" + al.size()); - System.out.println("al.toString1-->" + al.toString()); - String re = (String)al.remove(12); - System.out.println("remove index=12 :"); - System.out.println("re-->" + re); - System.out.println("size2-->" + al.size()); - System.out.println("al.toString2-->" + al.toString()); - - String re1 = (String)al.remove(1); - System.out.println("remove index=1 :"); - System.out.println("re-->" + re1); - System.out.println("size2-->" + al.size()); - System.out.println("al.toString2-->" + al.toString()); - } - -} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java b/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java deleted file mode 100644 index 1dc1a6f263..0000000000 --- a/group24/75939388/learning2017/src/test/java/data_structure/ArrayUtilTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package data_structure; - -import org.junit.Test; -import basic.dataStructure.ArrayUtil; - -import java.util.Arrays; - -/** - * @author : 温友朝 - * @date : 2017/4/5 - */ -public class ArrayUtilTest { - ArrayUtil au = new ArrayUtil(); - - @Test - public void testReverse(){ - int[] arr = {1, 2, 3, 4, 5}; - this.au.reverseArray(arr); - } - - @Test - public void testTrim(){ - int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; - int[] arr = this.au.removeZero(oldArr); - System.out.println(Arrays.toString(arr)); - } - - @Test - public void testMerge(){ - int[] a1 = {3, 5, 7,8}; - int[] a2 = {4, 5, 6,7}; - - int[] arr = this.au.merge(a1, a2); - System.out.println(Arrays.toString(arr)); - } - - @Test - public void testGrow(){ - int[] arr = {1, 2, 3, 4, 5}; - int[] arr2 = this.au.grow(arr, 4); - System.out.println(Arrays.toString(arr2)); - } - - @Test - public void testFibonacci(){ - int[] arr = this.au.fibonacci(100); - System.out.println(Arrays.toString(arr)); - } - - @Test - public void testPrimes(){ - int[] arr = this.au.getPrimes(100000); - System.out.println(Arrays.toString(arr)); - } - - @Test - public void testPerfectNumbers(){ - int[] arr = this.au.getPerfectNumbers(10000); - System.out.println(Arrays.toString(arr)); - } - - @Test - public void testJoin(){ - int[] arr = this.au.getPerfectNumbers(10000); - System.out.println(this.au.join(arr, "-")); - } -} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java b/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java deleted file mode 100644 index c98a305623..0000000000 --- a/group24/75939388/learning2017/src/test/java/data_structure/LinkedListTest.java +++ /dev/null @@ -1,151 +0,0 @@ -package data_structure; - -import basic.dataStructure.LinkedList; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; - -/** - * Created by macvi on 2017/4/3. - */ -public class LinkedListTest { - - LinkedList ll = new LinkedList(); - - @Before - public void init(){ - for(int i = 0; i < 10; i++){ - ll.add(i); - } - } - - @After - public void print(){ - - } - - - @Test - public void testLinkedListAdd(){ - LinkedList ll = new LinkedList(); - ll.add("123"); - ll.add("456"); - ll.add("asdf"); - ll.add("zxcv"); - - - System.out.println("ll.toString-->" + ll); - System.out.println("ll.size--->" + ll.size()); - } - - @Test - public void testLinkedListIndexAdd(){ - System.out.println("12345"); - } - - @Test - public void testGet(){ - LinkedList ll = new LinkedList(); - for(int i = 0; i < 10; i ++){ - ll.add(i + ""); - } - - System.out.println("get-->" + ll.get(9)); - System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); - } - - @Test - public void testIndexAdd(){ - LinkedList ll = new LinkedList(); - for(int i = 0; i < 5; i ++){ - ll.add(i + ""); - } - - ll.add(5, "xxoo"); - System.out.println("index get-->" + ll.get(0)); - System.out.println("ll.toString2-->" + ll.toString() + "\nsize-->" + ll.size()); - } - - @Test - public void testRemove(){ - LinkedList ll = new LinkedList(); - for(int i = 0; i < 6; i ++){ - ll.add(i + ""); - } - - Object removed = ll.remove(-1); - System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); - System.out.println("removed-->" + removed.toString()); - } - - @Test - public void testReverse(){ - ll.reverse(); - System.out.println("ll.reverse-->" + ll.toString()); - } - - @Test - public void testRemoveFirstHalf(){ - ll.removeFirstHalf(); - System.out.println("ll.removeFirstHalf-->" + ll.toString()); - } - - @Test - public void testRemoveL(){ - ll.remove(2, 5); - System.out.println("ll.toString-->" + ll.toString()); - } - - @Test - public void testGetElements(){ - LinkedList l2 = new LinkedList(); - l2.add(3); - l2.add(5); - l2.add(9); - l2.add(0); - - int[] arr = ll.getElements(l2); - System.out.println("arr->" + Arrays.toString(arr)); - } - - @Test - public void testRemoveDuplicate(){ - ll.add(1); - ll.add(3); - ll.add(4); - ll.add(10); - ll.add(11); - ll.removeDuplicateValues(); - System.out.println("ll.toString-->" + ll.toString()); - } - - @Test - public void testRemoveRange(){ - ll.removeRange(2, 6); - System.out.println("ll.toString-->" + ll.toString()); - } - - @Test - public void testSubtract(){ - LinkedList list = new LinkedList(); - list.add(1); - list.add(2); - list.add(5); - - ll.subtract(list); - System.out.println("ll.toString-->" + ll); - } - - @Test - public void testIntersection(){ - LinkedList list = new LinkedList(); - list.add(1); - list.add(2); - list.add(5); - - LinkedList list2 = ll.intersection(list); - System.out.println(list2); - } -} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java b/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java deleted file mode 100644 index 3db6d82e49..0000000000 --- a/group24/75939388/learning2017/src/test/java/data_structure/QueueTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package data_structure; - -import org.junit.Assert; -import org.junit.Test; -import basic.dataStructure.Queue; - -/** - * Created by macvi on 2017/4/4. - */ -public class QueueTest { - - private Queue newQueue(){ - Queue q = new Queue(); - for(int i = 0; i < 13; i++){ - q.enQueue(i + ""); - } - - return q; - } - - @Test - public void testEnqueue(){ - Queue q = newQueue(); - q.enQueue(10 + ""); - q.enQueue( "xxoo"); - System.out.println("queue-->" + q.toString()); - } - - @Test - public void testSize(){ - Queue q = newQueue(); - - Assert.assertEquals(13, q.size()); - } - - @Test - public void testDequeue(){ - Queue q = newQueue(); - Object obj = q.deQueue(); - - Assert.assertEquals("0", obj); - } - - @Test - public void testIsEmpty(){ - Queue q = newQueue(); - - Assert.assertEquals(false, q.isEmpty()); - } -} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java b/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java deleted file mode 100644 index b933b8b63e..0000000000 --- a/group24/75939388/learning2017/src/test/java/data_structure/StackTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package data_structure; - -import org.junit.Assert; -import org.junit.Test; -import basic.dataStructure.Stack; - -/** - * Created by macvi on 2017/4/4. - */ -public class StackTest { - - private Stack getStack(){ - Stack s = new Stack(); - for(int i = 0; i < 14; i ++){ - s.push(i + ""); - } - - return s; - } - - @Test - public void pushTest(){ - Stack s = getStack(); - - System.out.println("stack-->" + s.toString()); - } - - @Test - public void testSize(){ - Stack s = getStack(); - - Assert.assertEquals(14, s.size()); - } - - @Test - public void testPeek(){ - Stack s = getStack(); - - 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/array/ArrayUtilTest.java b/group24/75939388/learning2017/src/test/java/data_structure/array/ArrayUtilTest.java new file mode 100644 index 0000000000..335f5f99bd --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/array/ArrayUtilTest.java @@ -0,0 +1,67 @@ +package data_structure.array; + +import org.junit.Test; +import basic.dataStructure.ArrayUtil; + +import java.util.Arrays; + +/** + * @author : 温友朝 + * @date : 2017/4/5 + */ +public class ArrayUtilTest { + ArrayUtil au = new ArrayUtil(); + + @Test + public void testReverse(){ + int[] arr = {1, 2, 3, 4, 5}; + this.au.reverseArray(arr); + } + + @Test + public void testTrim(){ + int oldArr[]={1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; + int[] arr = this.au.removeZero(oldArr); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testMerge(){ + int[] a1 = {3, 5, 7,8}; + int[] a2 = {4, 5, 6,7}; + + int[] arr = this.au.merge(a1, a2); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testGrow(){ + int[] arr = {1, 2, 3, 4, 5}; + int[] arr2 = this.au.grow(arr, 4); + System.out.println(Arrays.toString(arr2)); + } + + @Test + public void testFibonacci(){ + int[] arr = this.au.fibonacci(100); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testPrimes(){ + int[] arr = this.au.getPrimes(100000); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testPerfectNumbers(){ + int[] arr = this.au.getPerfectNumbers(10000); + System.out.println(Arrays.toString(arr)); + } + + @Test + public void testJoin(){ + int[] arr = this.au.getPerfectNumbers(10000); + System.out.println(this.au.join(arr, "-")); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/binaryTree/BinaryTreeUtilTest.java b/group24/75939388/learning2017/src/test/java/data_structure/binaryTree/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..09b50a1148 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/binaryTree/BinaryTreeUtilTest.java @@ -0,0 +1,77 @@ +package data_structure.binaryTree; + +import basic.dataStructure.binaryTree.BinaryTreeNode; +import basic.dataStructure.binaryTree.BinaryTreeUtil; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + + + +public class BinaryTreeUtilTest { + + BinaryTreeNode root = null; + @Before + public void setUp() throws Exception { + root = new BinaryTreeNode(1); + root.setLeft(new BinaryTreeNode(2)); + root.setRight(new BinaryTreeNode(5)); + root.getLeft().setLeft(new BinaryTreeNode(3)); + root.getLeft().setRight(new BinaryTreeNode(4)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + + + } + @Test + public void testInOrderVisit() { + + + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[3, 2, 4, 1, 5]", result.toString()); + + } + + @Test + public void testPostOrderVisit() { + + + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[3, 4, 2, 5, 1]", result.toString()); + + } + + + @Test + public void testInOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[3, 2, 6, 4, 7, 1, 5]", result.toString()); + + } + @Test + public void testPreOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 6, 7, 5]", result.toString()); + + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/list/ArrayListTest.java b/group24/75939388/learning2017/src/test/java/data_structure/list/ArrayListTest.java new file mode 100644 index 0000000000..5ef855408f --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/list/ArrayListTest.java @@ -0,0 +1,69 @@ +package data_structure.list; + +import org.junit.Test; +import basic.dataStructure.array.ArrayList; + +/** + * Created by macvi on 2017/4/2. + */ +public class ArrayListTest { + + @Test + public void TestAdd(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 32; i++){ + al.add(i + ""); + } + + System.out.println("ArrayList.content-->" + al.toString()); + } + + + @Test + public void testIndexAdd(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 17; i ++){ + al.add(i + ""); + } + + al.add(3, "xxoo"); + al.add(11, "abcd"); + al.add(0, "efgh"); + al.add(al.size(), "ijkl"); + + System.out.println("al.toString-->" + al.toString()); + System.out.println("size-->" + al.size()); + } + + @Test + public void testGet(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 18; i ++){ + al.add(i + "zxcd"); + } + + System.out.println("get-->" + al.get(13)); + } + + @Test + public void testRemove(){ + ArrayList al = new ArrayList(); + for(int i = 0; i < 18; i ++){ + al.add(i + ""); + } + System.out.println("size1-->" + al.size()); + System.out.println("al.toString1-->" + al.toString()); + String re = (String)al.remove(12); + System.out.println("remove index=12 :"); + System.out.println("re-->" + re); + System.out.println("size2-->" + al.size()); + System.out.println("al.toString2-->" + al.toString()); + + String re1 = (String)al.remove(1); + System.out.println("remove index=1 :"); + System.out.println("re-->" + re1); + System.out.println("size2-->" + al.size()); + System.out.println("al.toString2-->" + al.toString()); + } + +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java b/group24/75939388/learning2017/src/test/java/data_structure/list/BinaryNodeTreeTest.java similarity index 85% rename from group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java rename to group24/75939388/learning2017/src/test/java/data_structure/list/BinaryNodeTreeTest.java index df976147e3..0d14cdbd8c 100644 --- a/group24/75939388/learning2017/src/test/java/data_structure/BinaryNodeTreeTest.java +++ b/group24/75939388/learning2017/src/test/java/data_structure/list/BinaryNodeTreeTest.java @@ -1,7 +1,7 @@ -package data_structure; +package data_structure.list; import org.junit.Test; -import basic.dataStructure.BinaryTreeNode; +import basic.dataStructure.binaryTree.BinaryTreeNode; /** * @author : 温友朝 diff --git a/group24/75939388/learning2017/src/test/java/data_structure/list/LRUPageFrameTest.java b/group24/75939388/learning2017/src/test/java/data_structure/list/LRUPageFrameTest.java new file mode 100644 index 0000000000..9612c97a16 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/list/LRUPageFrameTest.java @@ -0,0 +1,65 @@ +package data_structure.list; + +import basic.dataStructure.linkedList.LRUPageFrame; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author : 温友朝 + * @date : 2017/4/19 + */ +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + + @Test + public void testSet(){ + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + frame.moveToFirst(1); + System.out.println(frame.toString()); + } + + @Test + public void testGet(){ + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + System.out.println(frame.get(0)); + } + + @Test + public void testRemoveFirst(){ + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + frame.removeLast(); + System.out.println(frame.toString()); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/list/LinkedListTest.java b/group24/75939388/learning2017/src/test/java/data_structure/list/LinkedListTest.java new file mode 100644 index 0000000000..97ef76c2eb --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/list/LinkedListTest.java @@ -0,0 +1,151 @@ +package data_structure.list; + +import basic.dataStructure.linkedList.LinkedList; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +/** + * Created by macvi on 2017/4/3. + */ +public class LinkedListTest { + + LinkedList ll = new LinkedList(); + + @Before + public void init(){ + for(int i = 0; i < 10; i++){ + ll.add(i); + } + } + + @After + public void print(){ + + } + + + @Test + public void testLinkedListAdd(){ + LinkedList ll = new LinkedList(); + ll.add("123"); + ll.add("456"); + ll.add("asdf"); + ll.add("zxcv"); + + + System.out.println("ll.toString-->" + ll); + System.out.println("ll.size--->" + ll.size()); + } + + @Test + public void testLinkedListIndexAdd(){ + System.out.println("12345"); + } + + @Test + public void testGet(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 10; i ++){ + ll.add(i + ""); + } + + System.out.println("get-->" + ll.get(9)); + System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); + } + + @Test + public void testIndexAdd(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 5; i ++){ + ll.add(i + ""); + } + + ll.add(5, "xxoo"); + System.out.println("index get-->" + ll.get(0)); + System.out.println("ll.toString2-->" + ll.toString() + "\nsize-->" + ll.size()); + } + + @Test + public void testRemove(){ + LinkedList ll = new LinkedList(); + for(int i = 0; i < 6; i ++){ + ll.add(i + ""); + } + + Object removed = ll.remove(-1); + System.out.println("ll.toString-->" + ll.toString() + "\nsize-->" + ll.size()); + System.out.println("removed-->" + removed.toString()); + } + + @Test + public void testReverse(){ + ll.reverse(); + System.out.println("ll.reverse-->" + ll.toString()); + } + + @Test + public void testRemoveFirstHalf(){ + ll.removeFirstHalf(); + System.out.println("ll.removeFirstHalf-->" + ll.toString()); + } + + @Test + public void testRemoveL(){ + ll.remove(2, 5); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testGetElements(){ + LinkedList l2 = new LinkedList(); + l2.add(3); + l2.add(5); + l2.add(9); + l2.add(0); + + int[] arr = ll.getElements(l2); + System.out.println("arr->" + Arrays.toString(arr)); + } + + @Test + public void testRemoveDuplicate(){ + ll.add(1); + ll.add(3); + ll.add(4); + ll.add(10); + ll.add(11); + ll.removeDuplicateValues(); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testRemoveRange(){ + ll.removeRange(2, 6); + System.out.println("ll.toString-->" + ll.toString()); + } + + @Test + public void testSubtract(){ + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(5); + + ll.subtract(list); + System.out.println("ll.toString-->" + ll); + } + + @Test + public void testIntersection(){ + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(5); + + LinkedList list2 = ll.intersection(list); + System.out.println(list2); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/queue/CircleQueueTest.java b/group24/75939388/learning2017/src/test/java/data_structure/queue/CircleQueueTest.java new file mode 100644 index 0000000000..9e7f7292b7 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/queue/CircleQueueTest.java @@ -0,0 +1,45 @@ +package data_structure.queue; + +import basic.dataStructure.queue.CircleQueue; +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"); + 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.assertEquals("d", queue.deQueue()); + Assert.assertEquals("e", queue.deQueue()); + + } + +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/queue/JosephusTest.java b/group24/75939388/learning2017/src/test/java/data_structure/queue/JosephusTest.java new file mode 100644 index 0000000000..645428764e --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/queue/JosephusTest.java @@ -0,0 +1,28 @@ +package data_structure.queue; + +import basic.dataStructure.queue.Josephus; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/queue/QueueTest.java b/group24/75939388/learning2017/src/test/java/data_structure/queue/QueueTest.java new file mode 100644 index 0000000000..682aa8dfe9 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/queue/QueueTest.java @@ -0,0 +1,50 @@ +package data_structure.queue; + +import org.junit.Assert; +import org.junit.Test; +import basic.dataStructure.queue.Queue; + +/** + * Created by macvi on 2017/4/4. + */ +public class QueueTest { + + private Queue newQueue(){ + Queue q = new Queue(); + for(int i = 0; i < 13; i++){ + q.enQueue(i + ""); + } + + return q; + } + + @Test + public void testEnqueue(){ + Queue q = newQueue(); + q.enQueue(10 + ""); + q.enQueue("xxoo"); + System.out.println("queue-->" + q.toString()); + } + + @Test + public void testSize(){ + Queue q = newQueue(); + + Assert.assertEquals(13, q.size()); + } + + @Test + public void testDequeue(){ + Queue q = newQueue(); + Object obj = q.deQueue(); + + Assert.assertEquals("0", obj); + } + + @Test + public void testIsEmpty(){ + Queue q = newQueue(); + + Assert.assertEquals(false, q.isEmpty()); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/queue/TwoStacksQueueTest.java b/group24/75939388/learning2017/src/test/java/data_structure/queue/TwoStacksQueueTest.java new file mode 100644 index 0000000000..666620dbe1 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/queue/TwoStacksQueueTest.java @@ -0,0 +1,35 @@ +package data_structure.queue; + +import basic.dataStructure.queue.QueueWithTwoStacks; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * @author : 温友朝 + * @date : 2017/5/2 + */ +public class TwoStacksQueueTest { + + private QueueWithTwoStacks queue; + + @Before + public void init(){ + queue = new QueueWithTwoStacks(); + } + + @After + public void after(){ + + } + + @Test + public void testQueue(){ + queue.enQueue(10 + ""); + queue.enQueue( "xxoo"); + queue.enQueue( "ppxxoo"); + Assert.assertEquals(3, queue.size()); + Assert.assertEquals("10", queue.deQueue()); + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/stack/ExprTest.java b/group24/75939388/learning2017/src/test/java/data_structure/stack/ExprTest.java new file mode 100644 index 0000000000..fda0748923 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/stack/ExprTest.java @@ -0,0 +1,106 @@ +package data_structure.stack; + +import basic.dataStructure.stack.expr.InfixExpr; +import basic.dataStructure.stack.expr.InfixToPostfix; +import basic.dataStructure.stack.expr.PostfixExpr; +import basic.dataStructure.stack.expr.PrefixExpr; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author : 温友朝 + * @date : 2017/4/27 + */ +public class ExprTest { + + + @Test + public void testInfixEvaluate() { + //InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); + +// { +// InfixExpr expr = new InfixExpr("2+3*4+5"); +// Assert.assertEquals(19.0, expr.evaluate(), 0.001f); +// } + { + InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); + Assert.assertEquals(100.0, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("3*20/2"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("20/2*3"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + + { + InfixExpr expr = new InfixExpr("10-30+50"); + Assert.assertEquals(30, expr.evaluate(), 0.001f); + } + { + InfixExpr expr = new InfixExpr("10-2*3+50"); + Assert.assertEquals(54, expr.evaluate(), 0.001f); + } + } + + + @Test + public void testPostfixEvaluate() { + { + 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); + } + } + + @Test + public void testPrefixEvaluate() { + { + // 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); + } + } + + @Test + public void textInfixToPostfixExpr(){ + { + //9+(3-1)*3+10/2 = 9 3 1 - 3 * 10 2 / + + + String expr = "9+(3-1)*3+10/2"; + Assert.assertEquals("[9, 3, 1, -, 3, *, 10, 2, /, +, +]", InfixToPostfix.convert(expr).toString()); + } + { + //10-2*3+50 = 10 2 3 * 50 + - + String expr = "10-2*3+50"; + Assert.assertEquals("[10, 2, 3, *, 50, +, -]", InfixToPostfix.convert(expr).toString()); + } + } +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/stack/StackTest.java b/group24/75939388/learning2017/src/test/java/data_structure/stack/StackTest.java new file mode 100644 index 0000000000..78503eff4b --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/stack/StackTest.java @@ -0,0 +1,98 @@ +package data_structure.stack; + +import basic.dataStructure.stack.*; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by macvi on 2017/4/4. + */ +public class StackTest { + + private Stack s; + + @Before + public void init(){ + s = new Stack(); + for(int i = 0; i < 5; i ++){ + s.push(i + ""); + } + } + + @Test + 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 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})")); + + } + + /** + * QuickMinStack + * + * StackWithTwoQueues + * + * TwoStackInOneArray + */ + @Test + public void test3(){ + //QuickMinStack + { + QuickMinStack qms = new QuickMinStack(); + qms.push(0); + qms.push(-2); + qms.push(10); + for(int i = 0; i < 14; i++){ + qms.push(i); + } + Assert.assertEquals(-2, qms.findMin()); + Assert.assertEquals(17, qms.size()); + Assert.assertEquals(13, qms.pop()); + System.out.println(qms.toString()); + } + //StackWithTwoQueues + { + StackWithTwoQueues stack = new StackWithTwoQueues(); + stack.push(0); + stack.push(2); + stack.push(5); + stack.push(10); + Assert.assertEquals(10, stack.pop()); + } + //TwoStackInOneArray + { + TwoStackInOneArray stack = new TwoStackInOneArray(); + for(int i = 0; i < 7; i++){ + stack.push1(i); + } + + for(int i = 0; i < 8; i++){ + stack.push2(i); + } + System.out.println("size1 ->" + stack.size1()); + System.out.println("size2 ->" + stack.size2()); + System.out.println(stack.toString()); + + Assert.assertEquals(stack.peek1(), 6); + Assert.assertEquals(stack.peek2(), 7); + + Assert.assertEquals(stack.pop1(), 6); + Assert.assertEquals(stack.size1(), 6); + + Assert.assertEquals(stack.pop2(), 7); + Assert.assertEquals(stack.size2(), 7); + } + } + +} diff --git a/group24/75939388/learning2017/src/test/java/data_structure/stack/TokenParserTest.java b/group24/75939388/learning2017/src/test/java/data_structure/stack/TokenParserTest.java new file mode 100644 index 0000000000..3aa2c01abb --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/data_structure/stack/TokenParserTest.java @@ -0,0 +1,42 @@ +package data_structure.stack; + + +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/designPattern/StarBuzzCoffeeTest.java b/group24/75939388/learning2017/src/test/java/designPattern/StarBuzzCoffeeTest.java new file mode 100644 index 0000000000..8f04ce4ff1 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/designPattern/StarBuzzCoffeeTest.java @@ -0,0 +1,35 @@ +package designPattern; + +import designPattern.decorator.Beverage; +import designPattern.decorator.beverages.DarkRoast; +import designPattern.decorator.beverages.Espresso; +import designPattern.decorator.beverages.HouseBlend; +import designPattern.decorator.condiments.Mocha; +import designPattern.decorator.condiments.Soy; +import designPattern.decorator.condiments.Whip; +import org.junit.Test; + +/** + * @author : 温友朝 + * @date : 2017/5/5 + */ +public class StarBuzzCoffeeTest { + + @Test + public void test1(){ + Beverage espresso = new Espresso(); + System.out.println(espresso.getDescription() + " cost $" + espresso.cost()); + + Beverage darkRoast = new DarkRoast(); + darkRoast = new Mocha(darkRoast); + darkRoast = new Mocha(darkRoast); + darkRoast = new Whip(darkRoast); + System.out.println(darkRoast.getDescription() + " cost $" + darkRoast.cost()); + + Beverage houseBlend = new HouseBlend(); + houseBlend = new Soy(houseBlend); + houseBlend = new Mocha(houseBlend); + houseBlend = new Whip(houseBlend); + System.out.println(houseBlend.getDescription() + " cost $" + houseBlend.cost()); + } +} 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..2db9faa051 --- /dev/null +++ b/group24/75939388/learning2017/src/test/java/miniJVM/miniJVMTest.java @@ -0,0 +1,23 @@ +package miniJVM; + +import miniJVM.engine.MiniJVM; +import org.junit.Assert; +import org.junit.Test; +import thread.download.ClassFileReader; + +public class miniJVMTest { + + static final String PATH = "resources/classes"; + + @Test + public void readCafebabe(){ + Assert.assertEquals("cafebabe", ClassFileReader.readNextU4Bytes(0)); + } + + @Test + public void testMain() throws Exception{ + String[] classPaths = {PATH}; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "miniJVM.EmployeeV1"); + } +} diff --git a/group24/Homework/10-TenthWeek/tree/BinaryTreeNode.java b/group24/Homework/10-TenthWeek/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..467101a16f --- /dev/null +++ b/group24/Homework/10-TenthWeek/tree/BinaryTreeNode.java @@ -0,0 +1,35 @@ +package com.coding.basic.tree; + +public class BinaryTreeNode { + + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(T data){ + this.data=data; + } + public T getData() { + return data; + } + public void setData(T data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/group24/Homework/10-TenthWeek/tree/BinaryTreeUtil.java b/group24/Homework/10-TenthWeek/tree/BinaryTreeUtil.java new file mode 100644 index 0000000000..b033cbe1d5 --- /dev/null +++ b/group24/Homework/10-TenthWeek/tree/BinaryTreeUtil.java @@ -0,0 +1,66 @@ +package com.coding.basic.tree; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class BinaryTreeUtil { + /** + * 用递归的方式实现对二叉树的前序遍历, 需要通过BinaryTreeUtilTest测试 + * + * @param root + * @return + */ + public static List preOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + return result; + } + + /** + * 用递归的方式实现对二叉树的中遍历 + * + * @param root + * @return + */ + public static List inOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + return result; + } + + /** + * 用递归的方式实现对二叉树的后遍历 + * + * @param root + * @return + */ + public static List postOrderVisit(BinaryTreeNode root) { + List result = new ArrayList(); + + return result; + } + /** + * 用非递归的方式实现对二叉树的前序遍历 + * @param root + * @return + */ + public static List preOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + + return result; + } + /** + * 用非递归的方式实现对二叉树的中序遍历 + * @param root + * @return + */ + public static List inOrderWithoutRecursion(BinaryTreeNode root) { + + List result = new ArrayList(); + + return result; + } + +} diff --git a/group24/Homework/10-TenthWeek/tree/BinaryTreeUtilTest.java b/group24/Homework/10-TenthWeek/tree/BinaryTreeUtilTest.java new file mode 100644 index 0000000000..41857e137d --- /dev/null +++ b/group24/Homework/10-TenthWeek/tree/BinaryTreeUtilTest.java @@ -0,0 +1,75 @@ +package com.coding.basic.tree; + +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class BinaryTreeUtilTest { + + BinaryTreeNode root = null; + @Before + public void setUp() throws Exception { + root = new BinaryTreeNode(1); + root.setLeft(new BinaryTreeNode(2)); + root.setRight(new BinaryTreeNode(5)); + root.getLeft().setLeft(new BinaryTreeNode(3)); + root.getLeft().setRight(new BinaryTreeNode(4)); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPreOrderVisit() { + + List result = BinaryTreeUtil.preOrderVisit(root); + Assert.assertEquals("[1, 2, 3, 4, 5]", result.toString()); + + + } + @Test + public void testInOrderVisit() { + + + List result = BinaryTreeUtil.inOrderVisit(root); + Assert.assertEquals("[3, 2, 4, 1, 5]", result.toString()); + + } + + @Test + public void testPostOrderVisit() { + + + List result = BinaryTreeUtil.postOrderVisit(root); + Assert.assertEquals("[3, 4, 2, 5, 1]", result.toString()); + + } + + + @Test + public void testInOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.inOrderWithoutRecursion(root); + Assert.assertEquals("[3, 2, 6, 4, 7, 1, 5]", result.toString()); + + } + @Test + public void testPreOrderVisitWithoutRecursion() { + BinaryTreeNode node = root.getLeft().getRight(); + node.setLeft(new BinaryTreeNode(6)); + node.setRight(new BinaryTreeNode(7)); + + List result = BinaryTreeUtil.preOrderWithoutRecursion(root); + Assert.assertEquals("[1, 2, 3, 4, 6, 7, 5]", result.toString()); + + } +} diff --git a/group24/Homework/10-TenthWeek/tree/FileList.java b/group24/Homework/10-TenthWeek/tree/FileList.java new file mode 100644 index 0000000000..6e65192e4a --- /dev/null +++ b/group24/Homework/10-TenthWeek/tree/FileList.java @@ -0,0 +1,10 @@ +package com.coding.basic.tree; + +import java.io.File; + +public class FileList { + public void list(File f) { + } + + +} diff --git a/group24/Homework/9-NinthWeek/QuickMinStack.java b/group24/Homework/9-NinthWeek/QuickMinStack.java new file mode 100644 index 0000000000..f391d92b8f --- /dev/null +++ b/group24/Homework/9-NinthWeek/QuickMinStack.java @@ -0,0 +1,19 @@ +package com.coding.basic.stack; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + public void push(int data){ + + } + public int pop(){ + return -1; + } + public int findMin(){ + return -1; + } +} diff --git a/group24/Homework/9-NinthWeek/StackWithTwoQueues.java b/group24/Homework/9-NinthWeek/StackWithTwoQueues.java new file mode 100644 index 0000000000..d0ab4387d2 --- /dev/null +++ b/group24/Homework/9-NinthWeek/StackWithTwoQueues.java @@ -0,0 +1,16 @@ +package com.coding.basic.stack; + + +public class StackWithTwoQueues { + + + public void push(int data) { + + } + + public int pop() { + return -1; + } + + +} diff --git a/group24/Homework/9-NinthWeek/TwoStackInOneArray.java b/group24/Homework/9-NinthWeek/TwoStackInOneArray.java new file mode 100644 index 0000000000..e86d056a24 --- /dev/null +++ b/group24/Homework/9-NinthWeek/TwoStackInOneArray.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return null; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + return null; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return null; + } + +} diff --git a/group27/1252327158/task3_20170326/download/com/coderising/download/FileDownloaderTest.java b/group27/1252327158/task3_20170326/download/com/coderising/download/FileDownloaderTest.java index 865d65510d..8d9b15f690 100644 --- a/group27/1252327158/task3_20170326/download/com/coderising/download/FileDownloaderTest.java +++ b/group27/1252327158/task3_20170326/download/com/coderising/download/FileDownloaderTest.java @@ -21,7 +21,7 @@ public void tearDown() throws Exception { @Test public void testDownload() { - String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489721424&di=1fda6467501ab1d5e5bff43e801d14ee&imgtype=jpg&er=1&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201507%2F30%2F20150730163204_A24MX.thumb.700_0.jpeg"; + String url = "http://read.pudn.com/downloads161/ebook/730477/driver%20book/Windows文件系统过滤驱动开发教程(第二版).pdf"; FileDownloader downloader = new FileDownloader(url); diff --git a/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrame.java b/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..5068578571 --- /dev/null +++ b/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,131 @@ +package com.coding.basic.linklist; + + +public class LRUPageFrame { + + private static class Node { + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + public LRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + Node node = find(pageNum); + //在该队列中存在, 则提到队列头 + if (node != null) { + moveExistingNodeToHead(node); + } else{ + node = new Node(); + node.pageNum = pageNum; + + // 缓存容器是否已经超过大小. + if (currentSize >= capacity) { + removeLast(); + } + addNewNodetoHead(node); + } + } + + private void addNewNodetoHead(Node node) { + if(isEmpty()) { + node.prev = null; + node.next = null; + first = node; + last = node; + } else { + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + this.currentSize ++; + } + + private Node find(int data){ + Node node = first; + while(node != null){ + if(node.pageNum == data){ + return node; + } + node = node.next; + } + return null; + } + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize --; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + * + * @param node + */ + private void moveExistingNodeToHead(Node node) { + if (node == first) { + return; + } + else if(node == last){ + //当前节点是链表尾, 需要放到链表头 + Node prevNode = node.prev; + prevNode.next = null; + last.prev = null; + last = prevNode; + } else{ + //node 在链表的中间, 把node 的前后节点连接起来 + Node prevNode = node.prev; + prevNode.next = node.next; + + Node nextNode = node.next; + nextNode.prev = prevNode; + } + node.prev = null; + node.next = first; + first.prev = node; + first = node; + } + private boolean isEmpty(){ + return (first == null) && (last == null); + } + + 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/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrameTest.java b/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/group27/1252327158/task4_20170402/linklist/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package com.coding.basic.linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + frame.access(0); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + frame.access(5); + Assert.assertEquals("5,4,0", frame.toString()); + + } + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coderising.jvm.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/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + 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 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(){ + int thisClassIndex = this.clzIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getConstantPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int 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/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.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(); + } +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.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(); + } + + + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coderising.jvm.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()+")"; + } +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.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); + } + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.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; + } + + + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..9c9fac2839 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,140 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import com.coderising.jvm.clz.ClassFile; + + + + + +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", 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()); + } + + + +} diff --git a/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.test; + +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/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/util/Util.java b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group27/1252327158/task4_20170402/mini-jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.coderising.jvm.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 - - - + + + diff --git a/group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java b/group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java index 7a36a83263..c01589f572 100644 --- a/group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java +++ b/group27/383117348/data-structure/com/coding/basic/linklist/LinkedList.java @@ -1,6 +1,5 @@ package com.coding.basic.linklist; -import java.util.Arrays; import java.util.NoSuchElementException; import org.junit.Test; @@ -123,43 +122,42 @@ public void addLast(Object o) { * * @return */ - public Object removeFirst() { - Node node = first; - if (node == null) - throw new NoSuchElementException(); - else { - Node next = node.next; - if (next == null) - first = null; - else { - first = next; - first.prev = null; - } - } - size--; - return node.data; + public Object removeFirst(){ + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + final Object element = f.data; + final Node next = f.next; + f.data = null; + f.next = null; // help GC + first = next; + if (next == null) + last = null; + else + next.prev = null; + size--; + return element; } - /** * 移除链表最后一个元素 * * @return */ public Object removeLast() { - Node node = last; - if (last == null) - throw new NoSuchElementException(); - else { - Node prev = node.prev; - if (prev == null) - last = null; - else { - last = prev; - last.next = null; - } - } - size--; - return node.data; + final Node l = last; + if (l == null) + throw new NoSuchElementException(); + final Object element = l.data; + final Node prev = l.prev; + l.data = null; + l.prev = null; + last = prev; + if (prev == null) + first = null; + else + prev.next = null; + size--; + return element; } /** diff --git a/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java index ff94d5e21a..090564d8b6 100644 --- a/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java +++ b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueue.java @@ -1,5 +1,84 @@ package com.coding.basic.queue; -public class CircleQueue { +/** + * 用数组实现循环队列 + * + * @author liuxin + * + * @param + */ +public class CircleQueue { + private final static int DEFAULT_SIZE = 10; + + // 用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE]; + + // 队头 + private int front = 0; + // 队尾 + private int rear = 0; + + public boolean isEmpty() { + + return rear == front && elementData[rear] == null; + } + + public int size() { + if (isEmpty()) { + return 0; + } + return rear > front ? rear - front : DEFAULT_SIZE - (front - rear); + } + + public void enQueue(E data) { + if (rear == front && elementData[front] != null) { + throw new IndexOutOfBoundsException("队列已满的异常"); + } + elementData[rear++] = data; + // 如果rear已经到头,那就转头 + rear = rear == DEFAULT_SIZE ? 0 : rear; + } + + @SuppressWarnings("unchecked") + public E deQueue() { + if (isEmpty()) { + throw new IndexOutOfBoundsException("空队列异常"); + } + // 保留队列的rear端的元素的值 + E oldValue = (E) elementData[front]; + // 释放队列的rear端的元素 + elementData[front++] = null; + // 如果front已经到头,那就转头 + front = front == DEFAULT_SIZE ? 0 : front; + return oldValue; + } + + public String toString() { + if (isEmpty()) { + return "[]"; + } else { + // 如果front < rear,有效元素就是front到rear之间的元素 + if (front < rear) { + StringBuilder sb = new StringBuilder("["); + for (int i = front; i < rear; i++) { + sb.append(elementData[i].toString() + ", "); + } + int len = sb.length(); + return sb.delete(len - 2, len).append("]").toString(); + } + // 如果front >= rear,有效元素为front->capacity之间、0->front之间的 + else { + StringBuilder sb = new StringBuilder("["); + for (int i = front; i < DEFAULT_SIZE; i++) { + sb.append(elementData[i].toString() + ", "); + } + for (int i = 0; i < rear; i++) { + sb.append(elementData[i].toString() + ", "); + } + int len = sb.length(); + return sb.delete(len - 2, len).append("]").toString(); + } + } + } } diff --git a/group27/383117348/data-structure/com/coding/basic/queue/CircleQueueTest.java b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueueTest.java new file mode 100644 index 0000000000..2103b8d063 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/CircleQueueTest.java @@ -0,0 +1,32 @@ +package com.coding.basic.queue; + +import org.junit.Test; + +public class CircleQueueTest { + + @Test + public void testCircleQueue(){ + CircleQueue queue = new CircleQueue(); + queue.enQueue("aaaaa"); + queue.enQueue("bbbbb"); + queue.enQueue("ccccc"); + queue.enQueue("ddddd"); + queue.enQueue("eeeee"); + queue.enQueue("fffff"); + queue.enQueue("ggggg"); + queue.enQueue("hhhhh"); + queue.enQueue("iiiii"); + queue.enQueue("jjjjj"); + System.out.println("队列全满的时候:"+queue); + System.out.println("删除一个元素后的队列:" + queue.deQueue()); + + queue.enQueue("dddd"); + System.out.println("删除一个再加一个的时候:"+queue); + System.out.println("队列满时的长度:" + queue.size()); + + queue.deQueue(); + + System.out.println("删除一个的时候:"+queue); + } + +} diff --git a/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java b/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java index 9ff4187a53..c646e8ca9d 100644 --- a/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java +++ b/group27/383117348/data-structure/com/coding/basic/queue/Josephus.java @@ -2,10 +2,11 @@ import java.util.ArrayList; import java.util.List; +import java.util.Stack; /** * 用Queue来实现Josephus问题 在这个古老的问题当中, N个深陷绝境的人一致同意用这种方式减少生存人数: N个人围成一圈(位置记为0到N-1), - * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 + * 并且从第一个人报数, 报到M的人会被杀死, 直到最后一个人留下来 该方法返回一个List, 包含了被杀死人的次序 * * @author liuxin * @@ -13,23 +14,32 @@ public class Josephus { public static List execute(int n, int m) { - if (n < m || n <= 0 || m <= 0) { + if (n < m || n <= 0 || m < 0) { throw new RuntimeException("传入参数有误,执行失败!"); } - //保存被杀掉的数 + Stack copy = new Stack(); + Stack count = new Stack(); + for(int i = 0; i < n;i++){ + count.push(i); + } + while(!count.isEmpty()){ + copy.push(count.pop()); + } List ints = new ArrayList(); - //报数 - int count = 0; - while(ints.size()!=n){ - - for(int i=0;i + */ public class QueueWithTwoStacks { - private Stack stack1; - private Stack stack2; - - - public QueueWithTwoStacks() { - stack1 = new Stack(); - stack2 = new Stack(); - } - - - - - public boolean isEmpty() { - return false; - } - - - - public int size() { - return -1; - } - - - - public void enQueue(E item) { - - } - - public E deQueue() { - return null; - } - - - } + private Stack stack1; + private Stack stack2; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + } + + public boolean isEmpty() { + return stack1.size() == 0 && stack2.size() == 0; + } + + public int size() { + if (isEmpty()) { + return 0; + } else { + return stack1.size(); + } + } + + public void enQueue(E item) { + if (item == null) { + throw new NullPointerException(); + } + stack1.push(item); + } + + public E deQueue() { + if (stack1.isEmpty()) { + throw new RuntimeException("队列为空"); + } + while (stack1.size() > 0) { + stack2.push(stack1.pop()); + } + E item = stack2.pop(); + while (stack2.size() > 0) { + stack1.push(stack2.pop()); + }; + return item; + } + +} diff --git a/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacksTest.java b/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacksTest.java new file mode 100644 index 0000000000..79c302467a --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/queue/QueueWithTwoStacksTest.java @@ -0,0 +1,23 @@ +package com.coding.basic.queue; + +import org.junit.Test; + +public class QueueWithTwoStacksTest { + + + + @Test + public void testenQueueAndDequeue(){ + int[] ints = new int[]{2,5,10,32,41}; + QueueWithTwoStacks queue = new QueueWithTwoStacks(); + for(int i=0;i normalStack = new Stack(); + private Stack minNumStack = new Stack(); + + public void push(int data){ + + normalStack.push(data); + + if(minNumStack.isEmpty()){ + minNumStack.push(data); + } else{ + if(minNumStack.peek() >= data) { + minNumStack.push(data); + } + } + + } + public int pop(){ + if(normalStack.isEmpty()){ + throw new RuntimeException("the stack is empty"); + } + int value = normalStack.pop(); + if(value == minNumStack.peek()){ + minNumStack.pop(); + } + return value; + } + public int findMin(){ + return minNumStack.peek(); + } +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/StackWithTwoQueues.java b/group27/383117348/data-structure/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..a8c5e37387 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack; + +import com.coding.basic.queue.Queue; + +public class StackWithTwoQueues { + + /*private QueueWithTwoStacks first; + private QueueWithTwoStacks end;*/ + private Queue first; + private Queue end; + + public StackWithTwoQueues(){ + first = new Queue(); + end = new Queue(); + } + + public void push(int data) { + first.enQueue(data); + } + + public int pop() { + int result = 0; + if(first.isEmpty()){ + throw new NullPointerException("空栈!"); + } + while(!first.isEmpty()){ + if(first.size()==1){ + result = (Integer)first.deQueue(); + }else{ + end.enQueue(first.deQueue()); + } + } + while(!end.isEmpty()){ + first.enQueue(end.deQueue()); + } + return result; + } + + +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/TwoStackInOneArray.java b/group27/383117348/data-structure/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..33b65f82de --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,119 @@ +package com.coding.basic.stack; + +import java.util.NoSuchElementException; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + private static final int GROW_UP_SIZE = 100; + private int index1 =0; + private int index2 = data.length-1; + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + if(o!=null){ + checkIsMeeting(index1); + data[index1++] = o; + }else{ + throw new NullPointerException(); + } + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + if(index1==0) + throw new NoSuchElementException(); + Object first = data[index1-1]; + data[index1--] = null; + return first; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + if(index1==0) + throw new NoSuchElementException(); + return data[index1-1]; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + if(o!=null){ + checkIsMeeting(index2); + data[index2--] = o; + }else{ + throw new NoSuchElementException(); + } + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + if(index2==data.length-1) + throw new NoSuchElementException(); + Object last = data[index2+1]; + data[index2++] = null; + return last; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + if(index2==data.length-1) + throw new NoSuchElementException(); + return data[index2+1]; + } + + public int getSize(){ + System.out.println(index1); + System.out.println(index2); + return (index1-0)+(data.length-1-index2); + } + + /** + * 检查是否碰头 + */ + private void checkIsMeeting(int index){ + if(data[index]!=null){ + growUp(); + } + } + + /** + * 检查数组长度是否越界,越界就自动增长100 + */ + private void growUp() { + Object[] elementGrow = new Object[data.length + GROW_UP_SIZE]; + int start = 0; + int end = elementGrow.length-1; + if(index1!=0) + while(data[index1-1]!=null){ + elementGrow[start++] = pop1(); + } + if(index2!=data.length-1) + while(data[index2+1]!=null){ + elementGrow[end--] = pop2(); + } + data = elementGrow; + index1 = start; + index2 = end; + } + +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/test/StackWithTwoQueuesTest.java b/group27/383117348/data-structure/com/coding/basic/stack/test/StackWithTwoQueuesTest.java new file mode 100644 index 0000000000..eb09709f21 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/test/StackWithTwoQueuesTest.java @@ -0,0 +1,24 @@ +package com.coding.basic.stack.test; + +import java.util.LinkedList; + +import org.junit.Test; + +import com.coding.basic.stack.StackWithTwoQueues; + +import junit.framework.Assert; + +public class StackWithTwoQueuesTest { + + @Test + public void testTwoQueuesStack(){ + StackWithTwoQueues swq = new StackWithTwoQueues(); + swq.push(3); + swq.push(7); + swq.push(10); + LinkedList list = null; + Assert.assertEquals(10, swq.pop()); + Assert.assertEquals(7, swq.pop()); + Assert.assertEquals(3, swq.pop()); + } +} diff --git a/group27/383117348/data-structure/com/coding/basic/stack/test/TwoStackInOneArrayTest.java b/group27/383117348/data-structure/com/coding/basic/stack/test/TwoStackInOneArrayTest.java new file mode 100644 index 0000000000..6f9643eaf7 --- /dev/null +++ b/group27/383117348/data-structure/com/coding/basic/stack/test/TwoStackInOneArrayTest.java @@ -0,0 +1,35 @@ +package com.coding.basic.stack.test; + +import org.junit.Test; + +import com.coding.basic.stack.TwoStackInOneArray; + +import junit.framework.Assert; + +public class TwoStackInOneArrayTest { + + @Test + public void testTwoStack(){ + TwoStackInOneArray tso = new TwoStackInOneArray(); + tso.push1("aaa"); + tso.push1("bbb"); + tso.push1("ccc"); + tso.push1("ddd"); + tso.push2("zzz"); + tso.push2("yyy"); + Assert.assertEquals(6, tso.getSize()); + Assert.assertEquals("ddd", tso.pop1()); + Assert.assertEquals("ccc", tso.pop1()); + Assert.assertEquals("bbb", tso.pop1()); + Assert.assertEquals("aaa", tso.pop1()); + Assert.assertEquals("yyy", tso.pop2()); + Assert.assertEquals("zzz", tso.pop2()); + tso.push2("abcd"); + tso.push2("bcdf"); + Assert.assertEquals("bcdf", tso.pop2()); + Assert.assertEquals("abcd", tso.pop2()); + Assert.assertEquals(0, tso.getSize()); + + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java index cd0fbd4848..19b35ea04c 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/BiPushCmd.java @@ -3,6 +3,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class BiPushCmd extends OneOperandCmd { @@ -17,6 +21,14 @@ public String toString(ConstantPool pool) { return this.getOffset()+": "+ this.getOpCode()+" " + this.getReadableCodeText() + " " + this.getOperand(); } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int value = this.getOperand(); + JavaObject jo = Heap.getInstance().newInt(value); + frame.getOprandStack().push(jo); + + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java index 4006ca69e1..05fa0e2a35 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -6,6 +6,8 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.StackFrame; public abstract class ByteCodeCommand { @@ -14,6 +16,41 @@ public abstract class ByteCodeCommand { ClassFile clzFile; private int offset; + public static final String aconst_null = "01"; + public static final String new_object = "BB"; + public static final String lstore = "37"; + public static final String invokespecial = "B7"; + public static final String invokevirtual = "B6"; + public static final String getfield = "B4"; + public static final String putfield = "B5"; + public static final String getstatic = "B2"; + public static final String ldc = "12"; + public static final String dup = "59"; + public static final String bipush = "10"; + public static final String aload_0 = "2A"; + public static final String aload_1 = "2B"; + public static final String aload_2 = "2C"; + public static final String iload = "15"; + public static final String iload_1 = "1B"; + public static final String iload_2 = "1C"; + public static final String iload_3 = "1D"; + public static final String fload_3 = "25"; + + public static final String voidreturn = "B1"; + public static final String ireturn = "AC"; + public static final String freturn = "AE"; + + public static final String astore_1 = "4C"; + public static final String if_icmp_ge = "A2"; + public static final String if_icmple = "A4"; + public static final String goto_no_condition = "A7"; + public static final String iconst_0 = "03"; + public static final String iconst_1 = "04"; + public static final String istore_1 = "3C"; + public static final String istore_2 = "3D"; + public static final String iadd = "60"; + public static final String iinc = "84"; + private static Map codeMap = new HashMap(); static{ @@ -124,5 +161,5 @@ public String getReadableCodeText(){ return txt; } - //public abstract void execute(StackFrame frame,FrameResult result); + public abstract void execute(StackFrame frame,ExecutionResult result); } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java index 2e6061edd2..0bb497e8d9 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetFieldCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetFieldCmd extends TwoOperandCmd { @@ -16,7 +20,16 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String fieldName = fieldRef.getFieldName(); + JavaObject jo = frame.getOprandStack().pop(); + JavaObject fieldValue = jo.getFieldValue(fieldName); + + frame.getOprandStack().push(fieldValue); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java index e6cf9d5960..4224d1b49e 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/GetStaticFieldCmd.java @@ -5,6 +5,10 @@ import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.FieldRefInfo; import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class GetStaticFieldCmd extends TwoOperandCmd { @@ -19,5 +23,20 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo info = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + String className = info.getClassName(); + String fieldName = info.getFieldName(); + String fieldType = info.getFieldType(); + + if("java/lang/System".equals(className) + && "out".equals(fieldName) + && "Ljava/io/PrintStream;".equals(fieldType)){ + JavaObject jo = Heap.getInstance().newObject(className); + frame.getOprandStack().push(jo); + } + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java index ac228d0e4d..04ea9311a3 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeSpecialCmd.java @@ -3,21 +3,38 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.MethodRefInfo; - +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeSpecialCmd extends TwoOperandCmd { - public InvokeSpecialCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); - + public InvokeSpecialCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + } @Override public String toString(ConstantPool pool) { - + return super.getOperandAsMethod(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + // 我们不用实现jang.lang.Object 的init方法 + if (methodRefInfo.getClassName().equals("java/lang/Object") && methodRefInfo.getMethodName().equals("")) { + return; + + } + Method nextMethod = MethodArea.getInstance().getMethod(methodRefInfo); + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + result.setNextMethod(nextMethod); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java index c15d827797..ad6249c2e5 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/InvokeVirtualCmd.java @@ -2,21 +2,81 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; - +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.MethodArea; +import com.coderising.jvm.engine.StackFrame; +import com.coderising.jvm.method.Method; public class InvokeVirtualCmd extends TwoOperandCmd { - public InvokeVirtualCmd(ClassFile clzFile,String opCode) { - super(clzFile,opCode); + public InvokeVirtualCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); } @Override public String toString(ConstantPool pool) { - + return super.getOperandAsMethod(pool); } - - + private boolean isSystemOutPrintlnMethod(String className, String methodName) { + return "java/io/PrintStream".equals(className) && "println".equals(methodName); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + // 先得到对该方法的描述 + MethodRefInfo methodRefInfo = (MethodRefInfo) this.getConstantInfo(this.getIndex()); + + String className = methodRefInfo.getClassName(); + String methodName = methodRefInfo.getMethodName(); + + // 我们没有实现System.out.println方法, 所以也不用建立新的栈帧, 直接调用Java的方法, 打印出来即可。 + if (isSystemOutPrintlnMethod(className, methodName)) { + JavaObject jo = (JavaObject) frame.getOprandStack().pop(); + String value = jo.toString(); + System.err.println("-------------------" + value + "----------------"); + + // 这里就是那个out对象, 因为是个假的,直接pop出来 + frame.getOprandStack().pop(); + + return; + } + + // 注意:多态, 这才是真正的对象, 先从该对象的class 中去找对应的方法,找不到的话再去找父类的方法 + JavaObject jo = frame.getOprandStack().peek(); + + MethodArea ma = MethodArea.getInstance(); + + Method m = null; + + String currentClassName = jo.getClassName(); + + while (currentClassName != null) { + + ClassFile currentClassFile = ma.findClassFile(currentClassName); + + m = currentClassFile.getMethod(methodRefInfo.getMethodName(), methodRefInfo.getParamAndReturnType()); + if (m != null) { + + break; + + } else { + // 查找父类 + currentClassName = currentClassFile.getSuperClassName(); + } + } + + if (m == null) { + throw new RuntimeException("Can't find method for :" + methodRefInfo.toString()); + } + + result.setNextAction(ExecutionResult.PAUSE_AND_RUN_NEW_FRAME); + + result.setNextMethod(m); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java index ffb66f811c..8f68077c17 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/LdcCmd.java @@ -4,6 +4,10 @@ import com.coderising.jvm.constant.ConstantInfo; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.StringInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class LdcCmd extends OneOperandCmd { @@ -26,4 +30,22 @@ public String toString(ConstantPool pool) { } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + ConstantPool pool = this.getConstantPool(); + ConstantInfo info = (ConstantInfo)pool.getConstantInfo(this.getOperand()); + + if(info instanceof StringInfo){ + StringInfo strInfo = (StringInfo)info; + String value = strInfo.toString(); + JavaObject jo = Heap.getInstance().newString(value); + frame.getOprandStack().push(jo); + } + else{ + //TBD 处理其他类型 + throw new RuntimeException("Only support StringInfo constant"); + } + + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java index 33813b5d59..e60c6e2464 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NewObjectCmd.java @@ -1,19 +1,37 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; -public class NewObjectCmd extends TwoOperandCmd{ - - public NewObjectCmd(ClassFile clzFile, String opCode){ - super(clzFile,opCode); +public class NewObjectCmd extends TwoOperandCmd { + + public NewObjectCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); } @Override public String toString(ConstantPool pool) { - + return super.getOperandAsClassInfo(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + int index = this.getIndex(); + + ClassInfo info = (ClassInfo) this.getConstantInfo(index); + + String clzName = info.getClassName(); + + JavaObject jo = Heap.getInstance().newObject(clzName); + + frame.getOprandStack().push(jo); + + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java index 56c28fefe2..823a723e24 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/NoOperandCmd.java @@ -2,6 +2,10 @@ import com.coderising.jvm.clz.ClassFile; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class NoOperandCmd extends ByteCodeCommand{ @@ -13,11 +17,129 @@ public NoOperandCmd(ClassFile clzFile, String opCode) { public String toString(ConstantPool pool) { return this.getOffset()+":" +this.getOpCode() + " "+ this.getReadableCodeText(); } - - public int getLength(){ return 1; } + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + String opCode = this.getOpCode(); + + if(ByteCodeCommand.aload_0.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_1.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.aload_2.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + }else if(ByteCodeCommand.iload_1.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(1); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_2.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(2); + + frame.getOprandStack().push(jo); + + } else if (ByteCodeCommand.iload_3.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + }else if (ByteCodeCommand.fload_3.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getLocalVariableValue(3); + + frame.getOprandStack().push(jo); + + } + else if (ByteCodeCommand.voidreturn.equalsIgnoreCase(opCode)){ + + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + + } else if(ByteCodeCommand.ireturn.equalsIgnoreCase(opCode)){ + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.freturn.equalsIgnoreCase(opCode)){ + + StackFrame callerFrame = frame.getCallerFrame(); + JavaObject jo = frame.getOprandStack().pop(); + callerFrame.getOprandStack().push(jo); + } + + else if(ByteCodeCommand.astore_1.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.dup.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getOprandStack().peek(); + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_0.equalsIgnoreCase(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(0); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.iconst_1.equalsIgnoreCase(opCode)){ + + JavaObject jo = Heap.getInstance().newInt(1); + + frame.getOprandStack().push(jo); + + } else if(ByteCodeCommand.istore_1.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(1, jo); + + } else if(ByteCodeCommand.istore_2.equalsIgnoreCase(opCode)){ + + JavaObject jo = frame.getOprandStack().pop(); + + frame.setLocalVariableValue(2, jo); + + } else if(ByteCodeCommand.iadd.equalsIgnoreCase(opCode)){ + + JavaObject jo1 = frame.getOprandStack().pop(); + JavaObject jo2 = frame.getOprandStack().pop(); + + JavaObject sum = Heap.getInstance().newInt(jo1.getIntValue()+jo2.getIntValue()); + + frame.getOprandStack().push(sum); + + } else if (ByteCodeCommand.aconst_null.equalsIgnoreCase(opCode)){ + + frame.getOprandStack().push(null); + + } + else{ + throw new RuntimeException("you must forget to implement the operation :" + opCode); + } + + + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java index 85bb369c19..d693315397 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/cmd/PutFieldCmd.java @@ -1,7 +1,13 @@ package com.coderising.jvm.cmd; import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ClassInfo; import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; public class PutFieldCmd extends TwoOperandCmd { @@ -14,6 +20,22 @@ public String toString(ConstantPool pool) { return super.getOperandAsField(pool); } - + @Override + public void execute(StackFrame frame, ExecutionResult result) { + FieldRefInfo fieldRef = (FieldRefInfo)this.getConstantInfo(this.getIndex()); + + ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(fieldRef.getClassInfoIndex()); + NameAndTypeInfo nameTypeInfo = (NameAndTypeInfo)this.getConstantInfo(fieldRef.getNameAndTypeIndex()); + // for example : name + String fieldName = nameTypeInfo.getName(); + // for example : Ljava/lang/String : 注意:我们不再检查类型 + String fieldType = nameTypeInfo.getTypeInfo(); + + JavaObject fieldValue = frame.getOprandStack().pop(); + JavaObject objectRef = frame.getOprandStack().pop(); + + objectRef.setFieldValue(fieldName, fieldValue); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java index e12b3e164e..2896ae38bd 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ClassInfo.java @@ -21,4 +21,9 @@ public String getClassName() { UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); return utf8Info.getValue(); } + @Override + public void accept(Visitor visitor) { + visitor.visitClassInfo(this); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java index a3a0b53b76..05639417c7 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java @@ -27,4 +27,16 @@ public ConstantInfo getConstantInfo(int index){ return this.constantPool.getConstantInfo(index); } + public abstract void accept(Visitor visitor); + + public static interface Visitor{ + public void visitClassInfo(ClassInfo info); + public void visitFieldRef(FieldRefInfo info); + public void visitMethodRef(MethodRefInfo info); + public void visitNameAndType(NameAndTypeInfo info); + public void visitString(StringInfo info); + public void visistUTF8(UTF8Info info); + + } + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java index 0e940b78d0..805de5cd39 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/ConstantPool.java @@ -23,7 +23,7 @@ public ConstantInfo getConstantInfo(int index){ public String getUTF8String(int index){ return ((UTF8Info)this.constantInfos.get(index)).getValue(); } - public Object getSize() { + public int getSize() { return this.constantInfos.size() -1; } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java index 7ff9d5fb77..4e5ca460c7 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java @@ -51,4 +51,9 @@ 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/group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java index dc3765720c..dc970c5dcb 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/FloatInfo.java @@ -23,4 +23,10 @@ public float getValue() { public void setValue(float value) { this.value = value; } + + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java index 06e66c6e08..1c5202a9e9 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/IntegerInfo.java @@ -23,6 +23,12 @@ public int getValue() { public void setValue(int value) { this.value = value; } + + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java index 0feffa65b5..5ceaaaa1a3 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java @@ -49,6 +49,12 @@ public String getParamAndReturnType(){ NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex()); return typeInfo.getTypeInfo(); } + + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + visitor.visitMethodRef(this); + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java index dcac7f97c4..d47b0b5b15 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -42,4 +42,10 @@ public String getTypeInfo(){ public String toString(){ return "(" + getName() + "," + getTypeInfo()+")"; } + + @Override + public void accept(Visitor visitor) { + visitor.visitNameAndType(this); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java index fa90d110fe..64626490df 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java @@ -9,5 +9,10 @@ public NullConstantInfo(){ public int getType() { return -1; } + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java index d01065fd53..b07e783aa1 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/StringInfo.java @@ -22,5 +22,11 @@ public void setIndex(int index) { public String toString(){ return this.getConstantPool().getUTF8String(index); } + + @Override + public void accept(Visitor visitor) { + visitor.visitString(this); + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java b/group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java index b7407d146f..3f239c8b99 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/constant/UTF8Info.java @@ -26,6 +26,11 @@ public String getValue() { public void setValue(String value) { this.value = value; } + @Override + public void accept(Visitor visitor) { + // TODO Auto-generated method stub + visitor.visistUTF8(this); + } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java new file mode 100644 index 0000000000..87ae484b01 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutionResult.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.engine; + +import com.coderising.jvm.method.Method; + +public class ExecutionResult { + public static final int RUN_NEXT_CMD = 1; + public static final int JUMP = 2; + public static final int EXIT_CURRENT_FRAME = 3; + public static final int PAUSE_AND_RUN_NEW_FRAME = 4; + + private int nextAction = RUN_NEXT_CMD; + + private int nextCmdOffset = 0; + + private Method nextMethod; + + public Method getNextMethod() { + return nextMethod; + } + public void setNextMethod(Method nextMethod) { + this.nextMethod = nextMethod; + } + + + + public void setNextAction(int action){ + this.nextAction = action; + } + public boolean isPauseAndRunNewFrame(){ + return this.nextAction == PAUSE_AND_RUN_NEW_FRAME; + } + public boolean isExitCurrentFrame(){ + return this.nextAction == EXIT_CURRENT_FRAME; + } + + public boolean isRunNextCmd(){ + return this.nextAction == RUN_NEXT_CMD; + } + + public boolean isJump(){ + return this.nextAction == JUMP; + } + + public int getNextCmdOffset() { + return nextCmdOffset; + } + + public void setNextCmdOffset(int nextCmdOffset) { + this.nextCmdOffset = nextCmdOffset; + } + + + + + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java new file mode 100644 index 0000000000..f2cdee21b3 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/ExecutorEngine.java @@ -0,0 +1,77 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.attr.CodeAttr; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.method.Method; + +public class ExecutorEngine { + + private Stack stack = new Stack(); + + public ExecutorEngine() { + + } + + public void execute(Method mainMethod){ + StackFrame mainFrame = StackFrame.create(mainMethod); + stack.push(mainFrame); + + while(!stack.empty()){ + + StackFrame frame = stack.peek(); + + ExecutionResult result = frame.execute(); + + if(result.isPauseAndRunNewFrame()){ + + Method nextMethod = result.getNextMethod(); + StackFrame nextFrame = StackFrame.create(nextMethod); + nextFrame.setCallerFrame(frame); + setupFunctionCallParams(frame,nextFrame); + + stack.push(nextFrame); + + } else { + + stack.pop(); + + } + } + } + + + + private void setupFunctionCallParams(StackFrame currentFrame,StackFrame nextFrame) { + Method nextMethod = nextFrame.getMethod(); + List paramList = nextMethod.getParameterList(); + + //加上1 是因为要把this也传递过去 + + int paramNum = paramList.size() + 1; + + + List values = new ArrayList(); + + //数据结构知识: 从栈中取出栈顶的x个元素 + while(paramNum>0){ + values.add(currentFrame.getOprandStack().pop()); + paramNum --; + } + //数据结构知识: 把一个列表倒序排列 + List params = new ArrayList(); + + for(int i=values.size()-1; i>=0 ;i--){ + params.add(values.get(i)); + } + + nextFrame.setLocalVariableTable(params); + + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/Heap.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/Heap.java new file mode 100644 index 0000000000..7df6548625 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/Heap.java @@ -0,0 +1,39 @@ +package com.coderising.jvm.engine; + +public class Heap { + + /** + * 没有实现垃圾回收, 所以对于下面新创建的对象, 并没有记录到一个数据结构当中 + */ + + private static Heap instance = new Heap(); + private Heap() { + } + public static Heap getInstance(){ + return instance; + } + public JavaObject newObject(String clzName){ + + JavaObject jo = new JavaObject(JavaObject.OBJECT); + jo.setClassName(clzName); + return jo; + } + + public JavaObject newString(String value){ + JavaObject jo = new JavaObject(JavaObject.STRING); + jo.setStringValue(value); + return jo; + } + + public JavaObject newFloat(float value){ + JavaObject jo = new JavaObject(JavaObject.FLOAT); + jo.setFloatValue(value); + return jo; + } + public JavaObject newInt(int value){ + JavaObject jo = new JavaObject(JavaObject.INT); + jo.setIntValue(value); + return jo; + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/JavaObject.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/JavaObject.java new file mode 100644 index 0000000000..2d777ede03 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/JavaObject.java @@ -0,0 +1,82 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +public class JavaObject { + public static final int OBJECT = 1; + public static final int STRING = 2; + public static final int INT = 3; + public static final int FLOAT = 4; + + int type; + private String className; + + private Map fieldValues = new HashMap(); + + private String stringValue; + + private int intValue; + + private float floatValue; + + public void setFieldValue(String fieldName, JavaObject fieldValue) { + fieldValues.put(fieldName, fieldValue); + } + + public JavaObject(int type) { + this.type = type; + } + + public void setClassName(String className) { + this.className = className; + } + + public void setStringValue(String value) { + stringValue = value; + } + + public String getStringValue() { + return this.stringValue; + } + + public void setIntValue(int value) { + this.intValue = value; + } + + public int getIntValue() { + return this.intValue; + } + + public int getType() { + return type; + } + + public JavaObject getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public String toString() { + switch (this.getType()) { + case INT: + return String.valueOf(this.intValue); + case STRING: + return this.stringValue; + case OBJECT: + return this.className + ":" + this.fieldValues; + case FLOAT: + return String.valueOf(this.floatValue); + default: + return null; + } + } + + public String getClassName() { + return this.className; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } + +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/MethodArea.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/MethodArea.java new file mode 100644 index 0000000000..575e36d85f --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/MethodArea.java @@ -0,0 +1,81 @@ +package com.coderising.jvm.engine; + +import java.util.HashMap; +import java.util.Map; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.MethodRefInfo; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; + +public class MethodArea { + + public static final MethodArea instance = new MethodArea(); + + /** + * 注意:我们做了极大的简化, ClassLoader 只有一个, 实际JVM中的ClassLoader,是一个双亲委托的模型 + */ + + private ClassFileLoader clzLoader = null; + + Map map = new HashMap(); + + private MethodArea() { + } + + public static MethodArea getInstance() { + return instance; + } + + public void setClassFileLoader(ClassFileLoader clzLoader) { + this.clzLoader = clzLoader; + } + + public Method getMainMethod(String className) { + + ClassFile clzFile = this.findClassFile(className); + + return clzFile.getMainMethod(); + } + + public ClassFile findClassFile(String className) { + + if (map.get(className) != null) { + return map.get(className); + } + // 看来该class 文件还没有load过 + ClassFile clzFile = this.clzLoader.loadClass(className); + + map.put(className, clzFile); + + return clzFile; + + } + + public Method getMethod(String className, String methodName, String paramAndReturnType) { + ClassFile clz = this.findClassFile(className); + + Method m = clz.getMethod(methodName, paramAndReturnType); + + if (m == null) { + + throw new RuntimeException("method can't be found : \n" + "class: " + className + "method: " + methodName + + "paramAndReturnType: " + paramAndReturnType); + } + + return m; + } + + public Method getMethod(MethodRefInfo methodRef) { + ClassFile clz = this.findClassFile(methodRef.getClassName()); + + Method m = clz.getMethod(methodRef.getMethodName(), methodRef.getParamAndReturnType()); + + if (m == null) { + throw new RuntimeException("method can't be found : " + methodRef.toString()); + } + + return m; + + } +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/MiniJVM.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/MiniJVM.java new file mode 100644 index 0000000000..9b7e92ebdc --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/MiniJVM.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.engine; +import java.io.FileNotFoundException; +import java.io.IOException; + +import com.coderising.jvm.loader.ClassFileLoader; + + +public class MiniJVM { + + public void run(String[]classPaths , String className) throws FileNotFoundException, IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + for(int i=0;i operands = new ArrayList(); + + public void push(JavaObject jo){ + operands.add(jo); + } + public JavaObject pop(){ + int index = size()-1; + JavaObject jo = (JavaObject)operands.get(index); + operands.remove(index); + return jo; + + } + public JavaObject top(){ + int index = size()-1; + return (JavaObject)operands.get(index); + } + public int size(){ + return operands.size(); + } +} diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/engine/StackFrame.java b/group27/383117348/mini-jvm/com/coderising/jvm/engine/StackFrame.java new file mode 100644 index 0000000000..690a88cdc4 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/engine/StackFrame.java @@ -0,0 +1,116 @@ +package com.coderising.jvm.engine; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.coderising.jvm.cmd.ByteCodeCommand; +import com.coderising.jvm.method.Method; + +public class StackFrame { + + private List localVariableTable = new ArrayList(); + private Stack oprandStack = new Stack(); + + int index = 0; + + private Method m = null; + + private StackFrame callerFrame = null; + + public StackFrame getCallerFrame() { + return callerFrame; + } + + public void setCallerFrame(StackFrame callerFrame) { + this.callerFrame = callerFrame; + } + + public static StackFrame create(Method m) { + + StackFrame frame = new StackFrame(m); + + return frame; + } + + private StackFrame(Method m) { + this.m = m; + + } + + public JavaObject getLocalVariableValue(int index) { + return this.localVariableTable.get(index); + } + + public Stack getOprandStack() { + return this.oprandStack; + } + + public int getNextCommandIndex(int offset) { + + ByteCodeCommand[] cmds = m.getCodeAttr().getCmds(); + for (int i = 0; i < cmds.length; i++) { + if (cmds[i].getOffset() == offset) { + return i; + } + } + throw new RuntimeException("Can't find next command"); + } + + public ExecutionResult execute() { + + ByteCodeCommand[] cmds = m.getCmds(); + + while (index < cmds.length) { + + ExecutionResult result = new ExecutionResult(); + // 缺省值是执行下一条命令 + result.setNextAction(ExecutionResult.RUN_NEXT_CMD); + + System.out.println(cmds[index].toString()); + + cmds[index].execute(this, result); + + if (result.isRunNextCmd()) { + index++; + } else if (result.isExitCurrentFrame()) { + return result; + } else if (result.isPauseAndRunNewFrame()) { + index++; + return result; + } else if (result.isJump()) { + int offset = result.getNextCmdOffset(); + this.index = getNextCommandIndex(offset); + } else { + index++; + } + + } + + // 当前StackFrmae的指令全部执行完毕,可以退出了 + ExecutionResult result = new ExecutionResult(); + result.setNextAction(ExecutionResult.EXIT_CURRENT_FRAME); + return result; + + } + + public void setLocalVariableTable(List values) { + this.localVariableTable = values; + } + + public void setLocalVariableValue(int index, JavaObject jo) { + // 问题: 为什么要这么做?? + if (this.localVariableTable.size() - 1 < index) { + for (int i = this.localVariableTable.size(); i <= index; i++) { + this.localVariableTable.add(null); + } + } + this.localVariableTable.set(index, jo); + + } + + public Method getMethod() { + return m; + } + +} \ No newline at end of file diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java index 091ecc2209..47a9ce274f 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/method/Method.java @@ -1,5 +1,8 @@ package com.coderising.jvm.method; +import java.util.ArrayList; +import java.util.List; + import com.coderising.jvm.attr.AttributeInfo; import com.coderising.jvm.attr.CodeAttr; import com.coderising.jvm.clz.ClassFile; @@ -53,24 +56,83 @@ public static Method parse(ClassFile clzFile, ByteCodeIterator iter) { Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); int attirbutesCount = iter.nextU2Int(); - + for (int i = 0; i < attirbutesCount; i++) { int attributeNameIndex = iter.nextU2Int(); iter.back(2); String attributeName = ((UTF8Info) clzFile.getConstantPool().getConstantInfo(attributeNameIndex)) .getValue(); - + if (null != attributeName && attributeName.equalsIgnoreCase(AttributeInfo.CODE)) { CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); method.setCodeAttr(codeAttr); } else { - throw new RuntimeException("解析属性异常-属性名:"+attributeName); + throw new RuntimeException("解析属性异常-属性名:" + attributeName); } } return method; } - public ByteCodeCommand[] getCmds() { + + public ByteCodeCommand[] getCmds() { return this.getCodeAttr().getCmds(); } + + private String getParamAndReturnType() { + UTF8Info nameAndTypeInfo = (UTF8Info) this.getClzFile().getConstantPool() + .getConstantInfo(this.getDescriptorIndex()); + return nameAndTypeInfo.getValue(); + } + + public List getParameterList() { + + // e.g. (Ljava/util/List;Ljava/lang/String;II)V + String paramAndType = getParamAndReturnType(); + + int first = paramAndType.indexOf("("); + int last = paramAndType.lastIndexOf(")"); + // e.g. Ljava/util/List;Ljava/lang/String;II + String param = paramAndType.substring(first + 1, last); + + List paramList = new ArrayList(); + + if ((null == param) || "".equals(param)) { + return paramList; + } + + while (!param.equals("")) { + + int pos = 0; + // 这是一个对象类型 + if (param.charAt(pos) == 'L') { + + int end = param.indexOf(";"); + + if (end == -1) { + throw new RuntimeException("can't find the ; for a object type"); + } + paramList.add(param.substring(pos + 1, end)); + + pos = end + 1; + + } else if (param.charAt(pos) == 'I') { + // int + paramList.add("I"); + pos++; + + } else if (param.charAt(pos) == 'F') { + // float + paramList.add("F"); + pos++; + + } else { + throw new RuntimeException("the param has unsupported type:" + param); + } + + param = param.substring(pos); + + } + return paramList; + + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java b/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java index 14407bacbe..1786b7f4f4 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/print/ClassFilePrinter.java @@ -40,7 +40,7 @@ public void print(){ } public static void main(String[] args){ - String path = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + String path = "E:\\MyGit\\coding2017\\group27\\383117348\\bin"; ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path); String className = "com.coderising.jvm.test.EmployeeV1"; diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java b/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java index 028161adc7..412f4c8651 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/print/ConstantPoolPrinter.java @@ -18,7 +18,67 @@ public void print(){ System.out.println("Constant Pool:"); + ConstantInfo.Visitor visitor = new ConstantInfo.Visitor() { + + @Override + public void visitString(StringInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("String #").append(info.getIndex()); + System.out.println(buffer); + + } + + @Override + public void visitNameAndType(NameAndTypeInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("NameAndType #").append(info.getIndex1()).append(":#") + .append(info.getIndex2()); + System.out.println(buffer); + + } + + @Override + public void visitMethodRef(MethodRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("MethodRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitFieldRef(FieldRefInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("FieldRef #").append(info.getClassInfoIndex()).append(".#") + .append(info.getNameAndTypeIndex()); + System.out.println(buffer); + + } + + @Override + public void visitClassInfo(ClassInfo info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("Class #").append(info.getUtf8Index()) + .append(" ").append(info.getClassName()); + + System.out.println(buffer); + + } + + @Override + public void visistUTF8(UTF8Info info) { + StringBuilder buffer = new StringBuilder(); + buffer.append("UTF8 ").append(info.getValue()); + System.out.println(buffer); + + } + }; + for(int i=1; i<=pool.getSize(); i++){ + ConstantInfo constantInfo = pool.getConstantInfo(i); + System.out.print("#"+i+"="); + constantInfo.accept(visitor); + } } diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java index b2128a5372..b9dc2608f8 100644 --- a/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/383117348/mini-jvm/com/coderising/jvm/test/ClassFileloaderTest.java @@ -27,7 +27,7 @@ public class ClassFileloaderTest { private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; - static String path1 = "E:\\MyGit\\coding2017\\group27\\383117348\\bin"; + static String path1 = "E:\\coding2017\\group27\\383117348\\bin"; static String path2 = "C:\temp"; static ClassFile clzFile = null; diff --git a/group27/383117348/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java b/group27/383117348/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java new file mode 100644 index 0000000000..22193dc246 --- /dev/null +++ b/group27/383117348/mini-jvm/com/coderising/jvm/test/MiniJVMTest.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.engine.MiniJVM; + +public class MiniJVMTest { + + static final String PATH = "E:\\coding2017\\group27\\383117348\\bin"; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testMain() throws Exception { + String[] classPaths = { PATH }; + MiniJVM jvm = new MiniJVM(); + jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/queue/CircleQueue.java b/group27/513274874/data-structure/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..b346bb6044 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,80 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +/** + * 用数组实现循环队列 + * @author liuxin + * + * @param + */ +public class CircleQueue { + + private final static int DEFAULT_SIZE = 10; + private final static int INCREAMENT_SIZE = 5; + + //用数组来保存循环队列的元素 + private Object[] elementData = new Object[DEFAULT_SIZE] ; + + //队头 + private int front = 0; + //队尾 + private int rear = 0; + + public boolean isEmpty() { + return front == rear; + + } + + public int size() { + return rear > front ? rear-front : elementData.length - (front-rear); + } + + + + public void enQueue(E data) { + //empty + if(this.isEmpty()){ + elementData[front] = data; + rear++; + return; + } + + //oversize enlarge elementData + if(this.size() == elementData.length){ + Object[] newElementData = new Object[elementData.length + INCREAMENT_SIZE]; + int index = 0; + for(int i = front ; i==rear; i++){ + if(i == this.size()-1){ + i = 0 ; + } + newElementData[index++] = elementData[i]; + } + + elementData = newElementData; + }else{ + if(rear == elementData.length-1){ + rear = 0; + }else{ + rear++; + } + elementData[rear] = data; + } + + } + + public E deQueue() { + if (isEmpty()) { + throw new NoSuchElementException("Queue underflow"); + } + //rear is the first element + if(rear == 0 ){ + E data = (E)elementData[rear]; + rear = elementData.length -1 ; + return data ; + }else { + return (E)elementData[rear--]; + } + + } +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/queue/Josephus.java b/group27/513274874/data-structure/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..d565c8318f --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/queue/Josephus.java @@ -0,0 +1,44 @@ +package com.coding.basic.queue; + +import java.util.ArrayList; +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){ + + Queue queue = new Queue<>(); + + List killed = new ArrayList<>(); + + for(int i = 0 ;i< n ;i++){ + queue.enQueue(i); + } + + int index = 0; + + while( !queue.isEmpty()){ + + Integer num = queue.deQueue(); + + index ++; + + if(index % m == 0){ + killed.add(num); + }else { + queue.enQueue(num); + } + } + return killed; + } + + + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/queue/JosephusTest.java b/group27/513274874/data-structure/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/queue/JosephusTest.java @@ -0,0 +1,27 @@ +package com.coding.basic.queue; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class JosephusTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testExecute() { + + Assert.assertEquals("[1, 3, 5, 0, 4, 2, 6]", Josephus.execute(7, 2).toString()); + + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/queue/Queue.java b/group27/513274874/data-structure/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/queue/Queue.java @@ -0,0 +1,61 @@ +package com.coding.basic.queue; + +import java.util.NoSuchElementException; + +public class Queue { + 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/group27/513274874/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java b/group27/513274874/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..972bde1e7b --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,63 @@ +package com.coding.basic.queue; + +import java.util.Stack; + +/** + * 用两个栈来实现一个队列 + * @author liuxin + * + * @param + */ +public class QueueWithTwoStacks { + //store data + private Stack stack1; + + //temp memory + private Stack stack2; + + private int size; + + public QueueWithTwoStacks() { + stack1 = new Stack(); + stack2 = new Stack(); + size = 0 ; + } + + public boolean isEmpty() { + return stack1.isEmpty() && stack2.isEmpty(); + } + + + + public int size() { + return size; + } + + + + public void enQueue(E item) { + stack1.push(item); + size++; + } + + public E deQueue() { + if(this.isEmpty() ) return null; + + while(!stack1.isEmpty()){ + stack2.push(stack1.pop()); + } + + E data = stack2.pop(); + + //put back the data + while(!stack1.isEmpty()){ + stack1.push(stack2.pop()); + } + + size--; + return data; + } + + + } + diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/QuickMinStack.java b/group27/513274874/data-structure/src/com/coding/basic/stack/QuickMinStack.java new file mode 100644 index 0000000000..830c347ad5 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/QuickMinStack.java @@ -0,0 +1,42 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * 设计一个栈,支持栈的push和pop操作,以及第三种操作findMin, 它返回改数据结构中的最小元素 + * finMin操作最坏的情形下时间复杂度应该是O(1) , 简单来讲,操作一次就可以得到最小值 + * @author liuxin + * + */ +public class QuickMinStack { + + //存储栈中元素,升序排列,minAscList.get(0)即能取出 + private List minAscList = new ArrayList<>(); + + private Stack stack; + + public void push(int data){ + stack.push(data); + minAscList.add(data); + minAscList.sort(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o1.compareTo(o2); + } + }); + } + public int pop(){ + + int val = (Integer)stack.pop(); + minAscList.remove(new Integer(val)); + + return val; + } + public int findMin(){ + return minAscList.get(0); + } + + +} \ No newline at end of file diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/StackWithTwoQueues.java b/group27/513274874/data-structure/src/com/coding/basic/stack/StackWithTwoQueues.java new file mode 100644 index 0000000000..fef1b31bbd --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/StackWithTwoQueues.java @@ -0,0 +1,45 @@ +package com.coding.basic.stack; + + +import com.coding.basic.queue.Queue; + +public class StackWithTwoQueues { + + Queue q1 = new Queue<>(); + Queue q2 = new Queue<>(); + + + public void push(int data) { + if (q1.isEmpty()) { + q2.enQueue(data); + } else { + q1.enQueue(data); + } + } + + public int pop() { + if (!q1.isEmpty()) { + while (!q1.isEmpty()) { + int val = q1.deQueue(); + if (q1.isEmpty()) { + q2.enQueue(val); + } else { + return val; + } + } + } else { + while (!q2.isEmpty()) { + int val = q2.deQueue(); + if (!q2.isEmpty()) { + q1.enQueue(val); + } else { + return val; + } + } + + } + return 0; + } + + +} \ No newline at end of file diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java b/group27/513274874/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java new file mode 100644 index 0000000000..4d311762f6 --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/TwoStackInOneArray.java @@ -0,0 +1,57 @@ +package com.coding.basic.stack; + +/** + * 用一个数组实现两个栈 + * 将数组的起始位置看作是第一个栈的栈底,将数组的尾部看作第二个栈的栈底,压栈时,栈顶指针分别向中间移动,直到两栈顶指针相遇,则扩容。 + * @author liuxin + * + */ +public class TwoStackInOneArray { + Object[] data = new Object[10]; + + /** + * 向第一个栈中压入元素 + * @param o + */ + public void push1(Object o){ + + } + /** + * 从第一个栈中弹出元素 + * @return + */ + public Object pop1(){ + return null; + } + + /** + * 获取第一个栈的栈顶元素 + * @return + */ + + public Object peek1(){ + return null; + } + /* + * 向第二个栈压入元素 + */ + public void push2(Object o){ + + } + /** + * 从第二个栈弹出元素 + * @return + */ + public Object pop2(){ + return null; + } + /** + * 获取第二个栈的栈顶元素 + * @return + */ + + public Object peek2(){ + return null; + } + +} \ No newline at end of file diff --git a/group04/1796244932/learn01/src/main/java/com/dudy/learn01/litestruts/format/struts.xml b/liuxin/data-structure/answer/src/com/coderising/litestruts/struts.xml old mode 100755 new mode 100644 similarity index 100% rename from group04/1796244932/learn01/src/main/java/com/dudy/learn01/litestruts/format/struts.xml rename to liuxin/data-structure/answer/src/com/coderising/litestruts/struts.xml diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/QuickMinStack.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/QuickMinStack.java index b55762e8af..faf2644ab1 100644 --- a/liuxin/data-structure/answer/src/com/coding/basic/stack/QuickMinStack.java +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/QuickMinStack.java @@ -36,6 +36,9 @@ public int pop(){ return value; } public int findMin(){ + if(minNumStack.isEmpty()){ + throw new RuntimeException("the stack is empty"); + } return minNumStack.peek(); } } \ No newline at end of file diff --git a/liuxin/data-structure/assignment/.gitignore b/liuxin/data-structure/assignment/.gitignore new file mode 100644 index 0000000000..3e2fcc7171 --- /dev/null +++ b/liuxin/data-structure/assignment/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/liuxin/data-structure/assignment/src/com/coderising/litestruts/struts.xml b/liuxin/data-structure/assignment/src/com/coderising/litestruts/struts.xml new file mode 100644 index 0000000000..4c6eeabbd4 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coderising/litestruts/struts.xml @@ -0,0 +1,11 @@ + + + + /jsp/homepage.jsp + /jsp/showLogin.jsp + + + /jsp/welcome.jsp + /jsp/error.jsp + + \ No newline at end of file diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTree.java b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTree.java new file mode 100644 index 0000000000..f01cbe358b --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTree.java @@ -0,0 +1,48 @@ +package com.coding.basic.tree; + +import java.util.ArrayList; +import java.util.List; + +import com.coding.basic.queue.Queue; + +public class BinarySearchTree { + + BinaryTreeNode root; + public BinarySearchTree(BinaryTreeNode root){ + this.root = root; + } + public BinaryTreeNode getRoot(){ + return root; + } + public T findMin(){ + return null; + } + public T findMax(){ + return null; + } + public int height() { + return -1; + } + public int size() { + return -1; + } + public void remove(T e){ + + } + public List levelVisit(){ + + return null; + } + public boolean isValid(){ + return false; + } + public T getLowestCommonAncestor(T n1, T n2){ + return null; + + } + public List getNodesBetween(T n1, T n2){ + return null; + } + +} + diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTreeTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTreeTest.java new file mode 100644 index 0000000000..3f58b60bc9 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinarySearchTreeTest.java @@ -0,0 +1,67 @@ +package com.coding.basic.tree; + +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class BinarySearchTreeTest { + + BinarySearchTree tree = null; + + @Before + public void setUp() throws Exception { + BinaryTreeNode root = new BinaryTreeNode(6); + root.left = new BinaryTreeNode(2); + root.right = new BinaryTreeNode(8); + root.left.left = new BinaryTreeNode(1); + root.left.right = new BinaryTreeNode(4); + root.left.right.left = new BinaryTreeNode(3); + tree = new BinarySearchTree(root); + } + + @After + public void tearDown() throws Exception { + tree = null; + } + + @Test + public void testFindMin() { + Assert.assertEquals(1, tree.findMin().intValue()); + + } + + @Test + public void testFindMax() { + Assert.assertEquals(8, tree.findMax().intValue()); + } + + @Test + public void testHeight() { + Assert.assertEquals(4, tree.height()); + } + + @Test + public void testSize() { + Assert.assertEquals(6, tree.size()); + } + + @Test + public void testRemoveLeaf() { + tree.remove(4); + BinaryTreeNode root= tree.getRoot(); + Assert.assertEquals(3, root.left.right.data.intValue()); + + } + @Test + public void testRemoveMiddleNode() { + tree.remove(2); + BinaryTreeNode root= tree.getRoot(); + Assert.assertEquals(3, root.left.data.intValue()); + Assert.assertEquals(4, root.left.right.data.intValue()); + } +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinaryTreeNode.java b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinaryTreeNode.java index 467101a16f..e06edbd942 100644 --- a/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinaryTreeNode.java +++ b/liuxin/data-structure/assignment/src/com/coding/basic/tree/BinaryTreeNode.java @@ -1,35 +1,35 @@ -package com.coding.basic.tree; - -public class BinaryTreeNode { - - private T data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public BinaryTreeNode(T data){ - this.data=data; - } - public T getData() { - return data; - } - public void setData(T data) { - this.data = data; - } - public BinaryTreeNode getLeft() { - return left; - } - public void setLeft(BinaryTreeNode left) { - this.left = left; - } - public BinaryTreeNode getRight() { - return right; - } - public void setRight(BinaryTreeNode right) { - this.right = right; - } - - public BinaryTreeNode insert(Object o){ - return null; - } - -} +package com.coding.basic.tree; + +public class BinaryTreeNode { + + public T data; + public BinaryTreeNode left; + public BinaryTreeNode right; + + public BinaryTreeNode(T data){ + this.data=data; + } + public T getData() { + return data; + } + public void setData(T data) { + this.data = data; + } + public BinaryTreeNode getLeft() { + return left; + } + public void setLeft(BinaryTreeNode left) { + this.left = left; + } + public BinaryTreeNode getRight() { + return right; + } + public void setRight(BinaryTreeNode right) { + this.right = right; + } + + public BinaryTreeNode insert(Object o){ + return null; + } + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/ConstantValue.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/ConstantValue.java new file mode 100644 index 0000000000..9b23856bf4 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/ConstantValue.java @@ -0,0 +1,21 @@ +package com.coderising.jvm.attr; + +public class ConstantValue extends AttributeInfo { + + private int constValueIndex; + + public ConstantValue(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + + public int getConstValueIndex() { + return constValueIndex; + } + public void setConstValueIndex(int constValueIndex) { + this.constValueIndex = constValueIndex; + } + + + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java index 6b8f2e6348..e6af5b0a3f 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java @@ -55,6 +55,10 @@ public abstract class ByteCodeCommand { static{ codeMap.put("01", "aconst_null"); + codeMap.put("A2", "if_icmp_ge"); + codeMap.put("A4", "if_icmple"); + codeMap.put("A7", "goto"); + codeMap.put("BB", "new"); codeMap.put("37", "lstore"); codeMap.put("B7", "invokespecial"); diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java index f2ea2147fa..60fc52cc59 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java @@ -66,7 +66,20 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { BiPushCmd cmd = new BiPushCmd(clzFile, opCode); cmd.setOperand(iter.next2CharAsInt()); cmds.add(cmd); - } else if (ByteCodeCommand.dup.equals(opCode) + }else if(ByteCodeCommand.if_icmp_ge.equals(opCode) + || ByteCodeCommand.if_icmple.equals(opCode) + || ByteCodeCommand.goto_no_condition.equals(opCode)){ + ComparisonCmd cmd = new ComparisonCmd(clzFile,opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } else if(ByteCodeCommand.iinc.equals(opCode)){ + IncrementCmd cmd = new IncrementCmd(clzFile,opCode); + cmd.setOprand1(iter.next2CharAsInt()); + cmd.setOprand2(iter.next2CharAsInt()); + cmds.add(cmd); + } + else if (ByteCodeCommand.dup.equals(opCode) || ByteCodeCommand.aload_0.equals(opCode) || ByteCodeCommand.aload_1.equals(opCode) || ByteCodeCommand.aload_2.equals(opCode) @@ -74,8 +87,14 @@ public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) { || ByteCodeCommand.iload_2.equals(opCode) || ByteCodeCommand.iload_3.equals(opCode) || ByteCodeCommand.fload_3.equals(opCode) + || ByteCodeCommand.iconst_0.equals(opCode) + || ByteCodeCommand.iconst_1.equals(opCode) + || ByteCodeCommand.istore_1.equals(opCode) + || ByteCodeCommand.istore_2.equals(opCode) || ByteCodeCommand.voidreturn.equals(opCode) - || ByteCodeCommand.astore_1.equals(opCode)) { + || ByteCodeCommand.iadd.equals(opCode) + || ByteCodeCommand.astore_1.equals(opCode) + || ByteCodeCommand.ireturn.equals(opCode)) { NoOperandCmd cmd = new NoOperandCmd(clzFile, opCode); cmds.add(cmd); diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ComparisonCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ComparisonCmd.java new file mode 100644 index 0000000000..fd900ceaea --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ComparisonCmd.java @@ -0,0 +1,78 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class ComparisonCmd extends TwoOperandCmd { + + protected ComparisonCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + + @Override + public void execute(StackFrame frame,ExecutionResult result) { + + if(ByteCodeCommand.if_icmp_ge.equals(this.getOpCode())){ + //注意次序 + JavaObject jo2 = frame.getOprandStack().pop(); + JavaObject jo1 = frame.getOprandStack().pop(); + + if(jo1.getIntValue() >= jo2.getIntValue()){ + + this.setJumpResult(result); + + } + + } else if(ByteCodeCommand.if_icmple.equals(this.getOpCode())){ + //注意次序 + JavaObject jo2 = frame.getOprandStack().pop(); + JavaObject jo1 = frame.getOprandStack().pop(); + + if(jo1.getIntValue() <= jo2.getIntValue()){ + this.setJumpResult(result); + } + + } else if(ByteCodeCommand.goto_no_condition.equals(this.getOpCode())){ + this.setJumpResult(result); + + } else{ + throw new RuntimeException(this.getOpCode() + "has not been implemented"); + } + + + + + } + + private int getOffsetFromStartCmd(){ + //If the comparison succeeds, the unsigned branchbyte1 and branchbyte2 + //are used to construct a signed 16-bit offset, where the offset is calculated + //to be (branchbyte1 << 8) | branchbyte2. Execution then proceeds at that + //offset from the address of the opcode of this if_icmp instruction + + + int index1 = this.getOprand1(); + int index2 = this.getOprand2(); + short offsetFromCurrent = (short)(index1 << 8 | index2); + return this.getOffset() + offsetFromCurrent ; + } + private void setJumpResult(ExecutionResult result){ + + int offsetFromStartCmd = this.getOffsetFromStartCmd(); + + result.setNextAction(ExecutionResult.JUMP); + result.setNextCmdOffset(offsetFromStartCmd); + } + + @Override + public String toString() { + int index = this.getIndex(); + String text = this.getReadableCodeText(); + return this.getOffset()+":"+ this.getOpCode() + " "+text + " " + this.getOffsetFromStartCmd(); + } + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/IncrementCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/IncrementCmd.java new file mode 100644 index 0000000000..dda40bc74d --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/IncrementCmd.java @@ -0,0 +1,38 @@ +package com.coderising.jvm.cmd; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.engine.ExecutionResult; +import com.coderising.jvm.engine.Heap; +import com.coderising.jvm.engine.JavaObject; +import com.coderising.jvm.engine.StackFrame; + +public class IncrementCmd extends TwoOperandCmd { + + public IncrementCmd(ClassFile clzFile, String opCode) { + super(clzFile, opCode); + + } + + @Override + public String toString() { + + return this.getOffset()+":"+this.getOpCode()+ " " +this.getReadableCodeText(); + } + + @Override + public void execute(StackFrame frame, ExecutionResult result) { + + int index = this.getOprand1(); + + int constValue = this.getOprand2(); + + int currentValue = frame.getLocalVariableValue(index).getIntValue(); + + JavaObject jo = Heap.getInstance().newInt(constValue+currentValue); + + frame.setLocalVariableValue(index, jo); + + + } + +} \ No newline at end of file diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java index c6eb0196f8..e1e4723aa0 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java @@ -1,5 +1,7 @@ package com.coderising.jvm.field; +import com.coderising.jvm.attr.AttributeInfo; +import com.coderising.jvm.attr.ConstantValue; import com.coderising.jvm.constant.ConstantPool; import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ByteCodeIterator; @@ -10,9 +12,8 @@ public class Field { private int nameIndex; private int descriptorIndex; - - private ConstantPool pool; + private ConstantValue constValue; public Field( int accessFlag, int nameIndex, int descriptorIndex,ConstantPool pool) { @@ -40,11 +41,24 @@ public static Field parse(ConstantPool pool,ByteCodeIterator iter){ Field f = new Field(accessFlag, nameIndex, descIndex,pool); - if(attribCount > 0){ - throw new RuntimeException("Field Attribute has not been implemented"); + for( int i=1; i<= attribCount; i++){ + int attrNameIndex = iter.nextU2ToInt(); + String attrName = pool.getUTF8String(attrNameIndex); + + if(AttributeInfo.CONST_VALUE.equals(attrName)){ + int attrLen = iter.nextU4ToInt(); + ConstantValue constValue = new ConstantValue(attrNameIndex, attrLen); + constValue.setConstValueIndex(iter.nextU2ToInt()); + f.setConstantValue(constValue); + } else{ + throw new RuntimeException("the attribute " + attrName + " has not been implemented yet."); + } } return f; } + public void setConstantValue(ConstantValue constValue) { + this.constValue = constValue; + } } diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/EmployeeV2.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/EmployeeV2.java new file mode 100644 index 0000000000..039800d2b1 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/EmployeeV2.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.test; + +public class EmployeeV2 { + + public final static String TEAM_NAME = "Dev Team"; + private String name; + private int age; + public EmployeeV2(String name, int age) { + this.name = name; + this.age = age; + } + + public void sayHello() { + System.out.println("Hello , this is class Employee "); + System.out.println(TEAM_NAME); + System.out.println(this.name); + } + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age; + } + + + + public void isYouth() { + if (age < 40) { + System.out.println("You're still young"); + } else { + System.out.println("You're old"); + } + } + + + + public void testAdd() { + int sum = 0; + for (int i = 1; i <= 100; i++) { + sum += i; + } + System.out.println(sum); + } + + + public static void main(String[] args) { + EmployeeV2 p = new EmployeeV2("Andy", 35); + p.sayHello(); + p.isYouth(); + p.testAdd(); + } +} \ No newline at end of file diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/Example.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/Example.java new file mode 100644 index 0000000000..7763e38d1e --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/Example.java @@ -0,0 +1,16 @@ +package com.coderising.jvm.test; + +public class Example{ + public void disp(char c){ + System.out.println(c); + } + public void disp(int c){ + System.out.println(c ); + } + public static void main(String args[]){ + Example obj = new Example(); + obj.disp('a'); + obj.disp(5); + } +} + diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/HourlyEmployee.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/HourlyEmployee.java new file mode 100644 index 0000000000..d26e097a82 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/HourlyEmployee.java @@ -0,0 +1,27 @@ +package com.coderising.jvm.test; + +public class HourlyEmployee extends EmployeeV2 { + + int hourlySalary; + + public HourlyEmployee(String name, + int age, int hourlySalary) { + super(name, age); + this.hourlySalary = hourlySalary; + } + + public void sayHello(){ + System.out.println("Hello , this is Hourly Employee"); + } + public static void main(String[] args){ + EmployeeV2 e = new HourlyEmployee("Lisa", 20, 40); + e.sayHello(); + } + + public int getHourlySalary(){ + return this.hourlySalary; + } + + + +} diff --git a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java index 787c0d954d..48b1383c2a 100644 --- a/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/MiniJVMTest.java @@ -21,7 +21,7 @@ public void tearDown() throws Exception { public void testMain() throws Exception{ String[] classPaths = {PATH}; MiniJVM jvm = new MiniJVM(); - jvm.run(classPaths, "com.coderising.jvm.test.EmployeeV1"); + jvm.run(classPaths, "com.coderising.jvm.test.HourlyEmployee"); }