diff --git a/group01/1298552064/src/week04/lru/LRUPageFrame.java b/group01/1298552064/src/week04/lru/LRUPageFrame.java new file mode 100644 index 0000000000..b00ff2c116 --- /dev/null +++ b/group01/1298552064/src/week04/lru/LRUPageFrame.java @@ -0,0 +1,116 @@ +package week04.lru; + +public class LRUPageFrame { + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node(Node prev, Node next, int pageNum) { + this.prev = prev; + this.next = next; + this.pageNum = pageNum; + } + } + + private int capacity; + + private Node first;// 链表头 + private Node last;// 链表尾 + private int size; // 链表长度 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + int index = find(pageNum); + if (size != 0) { + if(index >= 0){ + remove(index); + }else if(size == capacity){ + remove(size - 1); + } + } + addToHead(pageNum); + } + + public void remove(int index) { + if (index == 0) { + if(size == 1){ + first = last = null; + }else{ + first = first.next; + first.prev = null; + } + } else if (index == (size - 1)) { + if(size == 1){ + first = last = null; + }else{ + last = last.prev; + last.next = null; + } + } else { + Node node = first; + for (int i = 1; i < index; i++) { + node = node.next; + } + + Node nxt = node.next; + + node.next = nxt.next; + (nxt.next).prev = node; + nxt = null; + } + size--; + } + + public int find(int pageNum) { + int index = 0; + Node cur = first; + while (cur != null) { + if (pageNum == cur.pageNum) { + return index; + } + cur = cur.next; + index++; + } + return -1; + } + + public void addToHead(int pageNum) { + // 链表为空 + if (first == null) { + Node node = new Node(null, null, pageNum); + first = node; + last = node; + } else { + Node node = new Node(null,first,pageNum); + first.prev = node; + first = node; + } + size ++; + } + + @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/group01/1298552064/src/week04/minijvm/loader/ClassFileLoader.java b/group01/1298552064/src/week04/minijvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..2e80e89587 --- /dev/null +++ b/group01/1298552064/src/week04/minijvm/loader/ClassFileLoader.java @@ -0,0 +1,67 @@ +package week04.minijvm.loader; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +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) throws IOException { + if(className == null){ + return null; + } + + boolean isFileExist = false; + File file = null; + String classPath = className.replace(".", "\\"); + for(int i = 0 ; i < clzPaths.size(); i++){ + String basePath = clzPaths.get(i); + file = new File(basePath + File.separator + classPath + ".class"); + + if(file.exists()){ + isFileExist = true; + break; + } + } + + //找不到类 + if(!isFileExist){ + throw new FileNotFoundException(); + } + + //读取字节码文件到数组 + FileInputStream in = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte [] rs = new byte[1024]; + int len = 0; + while((len = in.read(rs)) != -1){ + bos.write(rs, 0, len); + } + bos.close(); + in.close(); + System.out.println("readBinaryCode:" + " file size = " + file.length()); + return bos.toByteArray(); + } + + public void addClassPath(String path) { + if(! clzPaths.contains(path)){ + clzPaths.add(path); + } + } + + 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(); + } +} diff --git a/group01/1298552064/src/week04/test/ClassFileloaderTest.java b/group01/1298552064/src/week04/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..18b42f859d --- /dev/null +++ b/group01/1298552064/src/week04/test/ClassFileloaderTest.java @@ -0,0 +1,78 @@ +package week04.test; + +import java.io.IOException; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import week04.minijvm.loader.ClassFileLoader; + + +public class ClassFileloaderTest { + static String path1 = "D:\\Git_2017\\coding2017\\group01\\1298552064\\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() throws IOException { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "week04.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1032, byteCodes.length); + + } + + @Test + public void testMagicNumber() throws IOException { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "week04.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(); + } +} diff --git a/group01/1298552064/src/week04/test/EmployeeV1.java b/group01/1298552064/src/week04/test/EmployeeV1.java new file mode 100644 index 0000000000..1c292f7744 --- /dev/null +++ b/group01/1298552064/src/week04/test/EmployeeV1.java @@ -0,0 +1,30 @@ +package week04.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(); + + } +} diff --git a/group01/1298552064/src/week04/test/LRUPageFrameTest.java b/group01/1298552064/src/week04/test/LRUPageFrameTest.java new file mode 100644 index 0000000000..6fbf3ddef9 --- /dev/null +++ b/group01/1298552064/src/week04/test/LRUPageFrameTest.java @@ -0,0 +1,29 @@ +package week04.test; + +import org.junit.Assert; +import org.junit.Test; + +import week04.lru.LRUPageFrame; + +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/group01/1814014897/zhouhui/.classpath b/group01/1814014897/zhouhui/.classpath index 373dce4005..fd40ed3fdb 100644 --- a/group01/1814014897/zhouhui/.classpath +++ b/group01/1814014897/zhouhui/.classpath @@ -3,5 +3,7 @@ + + diff --git a/group01/1814014897/zhouhui/src/week05/jvm/clz/AccessFlag.java b/group01/1814014897/zhouhui/src/week05/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..b843c8917e --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package week05.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/week05/jvm/clz/ClassFile.java b/group01/1814014897/zhouhui/src/week05/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..3969967b24 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/clz/ClassFile.java @@ -0,0 +1,75 @@ +package week05.jvm.clz; + +import week05.jvm.constant.ClassInfo; +import week05.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/group01/1814014897/zhouhui/src/week05/jvm/clz/ClassIndex.java b/group01/1814014897/zhouhui/src/week05/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..31fb6f9eea --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package week05.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/week05/jvm/constant/ClassInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..6756c37efa --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..91db6cd7ee --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantPool.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..352b55bc23 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/FieldRefInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..4827d6d90a --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/MethodRefInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..d310854127 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/NameAndTypeInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..aaa5022dc3 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/NullConstantInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..d2ec4edcee --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package week05.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group01/1814014897/zhouhui/src/week05/jvm/constant/StringInfo.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..602a2948b1 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/constant/UTF8Info.java b/group01/1814014897/zhouhui/src/week05/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..d3fc7f9303 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package week05.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/group01/1814014897/zhouhui/src/week05/jvm/loader/ByteCodeIterator.java b/group01/1814014897/zhouhui/src/week05/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..76a6adeb8b --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,37 @@ +package week05.jvm.loader; + +import java.util.Arrays; + +import week05.jvm.util.Util; + +public class ByteCodeIterator { + byte[] codes; + int pos = 0; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public int nextU1ToInt() { + return Util.byteToInt(new byte[]{codes[pos++]}); + } + + public int nextU2ToInt() { + return Util.byteToInt(new byte[]{codes[pos++],codes[pos++]}); + } + + public String nextU4ToHexString() { + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + + 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; + } + +} diff --git a/group01/1814014897/zhouhui/src/week05/jvm/loader/ClassFileLoader.java b/group01/1814014897/zhouhui/src/week05/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f4561d2603 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/loader/ClassFileLoader.java @@ -0,0 +1,134 @@ +package week05.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 week05.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/group01/1814014897/zhouhui/src/week05/jvm/test/EmployeeV1.java b/group01/1814014897/zhouhui/src/week05/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..e86ea0ce81 --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package week05.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/week05/jvm/util/Util.java b/group01/1814014897/zhouhui/src/week05/jvm/util/Util.java new file mode 100644 index 0000000000..830e6bc26d --- /dev/null +++ b/group01/1814014897/zhouhui/src/week05/jvm/util/Util.java @@ -0,0 +1,24 @@ +package week05.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() || len <= 0) return null; + + Object[] result = new Object[len]; + for(int i=0;i=0;i--){ + s.push(result[i]); + } + + 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) { + char[] arr = s.toCharArray(); + + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + for(int i=arr.length-1;i>=0;i--){ + s1.push(arr[i]); + } + + for(int i=0;i=1;i--){ + Assert.assertEquals(i, s.pop()); + } + } + + @Test + public void testIsValidPairs() { + String s1 = "([e{d}f])"; + String s2 = "([b{x]y})"; + + Assert.assertTrue(StackUtil.isValidPairs(s1)); + Assert.assertFalse(StackUtil.isValidPairs(s2)); + } + +} diff --git a/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/StackUtil.java b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/StackUtil.java new file mode 100644 index 0000000000..99d9e1cb6d --- /dev/null +++ b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/StackUtil.java @@ -0,0 +1,122 @@ +package com.coding2017.basic.stack; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import java.util.Map; +import java.util.Set; +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; + } + + Stack tempStack = new Stack(); + Integer bottom = null; // 到什么元素为止 + Integer temp; + + while (!reachBottom(s, bottom)) { + temp = (Integer) s.pop(); + while (!reachBottom(s, bottom)) { + tempStack.push(s.pop()); + } + s.push(temp); + while (!tempStack.isEmpty()) { + s.push(tempStack.pop()); + } + bottom = temp; + } + } + + private static boolean reachBottom(Stack stack, Integer bottom) { + return stack.isEmpty() || stack.peek() == bottom; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack tempStack = new Stack(); + while (!s.isEmpty()) { + if (s.peek().equals(o)) { + s.pop(); + break; + } + tempStack.push(s.pop()); + } + while (!tempStack.isEmpty()) { + s.push(tempStack.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + Object[] result = new Object[len]; + Stack tempStack = new Stack(); + for (int i = 0; i < len; i++) { + if (s.isEmpty()) { + break; + } + result[i] = s.peek(); + tempStack.push(s.pop()); + } + while (!tempStack.isEmpty()) { + s.push(tempStack.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 < s.length(); i++) { + char c = s.charAt(i); + if (isRightBracket(c)) { + if (stack.isEmpty() || !isMatchBracket(stack.pop(), c)) { + return false; + } + } else if (isLeftBracket(c)) { + stack.push(c); + } + } + + return stack.isEmpty(); + } + + private static boolean isLeftBracket(Character character) { + final Set leftBrackets = ImmutableSet.copyOf(new Character[] { '(', '[', '{' }); + return leftBrackets.contains(character); + } + + private static boolean isRightBracket(Character character) { + final Set rightBrackets = ImmutableSet.copyOf(new Character[] { ')', ']', '}' }); + return rightBrackets.contains(character); + } + + private static boolean isMatchBracket(Character left, Character right) { + final Map bracketMap = ImmutableMap. builder().put(')', '(') + .put(']', '[').put('}', '{').build(); + return left.equals(bracketMap.get(right)); + } + +} diff --git a/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..0f95b519dd --- /dev/null +++ b/group01/280646174/basic/src/main/java/com/coding2017/basic/stack/expr/InfixExpr.java @@ -0,0 +1,18 @@ +package com.coding2017.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/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/StackUtilTest.java b/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..d25e7aee3d --- /dev/null +++ b/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/StackUtilTest.java @@ -0,0 +1,52 @@ +package com.coding2017.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Stack; + +import static org.junit.Assert.*; + +/** + * Created by kaitao.li on 2017/4/15. + */ +public class StackUtilTest { + + private Stack mockStack() { + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + return s; + } + + @Test + public void testReverse() { + Stack s = mockStack(); + StackUtil.reverse(s); + Assert.assertArrayEquals(s.toArray(), new Integer[] { 5, 4, 3, 2, 1 }); + } + + @Test + public void testRemove() { + Stack s = mockStack(); + StackUtil.remove(s, 3); + Assert.assertArrayEquals(s.toArray(), new Integer[] {1, 2, 4, 5}); + } + + @Test + public void testGetTop() { + Stack s = mockStack(); + Object[] top = StackUtil.getTop(s, 2); + Assert.assertArrayEquals(s.toArray(), new Integer[]{1, 2, 3, 4, 5}); + Assert.assertArrayEquals(top, new Integer[] {5, 4}); + } + + @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/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/expr/InfixExprTest.java b/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..0ded3f2a95 --- /dev/null +++ b/group01/280646174/basic/src/test/java/com/coding2017/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,51 @@ +package com.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by kaitao.li on 2017/4/15. + */ +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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java new file mode 100644 index 0000000000..4fdddbb2eb --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/bean/EmployeeV1.java @@ -0,0 +1,30 @@ +package com.coding2017.jvm.bean; + +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/280646174/jvm/src/main/java/com/coding2017/jvm/clz/AccessFlag.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..b2d58a1b50 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/AccessFlag.java @@ -0,0 +1,26 @@ +package com.coding2017.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/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..19c738f8d4 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassFile.java @@ -0,0 +1,77 @@ +package com.coding2017.jvm.clz; + +import com.coding2017.jvm.constant.ClassInfo; +import com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassIndex.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..2844afe494 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +package com.coding2017.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/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ClassInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e87c283295 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..9acf6d70fa --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantInfo.java @@ -0,0 +1,31 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantPool.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..61f8f8d5ba --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/ConstantPool.java @@ -0,0 +1,31 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/FieldRefInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..4f440c59d5 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/MethodRefInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..091bb4a5d3 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/MethodRefInfo.java @@ -0,0 +1,57 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NameAndTypeInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..cda8ec8cd4 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,48 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NullConstantInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..7ce288e868 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package com.coding2017.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/StringInfo.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6408f56b0a --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/StringInfo.java @@ -0,0 +1,27 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/UTF8Info.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..93bdd6f231 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/constant/UTF8Info.java @@ -0,0 +1,37 @@ +package com.coding2017.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/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..566b251c32 --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,38 @@ +package com.coding2017.jvm.loader; + +import com.coding2017.jvm.util.ByteUtil; + +public class ByteCodeIterator { + + private byte[] data; + private int pos; + + public ByteCodeIterator(byte[] data) { + this.data = data; + pos = 0; + } + + public void skip(int n) { + pos += n; + } + + public int nextU1ToInt() { + return nextByteN(1)[0]; + } + + public int nextU2ToInt() { + return ByteUtil.bytesToInt(nextByteN(2)); + } + + public String nextU4ToString() { + return ByteUtil.byteToHexString(nextByteN(4)); + } + + public byte[] nextByteN(int n) { + byte[] bytes = new byte[n]; + for (int i = 0; i < n; i++) { + bytes[i] = data[pos++]; + } + return bytes; + } +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileLoader.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..74796fbbcf --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileLoader.java @@ -0,0 +1,81 @@ +package com.coding2017.jvm.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.coding2017.jvm.clz.ClassFile; +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; + +public class ClassFileLoader { + private static Joiner SEMICOLON_JOINER = Joiner.on(";").skipNulls(); + private static Splitter DOT_SPLITTER = Splitter.on(".").trimResults(); + private static Joiner SLASH_JOINER = Joiner.on("/").skipNulls(); + + private static String CLASS_SUFFIX = ".class"; + + private List 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); + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..ff21b4fa0c --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/loader/ClassFileParser.java @@ -0,0 +1,99 @@ +package com.coding2017.jvm.loader; + +import com.coding2017.jvm.clz.AccessFlag; +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.jvm.clz.ClassIndex; +import com.coding2017.jvm.constant.*; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + boolean check = checkMagicNumber(iterator); + if (!check) { + System.out.println("不是标准class文件, magic number不正确"); + return null; + } + + // 版本号 + classFile.setMinorVersion(iterator.nextU2ToInt()); + classFile.setMajorVersion(iterator.nextU2ToInt()); + + // 常量池 + classFile.setConstPool(parseConstantPool(iterator)); + + // 访问标志 + classFile.setAccessFlag(parseAccessFlag(iterator)); + + // this class and super class + classFile.setClassIndex(parseClassInfex(iterator)); + + return classFile; + } + + private boolean checkMagicNumber(ByteCodeIterator iterator) { + String magicNumber = iterator.nextU4ToString(); + return "cafebabe".equals(magicNumber); + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextU2ToInt()); + classIndex.setSuperClassIndex(iter.nextU2ToInt()); + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + ConstantPool constantPool = new ConstantPool(); + int constantCount = iter.nextU2ToInt(); + constantPool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i < constantCount; i++) { + constantPool.addConstantInfo(parseConstantInfo(constantPool, iter)); + } + return constantPool; + } + + private ConstantInfo parseConstantInfo(ConstantPool constantPool, ByteCodeIterator iterator) { + int tag = iterator.nextU1ToInt(); + if (tag == ConstantInfo.UTF8_INFO) { + UTF8Info utf8Info = new UTF8Info(constantPool); + utf8Info.setLength(iterator.nextU2ToInt()); + utf8Info.setValue(new String(iterator.nextByteN(utf8Info.getLength()))); + return utf8Info; + } else if (tag == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(iterator.nextU2ToInt()); + return classInfo; + } else if (tag == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(iterator.nextU2ToInt()); + return stringInfo; + } else if (tag == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + return fieldRefInfo; + } else if (tag == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(iterator.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iterator.nextU2ToInt()); + return methodRefInfo; + } else if (tag == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(iterator.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iterator.nextU2ToInt()); + return nameAndTypeInfo; + } else { + throw new RuntimeException("not support tag " + tag); + } + } + +} diff --git a/group01/280646174/jvm/src/main/java/com/coding2017/jvm/util/ByteUtil.java b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/util/ByteUtil.java new file mode 100644 index 0000000000..f1f3ec883f --- /dev/null +++ b/group01/280646174/jvm/src/main/java/com/coding2017/jvm/util/ByteUtil.java @@ -0,0 +1,29 @@ +package com.coding2017.jvm.util; + +/** + * Created by kaitao.li on 2017/4/16. + */ +public class ByteUtil { + + public static int bytesToInt(byte[] data) { + int result = 0; + for (int i = 0; i < data.length; i++) { + result = result * 256 + data[i]; + } + return result; + } + + 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/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java new file mode 100644 index 0000000000..c25f6f2c0f --- /dev/null +++ b/group01/280646174/jvm/src/test/java/com/coding2017/jvm/loader/ClassFileLoaderTest.java @@ -0,0 +1,189 @@ +package com.coding2017.jvm.loader; + +import com.coding2017.jvm.clz.ClassFile; +import com.coding2017.jvm.clz.ClassIndex; +import com.coding2017.jvm.constant.*; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by kaitao.li on 2017/4/16. + */ +public class ClassFileLoaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "/Users/kaitao.li/code/study/coding2017/group01/280646174/jvm/target/classes"; + 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(1056, byteCodes.length); + + } + + @Test + public void testMagicNumber() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coding2017.week4.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()); + } + +} \ No newline at end of file diff --git a/group01/280646174/pom.xml b/group01/280646174/pom.xml index 75422ec638..cf3eefc767 100644 --- a/group01/280646174/pom.xml +++ b/group01/280646174/pom.xml @@ -10,6 +10,7 @@ 1.0-SNAPSHOT basic + jvm @@ -46,4 +47,17 @@ + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/group01/349209948/src/week2_0305/array/ArrayUtil.java b/group01/349209948/src/week2_0305/array/ArrayUtil.java new file mode 100644 index 0000000000..3158becf66 --- /dev/null +++ b/group01/349209948/src/week2_0305/array/ArrayUtil.java @@ -0,0 +1,246 @@ +package week2_0305.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) { + throw new IllegalArgumentException(); + } + int temp = 0; + for (int i = 0; i< origin.length/2; i++) { + temp = origin[i]; + origin[i] = origin[origin.length - i]; + origin[origin.length - 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) { + throw new IllegalArgumentException(); + } + int[] newArray = new int[oldArray.length]; + int index = 0; + for (int i =0; i < oldArray.length; i ++){ + if (oldArray[i] == 0) { + continue; + } else { + newArray[index++] = oldArray[i]; + } + } + return 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] , 注意: 已经消除了重复 + * @param array1 + * @param array2 + * @return + */ + + public int[] merge(int[] array1, int[] array2){ + if (array1 == null || array2 == null) { + throw new IllegalArgumentException(); + } + int[] array3 = new int[array1.length + array2.length]; + int index1 = 0; + int index2 = 0; + int actualSize = 0; + for (int i = 0; i < array3.length; i ++) { + //把array2剩余的部分拷入数据 + if (index1 >= array1.length) { + arrayCopy(array2, index2, array3, i, array2.length - index2); + actualSize = i + array2.length - index2; + return copyOf(array3, actualSize); + } + if (index2 >= array2.length) { + arrayCopy(array1, index1, array3, i, array1.length - index1); + actualSize = i + array1.length - index1; + return copyOf(array3, actualSize); + } + if (array1[index1] < array2[index2]) { + array3[i] = array1[index1]; + index1 ++; + } else if (array1[index1] == array2[index2]) { + array3[i] = array1[index1]; + index1 ++; + index2 ++; + } else { + array3[i] = array2[index2]; + index2 ++; + } + } + // array1 he array2 均为 空数组的情况 + return new int[0]; + } + + private void arrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length) { + for (int i = 0; i< length; i++) { + dest[destPos++] = src[srcPos++]; + } + } + + private int[] copyOf(int[] arr, int size) { + int[] dest = new int[size]; + for (int i = 0; i< size; i++) { + dest[i] = arr[i]; + } + return dest; + } + /** + * 把一个已经存满数据的数组 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 || size <0) { + throw new IllegalArgumentException(); + } + 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 int[] fibonacci(int max){ + if (max < 0 ) { + throw new IllegalArgumentException(); + } else if (max == 1) { + return new int[0]; + } + ArrayList list = new ArrayList(); + list.add(1); + list.add(1); + int i = 0; + while(true) { + int num = (int)list.get(i) + (int)list.get(i+1); + if (num < max) { + list.add(num); + } else { + break; + } + } + return listToArray(list); + } + + private int[] listToArray(ArrayList list){ + int[] arr = new int[list.size()]; + for (int i = 0;i < list.size(); i++) { + arr[i] = (int)list.get(i); + } + return arr; + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + if (max <2) { + throw new IllegalArgumentException(); + } + ArrayList list = new ArrayList(); + for (int i = 2; i < max; i++) { + if (isPrime(i)) { + list.add(i); + } + } + return listToArray(list); + } + + public boolean isPrime(int m) { + for (int i = 1; i < m/2; i++) { + if (m % 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 IllegalArgumentException(); + } + ArrayList list = new ArrayList(); + for (int i = 0; i< max; i++) { + if (isPerfectNumber(i)) { + list.add(i); + } + } + return listToArray(list); + } + + public boolean isPerfectNumber(int num) { + int sum = 0; + for (int i = 0; i < num; i++) { + if (num % i == 0) { + sum += i; + } + } + if (sum == 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) { + throw new IllegalArgumentException(); + } + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + builder.append(array[i]).append(seperator); + } + return builder.substring(0, builder.length() - seperator.length()); + } + + +} diff --git a/group01/349209948/src/week2_0305/litestruts/Configuration.java b/group01/349209948/src/week2_0305/litestruts/Configuration.java new file mode 100644 index 0000000000..a10ac1cef9 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/Configuration.java @@ -0,0 +1,95 @@ +package week2_0305.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; +import week2_0305.litestruts.ConfigurationException;; + +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 (IOException e) { + throw new ConfigurationException(e); + } catch (JDOMException 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 actionName, String resultName) { + ActionConfig ac = this.actions.get(actionName); + 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 this.clzName; + } + + public void addViewResult(String name, String viewName) { + viewResult.put(name, viewName); + } + + public String getViewName(String resultName) { + return viewResult.get(resultName); + } + } +} diff --git a/group01/349209948/src/week2_0305/litestruts/ConfigurationException.java b/group01/349209948/src/week2_0305/litestruts/ConfigurationException.java new file mode 100644 index 0000000000..d80baae668 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/ConfigurationException.java @@ -0,0 +1,18 @@ +package week2_0305.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/group01/349209948/src/week2_0305/litestruts/ConfigurationTest.java b/group01/349209948/src/week2_0305/litestruts/ConfigurationTest.java new file mode 100644 index 0000000000..3c2bf82ecc --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/ConfigurationTest.java @@ -0,0 +1,51 @@ +package week2_0305.litestruts; + +import week2_0305.litestruts.Configuration; + +import org.junit.Assert; +import org.junit.Test; + +public class ConfigurationTest { + + Configuration cfg = new Configuration("struts.xml"); + + @Test + public void testGetClassName() { + String clzName = cfg.getClassName("login"); + Assert.assertEquals("week2_0305.litestruts.LoginAction", clzName); + clzName = cfg.getClassName("logout"); + Assert.assertEquals("week2_0305.litestruts.LogoutAction", clzName); + } + @Test + public void testGetFileName() { + String packageName = this.getClass().getPackage().getName(); + packageName = packageName.replace('.', '/'); + packageName = "/" + packageName + "/" + "struts.xml"; + Assert.assertEquals("/week2_0305/litestruts/struts.xml", packageName); + } + + @Test + public void testGetResultView() { + String actionName = "login"; + String resultName = "success"; + String viewName = cfg.getResultView(actionName, resultName); + Assert.assertEquals("/jsp/homepage.jsp", viewName); + + actionName = "login"; + resultName = "fail"; + viewName = cfg.getResultView(actionName, resultName); + Assert.assertEquals("/jsp/showLogin.jsp", viewName); + + actionName = "logout"; + resultName = "success"; + viewName = cfg.getResultView(actionName, resultName); + Assert.assertEquals("/jsp/welcome.jsp", viewName); + + actionName = "logout"; + resultName = "error"; + viewName = cfg.getResultView(actionName, resultName); + Assert.assertEquals("/jsp/error.jsp", viewName); + + } + +} diff --git a/group01/349209948/src/week2_0305/litestruts/LoginAction.java b/group01/349209948/src/week2_0305/litestruts/LoginAction.java new file mode 100644 index 0000000000..ed666b6645 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package week2_0305.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/group01/349209948/src/week2_0305/litestruts/ReflectionUtil.java b/group01/349209948/src/week2_0305/litestruts/ReflectionUtil.java new file mode 100644 index 0000000000..a670d6df04 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/ReflectionUtil.java @@ -0,0 +1,74 @@ +package week2_0305.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) { + List methods = new ArrayList<>(); + for (Method m : clz.getDeclaredMethods()) { + if (m.getName().startsWith("set")) { + methods.add(m); + } + } + return methods; + } + + public static List getGetterMethods(Class clz) { + List methods = new ArrayList(); + for (Method m : clz.getDeclaredMethods()) { + if (m.getName().startsWith("get")) { + methods.add(m); + } + } + return methods; + } + + public 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 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 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; + } + +} diff --git a/group01/349209948/src/week2_0305/litestruts/ReflectionUtilTest.java b/group01/349209948/src/week2_0305/litestruts/ReflectionUtilTest.java new file mode 100644 index 0000000000..242487da60 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/ReflectionUtilTest.java @@ -0,0 +1,130 @@ +package week2_0305.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.Assert; +import org.junit.Test; + +public class ReflectionUtilTest { + + @Test + public void testGetSetterMethod() throws Exception{ + String name = "week2_0305.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getSetterMethods(clz); + + Assert.assertEquals(2, methods.size()); + + List expectNames = new ArrayList<>(); + expectNames.add("setName"); + expectNames.add("setPassword"); + + Set actualNames = new HashSet<>(); + for(Method m : methods) { + actualNames.add(m.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectNames)); + } + + @Test + public void testSetParameters() throws Exception{ + String name = "week2_0305.litestruts.LoginAction"; + Class clz = Class.forName(name); + Object o = clz.newInstance(); + + Map params = new HashMap(); + params.put("name", "test"); + params.put("password", "123456"); + + 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("123456", f.get(o)); + } + + @Test + public void testGetGetterMethod() throws Exception{ + String name = "week2_0305.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getGetterMethods(clz); + + Assert.assertEquals(3, methods.size()); + List expectNames = new ArrayList<>(); + expectNames.add("getName"); + expectNames.add("getPassword"); + expectNames.add("getMessage"); + + Set actualNames = new HashSet<>(); + + for(Method m : methods) { + actualNames.add(m.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectNames)); + + } + + @Test + public void testGetMethods() throws Exception{ + String name = "week2_0305.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getMethods(clz, "get"); + + Assert.assertEquals(3, methods.size()); + List expectNames = new ArrayList<>(); + expectNames.add("getName"); + expectNames.add("getPassword"); + expectNames.add("getMessage"); + + Set actualNames = new HashSet<>(); + + for(Method m : methods) { + actualNames.add(m.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectNames)); + + methods = ReflectionUtil.getMethods(clz, "set"); + + Assert.assertEquals(2, methods.size()); + + expectNames = new ArrayList<>(); + expectNames.add("setName"); + expectNames.add("setPassword"); + + actualNames = new HashSet<>(); + for(Method m : methods) { + actualNames.add(m.getName()); + } + Assert.assertTrue(actualNames.containsAll(expectNames)); + } + + @Test + public void testGetParameters() throws Exception{ + String name = "week2_0305.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("message")); + Assert.assertEquals("test", params.get("name")); + Assert.assertEquals("123456", params.get("password")); + + } + +} diff --git a/group01/349209948/src/week2_0305/litestruts/Struts.java b/group01/349209948/src/week2_0305/litestruts/Struts.java new file mode 100644 index 0000000000..4b97a947c1 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/Struts.java @@ -0,0 +1,55 @@ +package week2_0305.litestruts; + +import java.lang.reflect.InvocationTargetException; +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) { + + /* + + 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字段中。 + + */ + String clzName = cfg.getClassName(actionName); + + 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); + String jsp = cfg.getResultView(actionName, resultName); + Map params = ReflectionUtil.getParamterMap(action); + View view = new View(); + view.setJsp(jsp); + view.setParameters(params); + return view; + + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + +} diff --git a/group01/349209948/src/week2_0305/litestruts/StrutsTest.java b/group01/349209948/src/week2_0305/litestruts/StrutsTest.java new file mode 100644 index 0000000000..3b4ce1d7d1 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/StrutsTest.java @@ -0,0 +1,43 @@ +package week2_0305.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/group01/349209948/src/week2_0305/litestruts/View.java b/group01/349209948/src/week2_0305/litestruts/View.java new file mode 100644 index 0000000000..a414cad3e5 --- /dev/null +++ b/group01/349209948/src/week2_0305/litestruts/View.java @@ -0,0 +1,23 @@ +package week2_0305.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/group01/765324639/pom.xml b/group01/765324639/pom.xml new file mode 100644 index 0000000000..24816f0f3f --- /dev/null +++ b/group01/765324639/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + com.zavier + 765324639Learning + 0.0.1-SNAPSHOT + + + junit + junit + 4.12 + + + dom4j + dom4j + 1.6.1 + + + \ No newline at end of file diff --git a/group01/765324639/src/main/java/datastructure/BinaryTreeNode.java b/group01/765324639/src/main/java/datastructure/BinaryTreeNode.java new file mode 100644 index 0000000000..20d0734f11 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/BinaryTreeNode.java @@ -0,0 +1,63 @@ +package datastructure; + +public class BinaryTreeNode { + + private Integer data; + private BinaryTreeNode left; + private BinaryTreeNode right; + + public BinaryTreeNode(Integer data) { + this.data = data; + } + + public Integer 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 > this.data) { + + if (this.getRight() == null) { + BinaryTreeNode node = new BinaryTreeNode(o); + this.setRight(node); + return node; + } else { + return this.getRight().insert(o); + } + + } else { + + if (this.getLeft() == null) { + BinaryTreeNode node = new BinaryTreeNode(o); + this.setLeft(node); + return node; + } else { + return this.getLeft().insert(o); + } + + } + + } + +} diff --git a/group01/765324639/src/main/java/datastructure/Iterator.java b/group01/765324639/src/main/java/datastructure/Iterator.java new file mode 100644 index 0000000000..ae54040424 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/Iterator.java @@ -0,0 +1,8 @@ +package datastructure; + +public interface Iterator { + public boolean hasNext(); + + public Object next(); + +} diff --git a/group01/765324639/src/main/java/datastructure/List.java b/group01/765324639/src/main/java/datastructure/List.java new file mode 100644 index 0000000000..507cca34a8 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/List.java @@ -0,0 +1,13 @@ +package 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/group01/765324639/src/main/java/datastructure/Queue.java b/group01/765324639/src/main/java/datastructure/Queue.java new file mode 100644 index 0000000000..d4cfec525e --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/Queue.java @@ -0,0 +1,27 @@ +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/array/ArrayList.java b/group01/765324639/src/main/java/datastructure/array/ArrayList.java new file mode 100644 index 0000000000..a4b4182226 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/array/ArrayList.java @@ -0,0 +1,88 @@ +package datastructure.array; + +import java.util.Arrays; + +import datastructure.Iterator; +import datastructure.List; + +public class ArrayList implements List { + + private int size = 0; + + private Object[] elementData = new Object[100]; + + @Override + public void add(Object o) { + ensureCapacity(size + 1); + elementData[size++] = o; + } + + private void ensureCapacity(int size) { + if (size > elementData.length) { + grow(); + } + } + + private void grow() { + elementData = Arrays.copyOf(elementData, size * 2); + } + + @Override + public void add(int index, Object o) { + rangeCheckForAdd(index); + ensureCapacity(size + 1); + System.arraycopy(elementData, index, elementData, index + 1, size - index); + elementData[index] = o; + size++; + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(); + } + } + + @Override + public Object get(int index) { + rangeCheck(index); + return elementData[index]; + } + + private void rangeCheck(int index) { + if (index >= size || index < 0) { + throw new IndexOutOfBoundsException(); + } + } + + @Override + public Object remove(int index) { + rangeCheck(index); + Object dest = elementData[index]; + System.arraycopy(elementData, index + 1, elementData, index, size - index - 1); + size--; + return dest; + } + + @Override + public int size() { + return size; + } + + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + @Override + public Object next() { + return elementData[index++]; + } + + @Override + public boolean hasNext() { + return index < size; + } + }; + } + +} diff --git a/group01/765324639/src/main/java/datastructure/array/ArrayUtil.java b/group01/765324639/src/main/java/datastructure/array/ArrayUtil.java new file mode 100644 index 0000000000..74040ccbe0 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/array/ArrayUtil.java @@ -0,0 +1,262 @@ +package datastructure.array; + +import datastructure.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) { + if (origin == null) { + throw new IllegalArgumentException(); + } + + int temp; + for (int i = 0; i < origin.length / 2; i++) { + 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) { + throw new IllegalArgumentException(); + } + + int[] noZeroArray = new int[oldArray.length]; + int index = 0; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + noZeroArray[index++] = oldArray[i]; + } + } + + return copyOf(noZeroArray, index); + } + + /** + * 给定两个已经排序好的整形数组, 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) { + throw new IllegalArgumentException(); + } + + int indexOfArray1 = 0; + int indexOfArray2 = 0; + int totalLength = array1.length + array2.length; + int[] destArr = new int[totalLength]; + + for (int i = 0; i < totalLength; i++) { + if (indexOfArray1 >= array1.length) { + // array1填充完毕,将array2填充剩下的元素 + arrayCopy(array2, indexOfArray2, destArr, i, array2.length - indexOfArray2); + int actualSize = i + array2.length - indexOfArray2; + return copyOf(destArr, actualSize); + } + + if (indexOfArray2 >= array2.length) { + arrayCopy(array1, indexOfArray1, destArr, i, array1.length - indexOfArray1); + int actualSize = i + array1.length - indexOfArray1; + return copyOf(destArr, actualSize); + } + + if (array1[indexOfArray1] < array2[indexOfArray2]) { + destArr[i] = array1[indexOfArray1]; + indexOfArray1++; + } else if (array1[indexOfArray1] == array2[indexOfArray2]) { + destArr[i] = array1[indexOfArray1]; + indexOfArray1++; + indexOfArray2++; // 去除重复元素 + } else { + destArr[i] = array2[indexOfArray2]; + indexOfArray2++; + } + + } + // array1.length、array2.length均为0的情况 + return new int[0]; + } + + private void arrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length) { + for (int i = 0; i < length; i++) { + dest[destPos++] = src[srcPos++]; + } + } + + private int[] copyOf(int[] original, int newLength) { + int[] dest = new int[newLength]; + for (int i = 0; i < newLength; i++) { + dest[i] = original[i]; + } + return dest; + } + + /** + * 把一个已经存满数据的数组 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 || size < 0) { + throw new IllegalArgumentException(); + } + + int newSize = oldArray.length + size; + int[] newArray = new int[newSize]; + 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 int[] fibonacci(int max) { + if (max < 0) { + throw new IllegalArgumentException(); + } + if (max == 1) { + return new int[] {}; + } + + ArrayList list = new ArrayList(); + list.add(1); + list.add(1); + + int i = 0; + while (true) { + int num = (int) list.get(i) + (int) list.get(i + 1); + if (num < max) { + list.add(num); + } else { + break; + } + i++; + } + + return intListToArray(list); + } + + private int[] intListToArray(List list) { + int[] array = new int[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = (int) list.get(i); + } + return array; + } + + /** + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public int[] getPrimes(int max) { + if (max < 0) { + throw new IllegalArgumentException(); + } + + ArrayList list = new ArrayList(); + for (int i = 2; i < max; i++) { + if (isPrime(i)) { + list.add(i); + } + } + return intListToArray(list); + } + + private boolean isPrime(int num) { + 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) { + throw new IllegalArgumentException(); + } + + ArrayList list = new ArrayList(); + for (int i = 2; i < max; i++) { + if (isPerfectNumber(i)) { + list.add(i); + } + } + return intListToArray(list); + } + + private boolean isPerfectNumber(int num) { + int sumOfFactor = 1; + for (int i = 2; i <= num / 2; i++) { + if (num % i == 0) { + sumOfFactor += i; + } + } + if (sumOfFactor == num) { + return true; + } + 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) { + throw new IllegalArgumentException(); + } + if (array.length == 0) { + return ""; + } + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + builder.append(array[i]).append(seperator); + } + return builder.substring(0, builder.length() - seperator.length()); + } + + +} diff --git a/group01/765324639/src/main/java/datastructure/linkedlist/LRUPageFrame.java b/group01/765324639/src/main/java/datastructure/linkedlist/LRUPageFrame.java new file mode 100644 index 0000000000..cc4771562d --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/linkedlist/LRUPageFrame.java @@ -0,0 +1,177 @@ +package datastructure.linkedlist; + +/** + * 用双向链表实现LRU算法 + * + * @author liuxin + * + */ +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; + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + if (isEmpty()) { + initFirstNode(pageNum); + return; + } + + if (contains(pageNum)) { + moveToFirst(pageNum); + } else { + insert(pageNum); + } + } + + private void initFirstNode(int pageNum) { + Node node = new Node(pageNum); + first = last = node; + size++; + } + + private void moveToFirst(int pageNum) { + if (isFirst(pageNum)) { + return; + } + if (isLast(pageNum)) { + moveLastToFirst(); + } else { + moveMidToFirst(pageNum); + } + } + + private void moveLastToFirst() { + Node temp = last; + + removeLast(); + + addToFirst(temp); + } + + private void addToFirst(Node temp) { + temp.next = first; + first.prev = temp; + first = temp; + size++; + } + + private void moveMidToFirst(int pageNum) { + Node node = removeMidNode(pageNum); + addToFirst(node); + } + + private Node removeMidNode(int pageNum) { + Node temp = getNode(pageNum); + temp.prev.next = temp.next; + temp.next.prev = temp.prev; + + temp.next = null; + temp.prev = null; + + size--; + + return temp; + } + + private void insert(int pageNum) { + if (isFill()) { + removeLast(); + } + insertToFirst(pageNum); + } + + private void removeLast() { + last = last.prev; + last.next = null; + size--; + } + + private void insertToFirst(int pageNum) { + Node node = new Node(pageNum); + + addToFirst(node); + } + + private boolean contains(int pageNum) { + return indexOf(pageNum) != -1; + } + + private int indexOf(int num) { + Node temp = first; + for (int i = 0; i < size; i++) { + if (temp.pageNum == num) { + return i; + } + temp = temp.next; + } + return -1; + } + + private Node getNode(int pageNum) { + Node temp; + temp = first; + for (int i = 0; i < size; i++) { + if (temp.pageNum == pageNum) { + break; + } + temp = temp.next; + } + return temp; + } + + private boolean isEmpty() { + return size == 0; + } + + private boolean isFirst(int pageNum) { + return first.pageNum == pageNum; + } + + private boolean isLast(int pageNum) { + return last.pageNum == pageNum; + } + + private boolean isFill() { + return size == capacity; + } + + @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/group01/765324639/src/main/java/datastructure/linkedlist/LinkedList.java b/group01/765324639/src/main/java/datastructure/linkedlist/LinkedList.java new file mode 100644 index 0000000000..acdb3320d9 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/linkedlist/LinkedList.java @@ -0,0 +1,378 @@ +package datastructure.linkedlist; + +import java.util.NoSuchElementException; + +import datastructure.Iterator; +import datastructure.List; + +public class LinkedList implements List { + + private Node head; + + private int size = 0; + + @Override + public void add(Object o) { + if (head == null) { + head = new Node(o); + } else { + Node tail = head; + while (tail.next != null) { + tail = tail.next; + } + Node node = new Node(o); + + tail.next = node; + } + size++; + } + + @Override + public void add(int index, Object o) { + rangeCheckForAdd(index); + if (index == 0) { + Node node = new Node(o); + node.next = head; + head = node; + } else { + Node preDest = head; + for (int i = 0; i < index - 1; i++) { + preDest = preDest.next; + } + Node node = new Node(o); + node.next = preDest.next; + preDest.next = node; + } + + size++; + } + + private void rangeCheckForAdd(int index) { + if (index > size || index < 0) { + throw new IndexOutOfBoundsException(); + } + } + + @Override + public Object get(int index) { + rangeCheck(index); + + Node dest = head; + for (int i = 0; i < index; i++) { + dest = dest.next; + } + return dest.data; + } + + private void rangeCheck(int index) { + if (index >= size || index < 0) { + throw new IndexOutOfBoundsException(); + } + } + + @Override + public Object remove(int index) { + rangeCheck(index); + + Node preDest = head; + for (int i = 0; i < index - 1; i++) { + preDest = preDest.next; + } + Node dest = preDest.next; + preDest.next = dest.next; + + size--; + return dest.data; + } + + @Override + public int size() { + return size; + } + + public void addFirst(Object o) { + Node node = new Node(o); + node.next = head; + head = node; + size++; + } + + public void addLast(Object o) { + Node lastNode = head; + while (lastNode.next != null) { + lastNode = lastNode.next; + } + + Node node = new Node(o); + lastNode.next = node; + size++; + } + + public Object removeFirst() { + if (head == null) { + throw new NoSuchElementException(); + } + Node target = head; + head = head.next; + size--; + return target.data; + } + + public Object removeLast() { + if (head == null) { + throw new NoSuchElementException(); + } + + Node preDest = head; + while (preDest.next.next != null) { + preDest = preDest.next; + } + Node dest = preDest.next; + preDest.next = null; + + size--; + return dest.data; + } + + public Iterator iterator() { + return null; + } + + + private static class Node { + Object data; + Node next; + + Node(Object data) { + this.data = data; + next = null; + } + } + + // =========================第三周作业========================= + + /** + * 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node reverseNode = null; + while (head != null) { + Node temp = head; + head = head.next; + temp.next = reverseNode; + reverseNode = temp; + } + head = reverseNode; + } + + /** + * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int newStartIndex = size / 2; + for (int i = 0; i < newStartIndex; i++) { + head = head.next; + } + size = size - newStartIndex; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i < 0) { + throw new IllegalArgumentException(); + } + if (i + length >= size) { + length = size - i; + } + + if (i == 0) { + for (int j = 0; j < length; j++) { + head = head.next; + } + } else { + Node beforeRemoveStartNode = head; + for (int j = 0; j < i - 1; j++) { + beforeRemoveStartNode = beforeRemoveStartNode.next; + } + + Node removeEndNode = beforeRemoveStartNode; + for (int j = 0; j < length; j++) { + removeEndNode = removeEndNode.next; + } + + beforeRemoveStartNode.next = removeEndNode.next; + } + + 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) { + checkList(list); + + int[] dest = new int[list.size]; + int arrayNum = 0; + Node temp = head; + int n = (int) list.get(0); + for (int i = 0; i < n; i++) { + temp = temp.next; + } + dest[arrayNum++] = (int) temp.data; + + for (int i = 1; i < list.size; i++) { + int num = (int) list.get(i) - (int) list.get(i - 1); + for (int j = 0; j < num; j++) { + temp = temp.next; + } + dest[arrayNum++] = (int) temp.data; + } + return dest; + } + + private void checkList(LinkedList list) { + for (int i = 0; i < list.size; i++) { + if ((int) list.get(i) < 0 || (int) list.get(i) >= size) { + throw new IllegalArgumentException("list中的元素位置越界"); + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + if (list == null || list.size == 0 || this.size == 0) { + return; + } + + int thisIndex = 0; + int listIndex = 0; + Node temp = head; + while (true) { // 后续需要优化替换remove()方法 + if ((int) temp.data < (int) list.get(listIndex)) { + temp = temp.next; + thisIndex++; + } else if ((int) temp.data == (int) list.get(listIndex)) { + this.remove(thisIndex); + temp = temp.next; + thisIndex++; + listIndex++; + } else { + listIndex++; + } + + if (thisIndex >= this.size || listIndex >= list.size) { + break; + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + if (this.size == 0) { + return; + } + + Node subHead = head; + Node subTail = head; + + while (true) { + if (subTail == null) { + subHead.next = null; // 清除尾部重复的元素 + break; + } + if ((int) subTail.data == (int) subHead.data) { + if (!(subTail == subHead)) { // 判断两个指针是否指向同一个地方 + this.size--; + } + subTail = subTail.next; + } else { + subHead.next = subTail; + subHead = subHead.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + if (this.size == 0) { + return; + } + + if ((int) head.data > max) { + throw new IllegalArgumentException(); + } + + int length = 0; + Node subList = new Node(null); + Node temp = subList; + while (true) { + if (head == null) { + break; + } + if ((int) head.data <= min || (int) head.data >= max) { + temp.next = head; + temp = temp.next; + length++; + } + head = head.next; + } + temp.next = null; // 去掉尾部多余数据 + head = subList.next; + size = length; + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + if (this.size == 0 || list.size == 0) { + return null; + } + + Node tempHead = head; + int listIndex = 0; + + LinkedList newList = new LinkedList(); + while (true) { + if (tempHead == null || listIndex >= list.size) { + break; + } + + if ((int) tempHead.data < (int) list.get(listIndex)) { + tempHead = tempHead.next; + } else if ((int) tempHead.data > (int) list.get(listIndex)) { + listIndex++; + } else { + newList.add(tempHead.data); + + tempHead = tempHead.next; + listIndex++; + } + } + + return newList; + } +} diff --git a/group01/765324639/src/main/java/datastructure/stack/Stack.java b/group01/765324639/src/main/java/datastructure/stack/Stack.java new file mode 100644 index 0000000000..52d4f818e8 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/Stack.java @@ -0,0 +1,47 @@ +package datastructure.stack; + +import java.util.EmptyStackException; + +import datastructure.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o) { + elementData.add(o); + } + + public Object pop() { + if (elementData.size() == 0) { + throw new EmptyStackException(); + } + return elementData.remove(elementData.size() - 1); + } + + public Object peek() { + if (elementData.size() == 0) { + throw new EmptyStackException(); + } + return elementData.get(elementData.size() - 1); + } + + public boolean isEmpty() { + return elementData.size() == 0; + } + + public int size() { + return elementData.size(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + int i = 0; + for ( ; i < elementData.size() - 1; i++) { + builder.append(elementData.get(i) + ","); + } + builder.append(elementData.get(i)); + return builder.toString(); + } + +} diff --git a/group01/765324639/src/main/java/datastructure/stack/StackUtil.java b/group01/765324639/src/main/java/datastructure/stack/StackUtil.java new file mode 100644 index 0000000000..b45f90337d --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/StackUtil.java @@ -0,0 +1,110 @@ +package datastructure.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 temp1 = new Stack(); + while (!s.isEmpty()) { + temp1.push(s.pop()); + } + Stack temp2 = new Stack(); + 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 == null || s.isEmpty()) { + return; + } + + Stack temp = new Stack(); + while (!s.isEmpty()) { + int num = (int) s.pop(); + if (num != (int)o) { + temp.push(num); + } + } + 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 || s.isEmpty() || len < 0) { + return null; + } + + Stack temp = new Stack(); + int i = 0; + Object[] obj = new Object[len]; + while(!s.isEmpty() && i < len) { + temp.push(s.peek()); + obj[i++] = s.pop(); + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + return obj; + } + /** + * 字符串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) { + return false; + } + + Stack stack = new Stack(); + char[] charArray = s.toCharArray(); + for (int i = 0; i < charArray.length; i++) { + char c = charArray[i]; + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } else if (c == ')') { + if ('(' != (char)stack.pop()) { + return false; + } + } else if (c == ']') { + if ('[' != (char)stack.pop()) { + return false; + } + } else if (c == '}') { + if ('{' != (char)stack.pop()) { + return false; + } + } + } + return true; + } + + +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/InfixExpr.java b/group01/765324639/src/main/java/datastructure/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..febd242e75 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/InfixExpr.java @@ -0,0 +1,75 @@ +package datastructure.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(expr); + List tokenList = tokenParser.parse(); + + Stack operaStack = new Stack<>(); + Stack floatStack = new Stack<>(); + + for (int i = 0; i < tokenList.size(); i++) { + if (Token.OPERATOR.equals(tokenList.get(i).getType())) { + if (operaStack.isEmpty()) { + operaStack.push(tokenList.get(i)); + } else { + Token topToken = operaStack.peek(); + if (tokenList.get(i).comparePriority(topToken) > 0) { + operaStack.push(tokenList.get(i)); + } else { + float result = stackTopCalculate(operaStack, floatStack); + floatStack.push(result); + + i--; + } + } + } else { + floatStack.push(Float.valueOf(tokenList.get(i).getValue())); + } + } + while (!operaStack.empty()) { + float temp = stackTopCalculate(operaStack, floatStack); + floatStack.push(temp); + } + return floatStack.pop(); + } + + private float stackTopCalculate(Stack operaStack, Stack floatStack) { + String operator = operaStack.pop().getValue(); + float num2 = floatStack.pop(); + float num1 = floatStack.pop(); + float result = calculate(operator, num1, num2); + return result; + } + + private float calculate(String operator, float num1, float num2) { + float result = 0; + switch (operator.charAt(0)) { + case '+': + result = num1 + num2; + break; + case '-': + result = num1 - num2; + break; + case '*': + result = num1 * num2; + break; + case '/': + result = num1 / num2; + break; + default: + throw new IllegalArgumentException(); + } + return result; + } + +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/Token.java b/group01/765324639/src/main/java/datastructure/stack/expr/Token.java new file mode 100644 index 0000000000..44a019197d --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/Token.java @@ -0,0 +1,51 @@ +package datastructure.stack.expr; + +public class Token { + + public static final String NUMBER = "number"; + + public static final String OPERATOR = "operator"; + + private String type; + + private String value; + + public Token(String type, String value) { + this.type = type; + this.value = value; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public int comparePriority(Token token) { + String higherLevel = "*/"; + String lowerLevel = "+-"; + if (higherLevel.contains(token.getValue())) { + if (higherLevel.contains(this.value)) { + return 0; + } + return -1; + } else if (lowerLevel.contains(token.getValue())){ + if (lowerLevel.contains(this.value)) { + return 0; + } + return 1; + } else { + throw new RuntimeException("不支持的运算符"); + } + } +} diff --git a/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java b/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java new file mode 100644 index 0000000000..e1add57663 --- /dev/null +++ b/group01/765324639/src/main/java/datastructure/stack/expr/TokenParser.java @@ -0,0 +1,66 @@ +package datastructure.stack.expr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TokenParser { + + private String expr; + + private List tokenList = new ArrayList<>(); + + public TokenParser(String expr) { + this.expr = expr; + } + + public List parse() { + if (expr == null || "".equals(expr)) { + return Collections.emptyList(); + } + + char[] charArray = expr.toCharArray(); + for (int i = 0; i < charArray.length; i++) { + if (isNumber(charArray[i])) { + i = addFullNumber(charArray, i); + i--; + } else if (isOperator(charArray[i])) { + addOperator(charArray[i]); + } + } + return tokenList; + } + + private boolean isNumber(char c) { + String numbers = "0123456789"; + if (numbers.indexOf(c) != -1) { + return true; + } + return false; + } + + private boolean isOperator(char c) { + String supplyOperator = "+-*/"; + if (supplyOperator.indexOf(supplyOperator) != -1) { + return true; + } + return false; + } + + private int addFullNumber(char[] charArray, int i) { + StringBuilder builder = new StringBuilder(); + for (; i < charArray.length; i++) { + if (isNumber(charArray[i])) { + builder.append(charArray[i]); + } else { + break; + } + } + tokenList.add(new Token(Token.NUMBER, builder.toString())); + return i; + } + + private void addOperator(char c) { + tokenList.add(new Token(Token.OPERATOR, String.valueOf(c))); + } +} diff --git a/group01/765324639/src/main/java/download/DownloadThread.java b/group01/765324639/src/main/java/download/DownloadThread.java new file mode 100644 index 0000000000..88641b3741 --- /dev/null +++ b/group01/765324639/src/main/java/download/DownloadThread.java @@ -0,0 +1,45 @@ +package download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import 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; + + } + + @Override + public void run() { + System.out.println("start download:" + startPos + "~" + endPos); + byte[] data = new byte[endPos - startPos]; + try { + data = conn.read(startPos, endPos); + } catch (IOException e) { + e.printStackTrace(); + } + writeToFile(data); + } + + private void writeToFile(byte[] data) { + RandomAccessFile file; + try { + file = new RandomAccessFile("download20170311.jpg", "rw"); + file.seek(startPos); + file.write(data, 0, data.length); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/group01/765324639/src/main/java/download/FileDownloader.java b/group01/765324639/src/main/java/download/FileDownloader.java new file mode 100644 index 0000000000..91f972db71 --- /dev/null +++ b/group01/765324639/src/main/java/download/FileDownloader.java @@ -0,0 +1,100 @@ +package download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; +import 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 { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + createPlaceHolderFile("download20170311.jpg", length); + + DownloadThread downloadThread1 = new DownloadThread(cm.open(this.url), 0, length / 3); + downloadThread1.start(); + DownloadThread downloadThread2 = + new DownloadThread(cm.open(this.url), length / 3 + 1, length / 3 * 2); + downloadThread2.start(); + DownloadThread downloadThread3 = + new DownloadThread(cm.open(this.url), length / 3 * 2 + 1, length - 1); + downloadThread3.start(); + try { + downloadThread1.join(); + downloadThread2.join(); + downloadThread3.join(); + listener.notifyFinished(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } catch (ConnectionException e) { + e.printStackTrace(); + } catch (IOException e1) { + e1.printStackTrace(); + } finally { + if (conn != null) { + conn.close(); + } + } + + } + + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException { + + RandomAccessFile file = new RandomAccessFile(fileName, "rw"); + + for (int i = 0; i < contentLen; i++) { + file.write(0); + } + + file.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/group01/765324639/src/main/java/download/api/Connection.java b/group01/765324639/src/main/java/download/api/Connection.java new file mode 100644 index 0000000000..c0c2a33285 --- /dev/null +++ b/group01/765324639/src/main/java/download/api/Connection.java @@ -0,0 +1,26 @@ +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/group01/765324639/src/main/java/download/api/ConnectionException.java b/group01/765324639/src/main/java/download/api/ConnectionException.java new file mode 100644 index 0000000000..9daefa720f --- /dev/null +++ b/group01/765324639/src/main/java/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group01/765324639/src/main/java/download/api/ConnectionManager.java b/group01/765324639/src/main/java/download/api/ConnectionManager.java new file mode 100644 index 0000000000..c74bf0d41f --- /dev/null +++ b/group01/765324639/src/main/java/download/api/ConnectionManager.java @@ -0,0 +1,11 @@ +package download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group01/765324639/src/main/java/download/api/DownloadListener.java b/group01/765324639/src/main/java/download/api/DownloadListener.java new file mode 100644 index 0000000000..f3730b32a1 --- /dev/null +++ b/group01/765324639/src/main/java/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group01/765324639/src/main/java/download/impl/ConnectionImpl.java b/group01/765324639/src/main/java/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..634fd6f1df --- /dev/null +++ b/group01/765324639/src/main/java/download/impl/ConnectionImpl.java @@ -0,0 +1,62 @@ +package download.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import download.api.Connection; + +public class ConnectionImpl implements Connection { + + private URL url = null;; + + private HttpURLConnection conn = null; + + public ConnectionImpl(String url) { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + try { + conn = (HttpURLConnection) url.openConnection(); + } catch (IOException e) { + e.printStackTrace(); + } + conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + InputStream inputStream = conn.getInputStream(); + byte[] result = new byte[endPos - startPos + 1]; + byte[] data = new byte[1024]; + int read = -1; + int i = 0; + while ((read = inputStream.read(data, 0, data.length)) != -1) { + System.arraycopy(data, 0, result, i, read); + i += read; + } + return result; + } + + @Override + public int getContentLength() { + HttpURLConnection openConnection = null; + try { + openConnection = (HttpURLConnection) url.openConnection(); + } catch (IOException e) { + e.printStackTrace(); + } + int contentLength = openConnection.getContentLength(); + openConnection.disconnect(); + return contentLength; + } + + @Override + public void close() { + } + +} diff --git a/group01/765324639/src/main/java/download/impl/ConnectionManagerImpl.java b/group01/765324639/src/main/java/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..9663736f21 --- /dev/null +++ b/group01/765324639/src/main/java/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,14 @@ +package download.impl; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + +} diff --git a/group01/765324639/src/main/java/litestruts/LoginAction.java b/group01/765324639/src/main/java/litestruts/LoginAction.java new file mode 100644 index 0000000000..87ae0c4fcf --- /dev/null +++ b/group01/765324639/src/main/java/litestruts/LoginAction.java @@ -0,0 +1,42 @@ +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/group01/765324639/src/main/java/litestruts/Struts.java b/group01/765324639/src/main/java/litestruts/Struts.java new file mode 100644 index 0000000000..5230e424e2 --- /dev/null +++ b/group01/765324639/src/main/java/litestruts/Struts.java @@ -0,0 +1,117 @@ +package litestruts; + +import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.HashMap; +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 { + + 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 { + + SAXReader reader = new SAXReader(); + InputStream struts = Struts.class.getResourceAsStream("struts.xml"); + Document document = null; + try { + document = reader.read(struts); + } catch (DocumentException e) { + e.printStackTrace(); + } + + String className = ""; // actionName对应的类名 + Element rootElement = document.getRootElement(); + Iterator iterator = rootElement.elementIterator("action"); + Element targetAction = null; // actionName对应的action + while (iterator.hasNext()) { + Element element = (Element) iterator.next(); + String name = element.attributeValue("name"); + if (name.equals(actionName)) { + className = element.attributeValue("class"); + targetAction = element; + break; + } + } + + + Class class1 = Class.forName(className); + Object instance = class1.newInstance(); + + Set keySet = parameters.keySet(); + for (String key : keySet) { + // 将变量名拼成对应的set方法名 + String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1); + Class type = class1.getDeclaredField(key).getType(); + Method method = class1.getDeclaredMethod(methodName, type); + // 依次调用对应的set方法 + method.invoke(instance, parameters.get(key)); + } + + String result = (String) class1.getDeclaredMethod("execute").invoke(instance); + + Method[] declaredMethods = class1.getDeclaredMethods(); + HashMap map = new HashMap<>(); + for (int i = 0; i < declaredMethods.length; i++) { + if (declaredMethods[i].getName().startsWith("get")) { + String fieldValue = (String) declaredMethods[i].invoke(instance); + String fieldName = methodNameToFieldName(declaredMethods[i].getName()); + map.put(fieldName, fieldValue); + } + } + + View view = new View(); + view.setParameters(map); + + Iterator elementIterator = targetAction.elementIterator("result"); + while (elementIterator.hasNext()) { + Element element = (Element) elementIterator.next(); + if (result.equals(element.attributeValue("name"))) { + view.setJsp(element.getText()); + } + } + + return view; + + + } catch (Exception e1) { + e1.printStackTrace(); + } + + return null; + } + + private static String methodNameToFieldName(String methodName) { + if (!methodName.startsWith("get") && !methodName.startsWith("set")) { + throw new IllegalArgumentException(); + } + + return methodName.substring(3, 4).toLowerCase() + methodName.substring(4); + } + +} diff --git a/group01/765324639/src/main/java/litestruts/View.java b/group01/765324639/src/main/java/litestruts/View.java new file mode 100644 index 0000000000..4a553757d0 --- /dev/null +++ b/group01/765324639/src/main/java/litestruts/View.java @@ -0,0 +1,26 @@ +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/group01/765324639/src/main/java/litestruts/struts.xml b/group01/765324639/src/main/java/litestruts/struts.xml new file mode 100644 index 0000000000..a7eccffd9c --- /dev/null +++ b/group01/765324639/src/main/java/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/group01/765324639/src/main/java/minijvm/attr/AttributeInfo.java b/group01/765324639/src/main/java/minijvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..fc261d7eff --- /dev/null +++ b/group01/765324639/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/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java new file mode 100644 index 0000000000..0044adced8 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/attr/CodeAttr.java @@ -0,0 +1,55 @@ +package minijvm.attr; + +import minijvm.clz.ClassFile; +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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group01/765324639/src/main/java/minijvm/attr/LineNumberTable.java b/group01/765324639/src/main/java/minijvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..71a44fd83e --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/attr/LineNumberTable.java @@ -0,0 +1,42 @@ +package minijvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import minijvm.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/group01/765324639/src/main/java/minijvm/attr/LocalVariableItem.java b/group01/765324639/src/main/java/minijvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..7953b04d23 --- /dev/null +++ b/group01/765324639/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/group01/765324639/src/main/java/minijvm/attr/LocalVariableTable.java b/group01/765324639/src/main/java/minijvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..90248d54f4 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/attr/LocalVariableTable.java @@ -0,0 +1,26 @@ +package minijvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import minijvm.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/group01/765324639/src/main/java/minijvm/attr/StackMapTable.java b/group01/765324639/src/main/java/minijvm/attr/StackMapTable.java new file mode 100644 index 0000000000..7ed27a16a5 --- /dev/null +++ b/group01/765324639/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/group01/765324639/src/main/java/minijvm/clz/AccessFlag.java b/group01/765324639/src/main/java/minijvm/clz/AccessFlag.java new file mode 100644 index 0000000000..7585a3c460 --- /dev/null +++ b/group01/765324639/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/group01/765324639/src/main/java/minijvm/clz/ClassFile.java b/group01/765324639/src/main/java/minijvm/clz/ClassFile.java new file mode 100644 index 0000000000..d1cdbe0e05 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package minijvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import minijvm.constant.ClassInfo; +import minijvm.constant.ConstantPool; +import minijvm.field.Field; +import minijvm.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(); + } +} diff --git a/group01/765324639/src/main/java/minijvm/clz/ClassIndex.java b/group01/765324639/src/main/java/minijvm/clz/ClassIndex.java new file mode 100644 index 0000000000..4b25095924 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package minijvm.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/765324639/src/main/java/minijvm/constant/ClassInfo.java b/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c856052998 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/ClassInfo.java @@ -0,0 +1,25 @@ +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; + } + @Override + public int getType() { + return type; + } + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java b/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..5fa0be0189 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +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); + } + +} diff --git a/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java b/group01/765324639/src/main/java/minijvm/constant/ConstantPool.java new file mode 100644 index 0000000000..12746a1f3c --- /dev/null +++ b/group01/765324639/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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java b/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..ddcf2df456 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/FieldRefInfo.java @@ -0,0 +1,56 @@ +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); + } + @Override + 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; + } + + @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(); + } +} diff --git a/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java b/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f4c2368228 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/MethodRefInfo.java @@ -0,0 +1,57 @@ +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); + } + + @Override + 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; + } + + @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(); + } + + + +} diff --git a/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java b/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..de88422d82 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/NameAndTypeInfo.java @@ -0,0 +1,47 @@ +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; + } + @Override + 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(); + } + + @Override + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java b/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..88eb702f4b --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package minijvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/constant/StringInfo.java b/group01/765324639/src/main/java/minijvm/constant/StringInfo.java new file mode 100644 index 0000000000..915652a93c --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/StringInfo.java @@ -0,0 +1,28 @@ +package minijvm.constant; + +public class StringInfo extends ConstantInfo{ + private int type = ConstantInfo.STRING_INFO; + private int index; + public StringInfo(ConstantPool pool) { + super(pool); + } + + @Override + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + public void setIndex(int index) { + this.index = index; + } + + + @Override + public String toString(){ + return this.getConstantPool().getUTF8String(index); + } + +} diff --git a/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java b/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java new file mode 100644 index 0000000000..1af71e8e9c --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/constant/UTF8Info.java @@ -0,0 +1,33 @@ +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; + } + @Override + 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/group01/765324639/src/main/java/minijvm/field/Field.java b/group01/765324639/src/main/java/minijvm/field/Field.java new file mode 100644 index 0000000000..85fded5380 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/field/Field.java @@ -0,0 +1,39 @@ +package minijvm.field; + +import minijvm.constant.ConstantPool; +import minijvm.constant.UTF8Info; +import minijvm.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; + } + + @Override + public String toString() { + String fieldName = ((UTF8Info)pool.getConstantInfo(nameIndex)).getValue(); + String fieldDescription = ((UTF8Info)pool.getConstantInfo(descriptorIndex)).getValue(); + return fieldName + ":" + fieldDescription; + } +} diff --git a/group01/765324639/src/main/java/minijvm/loader/ByteCodeIterator.java b/group01/765324639/src/main/java/minijvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..bcfbbace77 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/loader/ByteCodeIterator.java @@ -0,0 +1,65 @@ +package minijvm.loader; + +import java.io.UnsupportedEncodingException; + +import minijvm.util.Util; + +public class ByteCodeIterator { + + private byte[] codes; + + private int pos = 0; + + public ByteCodeIterator (byte[] codes) { + this.codes = codes; + } + + 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 length) { + byte[] src = new byte[length]; + for (int i = 0; i < length; i++) { + src[i] = codes[pos++]; + } + return Util.byteToHexString(src); + } + + public String nextLengthToString(int length) { + String dest = null; + try { + dest = new String(getBytes(length), "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return dest; + } + + public void back(int length) { + for (int i = 0; i < length; i++) { + pos--; + } + } + + private byte[] getBytes(int length) { + byte[] b = new byte[length]; + for (int i = 0; i < length; i++) { + b[i] = codes[pos++]; + } + return b; + } + +} diff --git a/group01/765324639/src/main/java/minijvm/loader/ClassFileLoader.java b/group01/765324639/src/main/java/minijvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..51bce28f2a --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/loader/ClassFileLoader.java @@ -0,0 +1,80 @@ +package minijvm.loader; + +import java.io.ByteArrayOutputStream; +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 minijvm.clz.ClassFile; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) throws ClassNotFoundException { + File classFile = getClassFile(className); + return readFileToByteArray(classFile); + } + + private File getClassFile(String className) throws ClassNotFoundException { + File classFile = null; + String classFilePath = convertClassNameToFilePath(className); + for (String path : clzPaths) { + File file = new File(path, classFilePath); + if (file.exists()) { + classFile = file; + break; + } + } + + if (classFile == null) { // 文件不存在 + throw new ClassNotFoundException(); + } + return classFile; + } + + private byte[] readFileToByteArray(File classFile) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try (InputStream in = new FileInputStream(classFile);) { + byte[] data = new byte[1024]; + int len = -1; + while ((len = in.read(data)) != -1) { + out.write(data, 0, len); + } + } catch (FileNotFoundException e) { // 调用此函数时,已经确定文件是存在的 + e.printStackTrace(); + } catch (IOException e1) { + e1.printStackTrace(); + } + return out.toByteArray(); + } + + private String convertClassNameToFilePath(String fillClassName) { + return fillClassName.replace(".", File.separator) + ".class"; + } + + public void addClassPath(String path) { + if (clzPaths.contains(path)) { + return; + } + clzPaths.add(path); + } + + public String getClassPath() { + return String.join(";", clzPaths); + } + + public ClassFile loadClass(String className) throws ClassNotFoundException { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + +} diff --git a/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java b/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..cb42be22d6 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/loader/ClassFileParser.java @@ -0,0 +1,257 @@ +package minijvm.loader; + +import java.util.ArrayList; +import java.util.List; + +import minijvm.attr.AttributeInfo; +import minijvm.attr.CodeAttr; +import minijvm.attr.LineNumberTable; +import minijvm.attr.LocalVariableTable; +import minijvm.clz.AccessFlag; +import minijvm.clz.ClassFile; +import minijvm.clz.ClassIndex; +import minijvm.constant.ClassInfo; +import minijvm.constant.ConstantInfo; +import minijvm.constant.ConstantPool; +import minijvm.constant.FieldRefInfo; +import minijvm.constant.MethodRefInfo; +import minijvm.constant.NameAndTypeInfo; +import minijvm.constant.NullConstantInfo; +import minijvm.constant.StringInfo; +import minijvm.constant.UTF8Info; +import minijvm.field.Field; +import minijvm.method.Method; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ByteCodeIterator iter = new ByteCodeIterator(codes); + ClassFile classFile = new ClassFile(); + + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equalsIgnoreCase(magicNumber)) { + return null; + } + + classFile.setMinorVersion(iter.nextU2ToInt()); + classFile.setMajorVersion(iter.nextU2ToInt()); + + ConstantPool pool = parseConstantPool(iter); + classFile.setConstPool(pool); + + classFile.setAccessFlag(parseAccessFlag(iter)); + classFile.setClassIndex(parseClassIndex(iter)); + + // 目前没有处理接口 + parseInterfaces(iter); + + List fieldList = parseFields(iter, pool); + addFields(classFile, fieldList); + + List methodList = parseMethods(iter, classFile); + addMethods(classFile, methodList); + + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + int flag = iter.nextU2ToInt(); + AccessFlag accessFlag = new AccessFlag(flag); + return accessFlag; + } + + private ClassIndex parseClassIndex(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) { + int size = iter.nextU2ToInt(); + System.out.println("ConstantPool size: " + size); + + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); // 添加无效的第0项 + + for (int i = 1; i < size; i++) { + int tag = iter.nextU1ToInt(); + + if (tag == ConstantInfo.UTF8_INFO) { + UTF8Info utf8Info = new UTF8Info(pool); + int length = iter.nextU2ToInt(); + String value = iter.nextLengthToString(length); + utf8Info.setLength(length); + utf8Info.setValue(value); + + pool.addConstantInfo(utf8Info); + } else if (tag == ConstantInfo.CLASS_INFO) { + ClassInfo classInfo = new ClassInfo(pool); + int index = iter.nextU2ToInt(); + classInfo.setUtf8Index(index); + + pool.addConstantInfo(classInfo); + } else if (tag == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(pool); + int index = iter.nextU2ToInt(); + stringInfo.setIndex(index); + + pool.addConstantInfo(stringInfo); + } else if (tag == ConstantInfo.FIELD_INFO) { + 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 == ClassInfo.METHOD_INFO) { + 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 == ClassInfo.NAME_AND_TYPE_INFO) { + 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("这个类型的常量还没有实现"); + } + + } + + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceNum = iter.nextU2ToInt(); + if (interfaceNum != 0) { + throw new RuntimeException("有接口没有读取"); + } + } + + private List parseFields(ByteCodeIterator iter, ConstantPool pool) { + int filedNum = iter.nextU2ToInt(); + System.out.println("Field num: " + filedNum); + + List fieldList = new ArrayList<>(); + for (int i = 0; i < filedNum; i++) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptionIndex = iter.nextU2ToInt(); + int attributesCount = iter.nextU2ToInt(); + if (attributesCount != 0) { + throw new RuntimeException("字段的属性表没有处理"); + } + + fieldList.add(new Field(accessFlag, nameIndex, descriptionIndex, pool)); + } + + return fieldList; + } + + private void addFields(ClassFile classFile, List fieldList) { + for (Field field : fieldList) { + classFile.addField(field); + } + } + + private List parseMethods(ByteCodeIterator iter, ClassFile classFile) { + int methodNum = iter.nextU2ToInt(); + System.out.println("Methods num: " + methodNum); + + List methodList = new ArrayList<>(); + for (int i = 0; i < methodNum; i++) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptionIndex = iter.nextU2ToInt(); + + Method method = new Method(classFile, accessFlag, nameIndex, descriptionIndex); + + int attributesCount = iter.nextU2ToInt(); + for (int j = 0; j < attributesCount; j++) { + parseAttribute(iter, method, classFile); + } + + methodList.add(method); + } + return methodList; + } + + private void parseAttribute(ByteCodeIterator iter, Method method, ClassFile classFile) { + int nameIndex = iter.nextU2ToInt(); + int length = iter.nextU4ToInt(); + + if (AttributeInfo.CODE.equals(getUTF8ValueOfConstantPool(nameIndex, classFile))) { + CodeAttr codeAttr = parseCodeAttribute(iter, classFile); + method.setCodeAttr(codeAttr); + } else { + //TODO 目前没有处理除CODE外的其余属性 + iter.nextUxToHexString(length); + } + + } + + private CodeAttr parseCodeAttribute(ByteCodeIterator iter, ClassFile classFile) { + iter.back(6); // 因为之前验证类型时前进了6个字节,在此回退 + + int nameIndex = iter.nextU2ToInt(); + int length = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLength = iter.nextU4ToInt(); + String code = iter.nextUxToHexString(codeLength); + + CodeAttr codeAttr = new CodeAttr(nameIndex, length, maxStack, maxLocals, codeLength, code); + + // TODO Code属性中的exception + int exceptionLength = iter.nextU2ToInt(); + if (exceptionLength != 0) { + throw new RuntimeException("Code属性中有异常字段没有处理"); + } + + // Code属性中的属性 + int attributesCount = iter.nextU2ToInt(); + for (int i = 0; i < attributesCount; i++) { + int attrNameIndex = iter.nextU2ToInt(); + int attrLength = iter.nextU4ToInt(); + + if (AttributeInfo.LINE_NUM_TABLE.equals(getUTF8ValueOfConstantPool(attrNameIndex, classFile))) { + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex, attrLength); + codeAttr.setLineNumberTable(lineNumberTable); + iter.nextUxToHexString(attrLength); + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(getUTF8ValueOfConstantPool(attrNameIndex, classFile))) { + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIndex, attrLength); + codeAttr.setLocalVariableTable(localVariableTable); + iter.nextUxToHexString(attrLength); + } else { + String msg = "此属性:" + getUTF8ValueOfConstantPool(attrNameIndex, classFile) + "还没有处理"; + throw new RuntimeException(msg); + } + } + + return codeAttr; + } + + private void addMethods(ClassFile classFile, List methodList) { + for (Method method : methodList) { + classFile.addMethod(method); + } + } + + private String getUTF8ValueOfConstantPool(int index, ClassFile classFile) { + ConstantPool constantPool = classFile.getConstantPool(); + return constantPool.getUTF8String(index); + } + +} diff --git a/group01/765324639/src/main/java/minijvm/method/Method.java b/group01/765324639/src/main/java/minijvm/method/Method.java new file mode 100644 index 0000000000..3d0b9a5678 --- /dev/null +++ b/group01/765324639/src/main/java/minijvm/method/Method.java @@ -0,0 +1,54 @@ +package minijvm.method; + +import minijvm.attr.CodeAttr; +import minijvm.clz.ClassFile; +import minijvm.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/group01/765324639/src/main/java/minijvm/util/Util.java b/group01/765324639/src/main/java/minijvm/util/Util.java new file mode 100644 index 0000000000..e6370a4997 --- /dev/null +++ b/group01/765324639/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 tokenList = tokenParser.parse(); + Assert.assertEquals("2", tokenList.get(0).getValue()); + Assert.assertEquals("*", tokenList.get(3).getValue()); + Assert.assertEquals("5", tokenList.get(6).getValue()); + } + { + TokenParser tokenParser = new TokenParser("3*20+12*5-40/2"); + List tokenList = tokenParser.parse(); + Assert.assertEquals("20", tokenList.get(2).getValue()); + Assert.assertEquals("12", tokenList.get(4).getValue()); + Assert.assertEquals("5", tokenList.get(6).getValue()); + } + + } +} diff --git a/group01/765324639/src/test/java/download/FileDownloaderTest.java b/group01/765324639/src/test/java/download/FileDownloaderTest.java new file mode 100644 index 0000000000..e9ea374cb2 --- /dev/null +++ b/group01/765324639/src/test/java/download/FileDownloaderTest.java @@ -0,0 +1,61 @@ +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://121.42.185.101/forum/test.jpg"; // 此图片较大 + String url = "http://121.42.185.101/forum/weixin.jpg"; // 此图片较小 + + FileDownloader downloader = new FileDownloader(url); + + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + + }); + + new Thread() { + @Override + public void run() { + downloader.execute(); + } + }.start(); + + // 等待多线程下载程序执行完毕 + while (!downloadFinished) { + try { + System.out.println("Downloaded not complete, sleep 5 second"); + // 休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("download complete!"); + + } + +} diff --git a/group01/765324639/src/test/java/litestruts/StrutsTest.java b/group01/765324639/src/test/java/litestruts/StrutsTest.java new file mode 100644 index 0000000000..45616a42cd --- /dev/null +++ b/group01/765324639/src/test/java/litestruts/StrutsTest.java @@ -0,0 +1,42 @@ +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/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java b/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java new file mode 100644 index 0000000000..80586f51e2 --- /dev/null +++ b/group01/765324639/src/test/java/minijvm/loader/ClassFileloaderTest.java @@ -0,0 +1,274 @@ +package minijvm.loader; + +import java.io.File; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import minijvm.clz.ClassFile; +import minijvm.clz.ClassIndex; +import minijvm.constant.ClassInfo; +import minijvm.constant.ConstantPool; +import minijvm.constant.MethodRefInfo; +import minijvm.constant.NameAndTypeInfo; +import minijvm.constant.UTF8Info; +import minijvm.field.Field; +import minijvm.method.Method; + + + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "minijvm/loader/EmployeeV1"; + + static String path1 = new File(".", "target\\test-classes").getAbsolutePath(); + static String path2 = "C:\\temp"; + + static String className = EmployeeV1.class.getName(); + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "minijvm.loader.EmployeeV1"; + + try { + clzFile = loader.loadClass(className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + 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() throws ClassNotFoundException { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1038, byteCodes.length); + + } + + @Test(expected = ClassNotFoundException.class) + public void testClassNotFindException() throws ClassNotFoundException { + ClassFileLoader loader = new ClassFileLoader(); + loader.readBinaryCode(className); + } + + + @Test + public void testMagicNumber() throws ClassNotFoundException { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + 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); + } + +} diff --git a/group01/765324639/src/test/java/minijvm/loader/EmployeeV1.java b/group01/765324639/src/test/java/minijvm/loader/EmployeeV1.java new file mode 100644 index 0000000000..e501762cc4 --- /dev/null +++ b/group01/765324639/src/test/java/minijvm/loader/EmployeeV1.java @@ -0,0 +1,30 @@ +package minijvm.loader; + +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(); + + } +} diff --git a/group01/765324639/src/zavier/week01/basic/ArrayList.java b/group01/765324639/src/zavier/week01/basic/ArrayList.java deleted file mode 100644 index 38e5739fb8..0000000000 --- a/group01/765324639/src/zavier/week01/basic/ArrayList.java +++ /dev/null @@ -1,85 +0,0 @@ -package zavier.week01.basic; - -import java.util.Arrays; - -public class ArrayList implements List { - - private int size = 0; - - private Object[] elementData = new Object[100]; - - @Override - public void add(Object o) { - ensureCapacity(size + 1); - elementData[size++] = o; - } - - private void ensureCapacity(int size) { - if (size > elementData.length) { - grow(); - } - } - - private void grow() { - elementData = Arrays.copyOf(elementData, size * 2); - } - - @Override - public void add(int index, Object o) { - rangeCheckForAdd(index); - ensureCapacity(size + 1); - System.arraycopy(elementData, index, elementData, index + 1, size - index); - elementData[index] = o; - size++; - } - - private void rangeCheckForAdd(int index) { - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException(); - } - } - - @Override - public Object get(int index) { - rangeCheck(index); - return elementData[index]; - } - - private void rangeCheck(int index) { - if (index >= size || index < 0) { - throw new IndexOutOfBoundsException(); - } - } - - @Override - public Object remove(int index) { - rangeCheck(index); - Object dest = elementData[index]; - System.arraycopy(elementData, index + 1, elementData, index, size - index - 1); - size--; - return dest; - } - - @Override - public int size() { - return size; - } - - public Iterator iterator() { - return new Iterator() { - - private int index = 0; - - @Override - public Object next() { - return elementData[index++]; - } - - @Override - public boolean hasNext() { - return index < size; - } - }; - } - -} diff --git a/group01/765324639/src/zavier/week01/basic/BinaryTreeNode.java b/group01/765324639/src/zavier/week01/basic/BinaryTreeNode.java deleted file mode 100644 index 6ef26e8f9a..0000000000 --- a/group01/765324639/src/zavier/week01/basic/BinaryTreeNode.java +++ /dev/null @@ -1,63 +0,0 @@ -package zavier.week01.basic; - -public class BinaryTreeNode { - - private Integer data; - private BinaryTreeNode left; - private BinaryTreeNode right; - - public BinaryTreeNode(Integer data) { - this.data = data; - } - - public Integer 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 > this.data) { - - if (this.getRight() == null) { - BinaryTreeNode node = new BinaryTreeNode(o); - this.setRight(node); - return node; - } else { - return this.getRight().insert(o); - } - - } else { - - if (this.getLeft() == null) { - BinaryTreeNode node = new BinaryTreeNode(o); - this.setLeft(node); - return node; - } else { - return this.getLeft().insert(o); - } - - } - - } - -} diff --git a/group01/765324639/src/zavier/week01/basic/Iterator.java b/group01/765324639/src/zavier/week01/basic/Iterator.java deleted file mode 100644 index 664983e0fd..0000000000 --- a/group01/765324639/src/zavier/week01/basic/Iterator.java +++ /dev/null @@ -1,8 +0,0 @@ -package zavier.week01.basic; - -public interface Iterator { - public boolean hasNext(); - - public Object next(); - -} diff --git a/group01/765324639/src/zavier/week01/basic/LinkedList.java b/group01/765324639/src/zavier/week01/basic/LinkedList.java deleted file mode 100644 index 6e15220b34..0000000000 --- a/group01/765324639/src/zavier/week01/basic/LinkedList.java +++ /dev/null @@ -1,375 +0,0 @@ -package zavier.week01.basic; - -import java.util.NoSuchElementException; - -public class LinkedList implements List { - - private Node head; - - private int size = 0; - - @Override - public void add(Object o) { - if (head == null) { - head = new Node(o); - } else { - Node tail = head; - while (tail.next != null) { - tail = tail.next; - } - Node node = new Node(o); - - tail.next = node; - } - size++; - } - - @Override - public void add(int index, Object o) { - rangeCheckForAdd(index); - if (index == 0) { - Node node = new Node(o); - node.next = head; - head = node; - } else { - Node preDest = head; - for (int i = 0; i < index - 1; i++) { - preDest = preDest.next; - } - Node node = new Node(o); - node.next = preDest.next; - preDest.next = node; - } - - size++; - } - - private void rangeCheckForAdd(int index) { - if (index > size || index < 0) { - throw new IndexOutOfBoundsException(); - } - } - - @Override - public Object get(int index) { - rangeCheck(index); - - Node dest = head; - for (int i = 0; i < index; i++) { - dest = dest.next; - } - return dest.data; - } - - private void rangeCheck(int index) { - if (index >= size || index < 0) { - throw new IndexOutOfBoundsException(); - } - } - - @Override - public Object remove(int index) { - rangeCheck(index); - - Node preDest = head; - for (int i = 0; i < index - 1; i++) { - preDest = preDest.next; - } - Node dest = preDest.next; - preDest.next = dest.next; - - size--; - return dest.data; - } - - @Override - public int size() { - return size; - } - - public void addFirst(Object o) { - Node node = new Node(o); - node.next = head; - head = node; - size++; - } - - public void addLast(Object o) { - Node lastNode = head; - while (lastNode.next != null) { - lastNode = lastNode.next; - } - - Node node = new Node(o); - lastNode.next = node; - size++; - } - - public Object removeFirst() { - if (head == null) { - throw new NoSuchElementException(); - } - Node target = head; - head = head.next; - size--; - return target.data; - } - - public Object removeLast() { - if (head == null) { - throw new NoSuchElementException(); - } - - Node preDest = head; - while (preDest.next.next != null) { - preDest = preDest.next; - } - Node dest = preDest.next; - preDest.next = null; - - size--; - return dest.data; - } - - public Iterator iterator() { - return null; - } - - - private static class Node { - Object data; - Node next; - - Node(Object data) { - this.data = data; - next = null; - } - } - - // =========================第三周作业========================= - - /** - * 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse() { - Node reverseNode = null; - while (head != null) { - Node temp = head; - head = head.next; - temp.next = reverseNode; - reverseNode = temp; - } - head = reverseNode; - } - - /** - * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - */ - public void removeFirstHalf() { - int newStartIndex = size / 2; - for (int i = 0; i < newStartIndex; i++) { - head = head.next; - } - size = size - newStartIndex; - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * - * @param i - * @param length - */ - public void remove(int i, int length) { - if (i < 0) { - throw new IllegalArgumentException(); - } - if (i + length >= size) { - length = size - i; - } - - if (i == 0) { - for (int j = 0; j < length; j++) { - head = head.next; - } - } else { - Node beforeRemoveStartNode = head; - for (int j = 0; j < i - 1; j++) { - beforeRemoveStartNode = beforeRemoveStartNode.next; - } - - Node removeEndNode = beforeRemoveStartNode; - for (int j = 0; j < length; j++) { - removeEndNode = removeEndNode.next; - } - - beforeRemoveStartNode.next = removeEndNode.next; - } - - 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) { - checkList(list); - - int[] dest = new int[list.size]; - int arrayNum = 0; - Node temp = head; - int n = (int) list.get(0); - for (int i = 0; i < n; i++) { - temp = temp.next; - } - dest[arrayNum++] = (int) temp.data; - - for (int i = 1; i < list.size; i++) { - int num = (int) list.get(i) - (int) list.get(i - 1); - for (int j = 0; j < num; j++) { - temp = temp.next; - } - dest[arrayNum++] = (int) temp.data; - } - return dest; - } - - private void checkList(LinkedList list) { - for (int i = 0; i < list.size; i++) { - if ((int) list.get(i) < 0 || (int) list.get(i) >= size) { - throw new IllegalArgumentException("list中的元素位置越界"); - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 - * - * @param list - */ - - public void subtract(LinkedList list) { - if (list == null || list.size == 0 || this.size == 0) { - return; - } - - int thisIndex = 0; - int listIndex = 0; - Node temp = head; - while (true) { // 后续需要优化替换remove()方法 - if ((int) temp.data < (int) list.get(listIndex)) { - temp = temp.next; - thisIndex++; - } else if ((int) temp.data == (int) list.get(listIndex)) { - this.remove(thisIndex); - temp = temp.next; - thisIndex++; - listIndex++; - } else { - listIndex++; - } - - if (thisIndex >= this.size || listIndex >= list.size) { - break; - } - } - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues() { - if (this.size == 0) { - return; - } - - Node subHead = head; - Node subTail = head; - - while (true) { - if (subTail == null) { - subHead.next = null; // 清除尾部重复的元素 - break; - } - if ((int) subTail.data == (int) subHead.data) { - if (!(subTail == subHead)) { // 判断两个指针是否指向同一个地方 - this.size--; - } - subTail = subTail.next; - } else { - subHead.next = subTail; - subHead = subHead.next; - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * - * @param min - * @param max - */ - public void removeRange(int min, int max) { - if (this.size == 0) { - return; - } - - if ((int) head.data > max) { - throw new IllegalArgumentException(); - } - - int length = 0; - Node subList = new Node(null); - Node temp = subList; - while (true) { - if (head == null) { - break; - } - if ((int) head.data <= min || (int) head.data >= max) { - temp.next = head; - temp = temp.next; - length++; - } - head = head.next; - } - temp.next = null; // 去掉尾部多余数据 - head = subList.next; - size = length; - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * - * @param list - */ - public LinkedList intersection(LinkedList list) { - if (this.size == 0 || list.size == 0) { - return null; - } - - Node tempHead = head; - int listIndex = 0; - - LinkedList newList = new LinkedList(); - while (true) { - if (tempHead == null || listIndex >= list.size) { - break; - } - - if ((int) tempHead.data < (int) list.get(listIndex)) { - tempHead = tempHead.next; - } else if ((int) tempHead.data > (int) list.get(listIndex)) { - listIndex++; - } else { - newList.add(tempHead.data); - - tempHead = tempHead.next; - listIndex++; - } - } - - return newList; - } -} diff --git a/group01/765324639/src/zavier/week01/basic/List.java b/group01/765324639/src/zavier/week01/basic/List.java deleted file mode 100644 index 4f2d49bd73..0000000000 --- a/group01/765324639/src/zavier/week01/basic/List.java +++ /dev/null @@ -1,13 +0,0 @@ -package zavier.week01.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/group01/765324639/src/zavier/week01/basic/Queue.java b/group01/765324639/src/zavier/week01/basic/Queue.java deleted file mode 100644 index 5a212d46c1..0000000000 --- a/group01/765324639/src/zavier/week01/basic/Queue.java +++ /dev/null @@ -1,25 +0,0 @@ -package zavier.week01.basic; - -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/zavier/week01/basic/Stack.java b/group01/765324639/src/zavier/week01/basic/Stack.java deleted file mode 100644 index ebe4afb19f..0000000000 --- a/group01/765324639/src/zavier/week01/basic/Stack.java +++ /dev/null @@ -1,33 +0,0 @@ -package zavier.week01.basic; - -import java.util.EmptyStackException; - -public class Stack { - private ArrayList elementData = new ArrayList(); - - public void push(Object o) { - elementData.add(o); - } - - public Object pop() { - if (elementData.size() == 0) { - throw new EmptyStackException(); - } - return elementData.remove(elementData.size() - 1); - } - - public Object peek() { - if (elementData.size() == 0) { - throw new EmptyStackException(); - } - return elementData.get(elementData.size() - 1); - } - - public boolean isEmpty() { - return elementData.size() == 0; - } - - public int size() { - return elementData.size(); - } -} diff --git a/group01/765324639/src/zavier/week01/test/AllTests.java b/group01/765324639/src/zavier/week01/test/AllTests.java deleted file mode 100644 index c1755f6803..0000000000 --- a/group01/765324639/src/zavier/week01/test/AllTests.java +++ /dev/null @@ -1,12 +0,0 @@ -package zavier.week01.test; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -@RunWith(Suite.class) -@SuiteClasses({ArrayListTest.class, LinkedListTest.class, QueueTest.class, StackTest.class, - BinaryTreeNodeTest.class}) -public class AllTests { - -} diff --git a/group01/765324639/src/zavier/week01/test/ArrayListTest.java b/group01/765324639/src/zavier/week01/test/ArrayListTest.java deleted file mode 100644 index 6a475500df..0000000000 --- a/group01/765324639/src/zavier/week01/test/ArrayListTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package zavier.week01.test; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import zavier.week01.basic.ArrayList; -import zavier.week01.basic.Iterator; - -public class ArrayListTest { - - private ArrayList arrayList = new ArrayList(); - - @Before - public void setUp() { - for (int i = 0; i < 500; i++) { - arrayList.add(i); - } - } - - @Test - public void testAddObject() { - for (int i = 0; i < 500; i++) { - arrayList.add(i); - } - } - - @Test - public void testAddIntObject() { - arrayList.add(100, -100); - Assert.assertEquals(-100, arrayList.get(100)); - Assert.assertEquals(100, arrayList.get(101)); - Assert.assertEquals(501, arrayList.size()); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testAddIllegalIntObject() { - arrayList.add(1000, 5); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testAddNegativeIntObject() { - arrayList.add(-1, 5); - } - - @Test - public void testGet() { - for (int i = 0; i < 500; i++) { - Assert.assertEquals(i, ((Integer) arrayList.get(i)).intValue()); - } - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testIllegalGet() { - arrayList.get(500); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testNegativeGet() { - arrayList.get(-10); - } - - @Test - public void testRemove() { - Assert.assertEquals(100, arrayList.remove(100)); - Assert.assertEquals(101, arrayList.get(100)); - Assert.assertEquals(499, arrayList.size()); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testIllegalRemove() { - arrayList.remove(500); - } - - @Test - public void testSize() { - Assert.assertEquals(500, arrayList.size()); - } - - @Test - public void testIterator() { - Iterator iterator = arrayList.iterator(); - int i = 0; - while (iterator.hasNext()) { - Assert.assertEquals(i, iterator.next()); - i++; - } - Assert.assertEquals(500, i); - } - -} diff --git a/group01/765324639/src/zavier/week01/test/BinaryTreeNodeTest.java b/group01/765324639/src/zavier/week01/test/BinaryTreeNodeTest.java deleted file mode 100644 index 30a096a350..0000000000 --- a/group01/765324639/src/zavier/week01/test/BinaryTreeNodeTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package zavier.week01.test; - -import org.junit.Assert; -import org.junit.Test; - -import zavier.week01.basic.BinaryTreeNode; - -public class BinaryTreeNodeTest { - - private BinaryTreeNode root = new BinaryTreeNode(5); - - @Test - public void testInsert() { - root.insert(2); - root.insert(7); - root.insert(1); - root.insert(6); - - Assert.assertEquals((Integer) 5, root.getData()); - Assert.assertEquals((Integer) 2, root.getLeft().getData()); - Assert.assertEquals((Integer) 1, root.getLeft().getLeft().getData()); - Assert.assertEquals(null, root.getLeft().getRight()); - Assert.assertEquals((Integer) 7, root.getRight().getData()); - Assert.assertEquals((Integer) 6, root.getRight().getLeft().getData()); - Assert.assertEquals(null, root.getRight().getRight()); - - root.insert(4); - root.insert(8); - Assert.assertEquals((Integer) 4, root.getLeft().getRight().getData()); - Assert.assertEquals((Integer) 8, root.getRight().getRight().getData()); - } - -} diff --git a/group01/765324639/src/zavier/week01/test/LinkedListTest.java b/group01/765324639/src/zavier/week01/test/LinkedListTest.java deleted file mode 100644 index ea1f077704..0000000000 --- a/group01/765324639/src/zavier/week01/test/LinkedListTest.java +++ /dev/null @@ -1,259 +0,0 @@ -package zavier.week01.test; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import zavier.week01.basic.LinkedList; - - -public class LinkedListTest { - - private LinkedList linkedList = new LinkedList(); - - @Before - public void setUp() { - for (int i = 0; i < 500; i++) { - linkedList.add(i); - } - } - - @Test - public void testAddObject() { - for (int i = 0; i < 100; i++) { - linkedList.add(i); - } - Assert.assertEquals(600, linkedList.size()); - } - - @Test - public void testAddIntObject() { - linkedList.add(100, -100); - Assert.assertEquals(-100, linkedList.get(100)); - Assert.assertEquals(100, linkedList.get(101)); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testAddIllegalIntObject() { - linkedList.add(1000, 10); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testAddNegativeIntObject() { - linkedList.add(-10, 10); - } - - @Test - public void testGet() { - for (int i = 0; i < 500; i++) { - Assert.assertEquals(i, ((Integer) linkedList.get(i)).intValue()); - } - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testIllegalGet() { - linkedList.get(500); - } - - @Test(expected = IndexOutOfBoundsException.class) - public void testNegativeGet() { - linkedList.get(-10); - } - - @Test - public void testRemove() { - Assert.assertEquals(100, linkedList.remove(100)); - Assert.assertEquals(101, linkedList.get(100)); - Assert.assertEquals(499, linkedList.size()); - } - - @Test - public void testSize() { - Assert.assertEquals(500, linkedList.size()); - linkedList.add(10); - Assert.assertEquals(501, linkedList.size()); - } - - @Test - public void testAddFirst() { - linkedList.addFirst(-10); - Assert.assertEquals(-10, linkedList.get(0)); - linkedList.addFirst(-100); - Assert.assertEquals(-100, linkedList.get(0)); - Assert.assertEquals(-10, linkedList.get(1)); - } - - @Test - public void testAddLast() { - linkedList.addLast(-9); - Assert.assertEquals(-9, linkedList.get(linkedList.size() - 1)); - linkedList.addLast(-8); - Assert.assertEquals(-8, linkedList.get(linkedList.size() - 1)); - Assert.assertEquals(-9, linkedList.get(linkedList.size() - 2)); - } - - @Test - public void testRemoveFirst() { - Assert.assertEquals(0, linkedList.removeFirst()); - Assert.assertEquals(1, linkedList.removeFirst()); - Assert.assertEquals(498, linkedList.size()); - } - - @Test - public void testRemoveLast() { - Assert.assertEquals(499, linkedList.removeLast()); - Assert.assertEquals(498, linkedList.removeLast()); - Assert.assertEquals(498, linkedList.size()); - } - - // =========================第三周作业========================= - - @Test - public void testReverse() { - linkedList.reverse(); - for (int i = 0; i < linkedList.size(); i++) { - Assert.assertEquals(499 - i, linkedList.get(i)); - } - Assert.assertEquals(500, linkedList.size()); - } - - @Test - public void testRemoveFirstHalfOfEven() { - linkedList.removeFirstHalf(); - for (int i = 250; i < 500; i++) { - Assert.assertEquals(i, linkedList.get(i - 250)); - } - Assert.assertEquals(250, linkedList.size()); - } - - @Test - public void testRemoveFirstHalfOfOdd() { - linkedList.add(500); - linkedList.removeFirstHalf(); - for (int i = 250; i < 501; i++) { - Assert.assertEquals(i, linkedList.get(i - 250)); - } - Assert.assertEquals(251, linkedList.size()); - } - - @Test - public void testRemoveIntInt() { - linkedList.remove(10, 10); - Assert.assertEquals(0, linkedList.get(0)); - Assert.assertEquals(20, linkedList.get(10)); - Assert.assertEquals(490, linkedList.size()); - } - - @Test(expected = IllegalArgumentException.class) - public void testIllegalIRemoveIntInt() { - linkedList.remove(-10, 10); - } - - @Test - public void testIllegalLengthRemoveIntInt() { - linkedList.remove(0, 10); - Assert.assertEquals(490, linkedList.size()); - Assert.assertEquals(10, linkedList.get(0)); - - linkedList.remove(300, 500); - Assert.assertEquals(300, linkedList.size()); - for (int i = 0; i < 300; i++) { - Assert.assertEquals(i + 10, linkedList.get(i)); - } - } - - @Test(expected = IllegalArgumentException.class) - public void testGetElements() { - LinkedList list = new LinkedList(); - list.add(5); - list.add(10); - list.add(202); - list.add(305); - Assert.assertArrayEquals(new int[] {5, 10, 202, 305}, linkedList.getElements(list)); - - Assert.assertEquals(500, linkedList.size()); - - list.add(500); - linkedList.getElements(list); - } - - @Test - public void testSubtract() { - LinkedList list1 = new LinkedList(); - list1.add(1); - list1.add(5); - list1.add(8); - list1.add(10); - LinkedList list2 = new LinkedList(); - list2.add(2); - list2.add(5); - list2.add(7); - list2.add(11); - list1.subtract(list2); - - Assert.assertEquals(1, list1.get(0)); - Assert.assertEquals(8, list1.get(1)); - Assert.assertEquals(10, list1.get(2)); - Assert.assertEquals(3, list1.size()); - } - - @Test - public void testRemoveDuplicateValues() { - LinkedList list = new LinkedList(); - list.add(1); - list.add(2); - list.add(2); - list.add(2); - list.add(3); - list.add(4); - list.add(5); - list.add(6); - list.add(6); - list.add(7); - list.add(7); - list.add(7); - - list.removeDuplicateValues(); - for (int i = 0; i < 7; i++) { - Assert.assertEquals(i + 1, list.get(i)); - } - Assert.assertEquals(7, list.size()); - } - - @Test - public void testRemoveRange() { - linkedList.removeRange(100, 300); - Assert.assertEquals(301, linkedList.size()); - for (int i = 0; i < 100; i++) { - Assert.assertEquals(i, linkedList.get(i)); - } - for (int i = 300; i < 500; i++) { - Assert.assertEquals(i, linkedList.get(i - 199)); - } - } - - @Test - public void testIntersection() { - LinkedList list1 = new LinkedList(); - list1.add(1); - list1.add(2); - list1.add(5); - list1.add(7); - list1.add(9); - - LinkedList list2 = new LinkedList(); - list2.add(0); - list2.add(2); - list2.add(9); - list2.add(10); - list2.add(19); - - LinkedList intersection = list1.intersection(list2); - Assert.assertNotNull(intersection); - Assert.assertEquals(2, intersection.size()); - Assert.assertEquals(2, (int) intersection.get(0)); - Assert.assertEquals(9, (int) intersection.get(1)); - - - } -} diff --git a/group01/765324639/src/zavier/week01/test/QueueTest.java b/group01/765324639/src/zavier/week01/test/QueueTest.java deleted file mode 100644 index 99d6466c8a..0000000000 --- a/group01/765324639/src/zavier/week01/test/QueueTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package zavier.week01.test; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import zavier.week01.basic.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/zavier/week01/test/StackTest.java b/group01/765324639/src/zavier/week01/test/StackTest.java deleted file mode 100644 index 8138f97d3d..0000000000 --- a/group01/765324639/src/zavier/week01/test/StackTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package zavier.week01.test; - -import java.util.EmptyStackException; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import zavier.week01.basic.Stack; - - -public class StackTest { - - private Stack stack = new Stack(); - - @Before - public void setUp() { - for (int i = 0; i < 500; i++) { - stack.push(i); - } - } - - @Test - public void testPush() { - for (int i = 0; i < 100; i++) { - stack.push(i); - } - Assert.assertEquals(600, stack.size()); - } - - @Test(expected = EmptyStackException.class) - public void testPop() { - for (int i = 0; i < 500; i++) { - Assert.assertEquals(499 - i, stack.pop()); - } - stack.pop(); - } - - @Test - public void testPeek() { - Assert.assertEquals(499, stack.peek()); - Assert.assertEquals(499, stack.peek()); - stack.pop(); - Assert.assertEquals(498, stack.peek()); - } - - @Test - public void testIsEmpty() { - Assert.assertFalse(stack.isEmpty()); - Assert.assertTrue(new Stack().isEmpty()); - } - - @Test - public void testSize() { - Assert.assertEquals(500, stack.size()); - stack.pop(); - Assert.assertEquals(499, stack.size()); - } - -} diff --git a/group01/765324639/src/zavier/week02/coderising/array/ArrayUtil.java b/group01/765324639/src/zavier/week02/coderising/array/ArrayUtil.java deleted file mode 100644 index 96bff301c7..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,263 +0,0 @@ -package zavier.week02.coderising.array; - -import zavier.week01.basic.ArrayList; -import zavier.week01.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) { - if (origin == null) { - throw new IllegalArgumentException(); - } - - int temp; - for (int i = 0; i < origin.length / 2; i++) { - 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) { - throw new IllegalArgumentException(); - } - - int[] noZeroArray = new int[oldArray.length]; - int index = 0; - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] != 0) { - noZeroArray[index++] = oldArray[i]; - } - } - - return copyOf(noZeroArray, index); - } - - /** - * 给定两个已经排序好的整形数组, 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) { - throw new IllegalArgumentException(); - } - - int indexOfArray1 = 0; - int indexOfArray2 = 0; - int totalLength = array1.length + array2.length; - int[] destArr = new int[totalLength]; - - for (int i = 0; i < totalLength; i++) { - if (indexOfArray1 >= array1.length) { - // array1填充完毕,将array2填充剩下的元素 - arrayCopy(array2, indexOfArray2, destArr, i, array2.length - indexOfArray2); - int actualSize = i + array2.length - indexOfArray2; - return copyOf(destArr, actualSize); - } - - if (indexOfArray2 >= array2.length) { - arrayCopy(array1, indexOfArray1, destArr, i, array1.length - indexOfArray1); - int actualSize = i + array1.length - indexOfArray1; - return copyOf(destArr, actualSize); - } - - if (array1[indexOfArray1] < array2[indexOfArray2]) { - destArr[i] = array1[indexOfArray1]; - indexOfArray1++; - } else if (array1[indexOfArray1] == array2[indexOfArray2]) { - destArr[i] = array1[indexOfArray1]; - indexOfArray1++; - indexOfArray2++; // 去除重复元素 - } else { - destArr[i] = array2[indexOfArray2]; - indexOfArray2++; - } - - } - // array1.length、array2.length均为0的情况 - return new int[0]; - } - - private void arrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length) { - for (int i = 0; i < length; i++) { - dest[destPos++] = src[srcPos++]; - } - } - - private int[] copyOf(int[] original, int newLength) { - int[] dest = new int[newLength]; - for (int i = 0; i < newLength; i++) { - dest[i] = original[i]; - } - return dest; - } - - /** - * 把一个已经存满数据的数组 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 || size < 0) { - throw new IllegalArgumentException(); - } - - int newSize = oldArray.length + size; - int[] newArray = new int[newSize]; - 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 int[] fibonacci(int max) { - if (max < 0) { - throw new IllegalArgumentException(); - } - if (max == 1) { - return new int[] {}; - } - - ArrayList list = new ArrayList(); - list.add(1); - list.add(1); - - int i = 0; - while (true) { - int num = (int) list.get(i) + (int) list.get(i + 1); - if (num < max) { - list.add(num); - } else { - break; - } - i++; - } - - return intListToArray(list); - } - - private int[] intListToArray(List list) { - int[] array = new int[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = (int) list.get(i); - } - return array; - } - - /** - * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public int[] getPrimes(int max) { - if (max < 0) { - throw new IllegalArgumentException(); - } - - ArrayList list = new ArrayList(); - for (int i = 2; i < max; i++) { - if (isPrime(i)) { - list.add(i); - } - } - return intListToArray(list); - } - - private boolean isPrime(int num) { - 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) { - throw new IllegalArgumentException(); - } - - ArrayList list = new ArrayList(); - for (int i = 2; i < max; i++) { - if (isPerfectNumber(i)) { - list.add(i); - } - } - return intListToArray(list); - } - - private boolean isPerfectNumber(int num) { - int sumOfFactor = 1; - for (int i = 2; i <= num / 2; i++) { - if (num % i == 0) { - sumOfFactor += i; - } - } - if (sumOfFactor == num) { - return true; - } - 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) { - throw new IllegalArgumentException(); - } - if (array.length == 0) { - return ""; - } - - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - builder.append(array[i]).append(seperator); - } - return builder.substring(0, builder.length() - seperator.length()); - } - - -} diff --git a/group01/765324639/src/zavier/week02/coderising/array/ArrayUtilTest.java b/group01/765324639/src/zavier/week02/coderising/array/ArrayUtilTest.java deleted file mode 100644 index d0e6fa11d8..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/array/ArrayUtilTest.java +++ /dev/null @@ -1,133 +0,0 @@ -package zavier.week02.coderising.array; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class ArrayUtilTest { - - private ArrayUtil arrayUtil; - - @Before - public void setUp() { - arrayUtil = new ArrayUtil(); - } - - @Test - public void testReverseArray() { - int[] a = {}; - arrayUtil.reverseArray(a); - Assert.assertArrayEquals(new int[] {}, a); - - int[] b = {1, 2, 3}; - arrayUtil.reverseArray(b); - Assert.assertArrayEquals(new int[] {3, 2, 1}, b); - - int[] c = {1, 2, 3, 4}; - arrayUtil.reverseArray(c); - Assert.assertArrayEquals(new int[] {4, 3, 2, 1}, c); - - int[] d = new int[5000]; - int[] d1 = new int[5000]; - for (int i = 0; i < 5000; i++) { - d[i] = i; - d1[i] = 4999 - i; - } - arrayUtil.reverseArray(d); - Assert.assertArrayEquals(d1, d); - } - - @Test(expected = IllegalArgumentException.class) - public void testRemoveZero() { - int oldArr1[] = {1, 3, 4, 5, 0, 0, 6, 6, 0, 5, 4, 7, 6, 7, 0, 5}; - int newArr1[] = {1, 3, 4, 5, 6, 6, 5, 4, 7, 6, 7, 5}; - Assert.assertArrayEquals(newArr1, arrayUtil.removeZero(oldArr1)); - - int oldArr2[] = {0, 0, 0, 0, 0}; - int newArr2[] = {}; - Assert.assertArrayEquals(newArr2, arrayUtil.removeZero(oldArr2)); - - int oldArr3[] = {0, 0, 0, 0, 0, 1, 2, 3}; - int newArr3[] = {1, 2, 3}; - Assert.assertArrayEquals(newArr3, arrayUtil.removeZero(oldArr3)); - - int oldArr4[] = {1, 2, 3, 0, 0, 0, 0, 0}; - int newArr4[] = {1, 2, 3}; - Assert.assertArrayEquals(newArr4, arrayUtil.removeZero(oldArr4)); - - int oldArr5[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0}; - int newArr5[] = {1, 2, 3, 4}; - Assert.assertArrayEquals(newArr5, arrayUtil.removeZero(oldArr5)); - - int oldArr6[] = {}; - int newArr6[] = {}; - Assert.assertArrayEquals(newArr6, oldArr6); - - arrayUtil.removeZero(null); - } - - @Test - public void testMerge() { - int[] a1 = {3, 5, 7, 8}; - int[] a2 = {4, 5, 6, 7}; - Assert.assertArrayEquals(new int[] {3, 4, 5, 6, 7, 8}, arrayUtil.merge(a1, a2)); - - int[] b1 = {1, 2, 9, 100}; - int[] b2 = {3, 4, 5, 90, 100}; - Assert.assertArrayEquals(new int[] {1, 2, 3, 4, 5, 9, 90, 100}, arrayUtil.merge(b1, b2)); - - int[] c1 = {}; - int[] c2 = {1, 2, 3}; - Assert.assertArrayEquals(new int[] {1, 2, 3}, arrayUtil.merge(c1, c2)); - - int[] d1 = {}; - int[] d2 = {}; - Assert.assertArrayEquals(new int[] {}, arrayUtil.merge(d1, d2)); - } - - @Test - public void testGrow() { - int[] a1 = {2, 3, 6}; - Assert.assertArrayEquals(new int[] {2, 3, 6, 0, 0, 0}, arrayUtil.grow(a1, 3)); - Assert.assertArrayEquals(new int[] {2, 3, 6}, arrayUtil.grow(a1, 0)); - } - - @Test - public void testFibonacci() { - Assert.assertArrayEquals(new int[] {}, arrayUtil.fibonacci(1)); - Assert.assertArrayEquals(new int[] {1, 1, 2, 3, 5, 8, 13}, arrayUtil.fibonacci(15)); - - int[] a = new int[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, - 2584, 4181, 6765}; - Assert.assertArrayEquals(a, arrayUtil.fibonacci(6766)); - } - - @Test - public void testGetPrimes() { - Assert.assertArrayEquals(new int[] {}, arrayUtil.getPrimes(1)); - Assert.assertArrayEquals(new int[] {}, arrayUtil.getPrimes(2)); - Assert.assertArrayEquals(new int[] {2, 3, 5, 7, 11, 13, 17, 19}, arrayUtil.getPrimes(23)); - Assert.assertArrayEquals(new int[] {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, - 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, - 149, 151, 157, 163, 167, 173, 179}, arrayUtil.getPrimes(181)); - } - - @Test - public void testGetPerfectNumbers() { - Assert.assertArrayEquals(new int[] {6}, arrayUtil.getPerfectNumbers(7)); - Assert.assertArrayEquals(new int[] {6, 28}, arrayUtil.getPerfectNumbers(496)); - Assert.assertArrayEquals(new int[] {6, 28, 496}, arrayUtil.getPerfectNumbers(497)); - Assert.assertArrayEquals(new int[] {6, 28, 496, 8128}, arrayUtil.getPerfectNumbers(8129)); - - } - - @Test - public void testJoin() { - Assert.assertEquals("", arrayUtil.join(new int[] {}, "-")); - Assert.assertEquals("1", arrayUtil.join(new int[] {1}, "-")); - Assert.assertEquals("1-2-8-3-4-5", arrayUtil.join(new int[] {1, 2, 8, 3, 4, 5}, "-")); - Assert.assertEquals("1*-*2*-*8*-*3*-*4*-*5", - arrayUtil.join(new int[] {1, 2, 8, 3, 4, 5}, "*-*")); - } - -} diff --git a/group01/765324639/src/zavier/week02/coderising/litestruts/LoginAction.java b/group01/765324639/src/zavier/week02/coderising/litestruts/LoginAction.java deleted file mode 100644 index 617b5f115b..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/litestruts/LoginAction.java +++ /dev/null @@ -1,42 +0,0 @@ -package zavier.week02.coderising.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/group01/765324639/src/zavier/week02/coderising/litestruts/Struts.java b/group01/765324639/src/zavier/week02/coderising/litestruts/Struts.java deleted file mode 100644 index d30beaafb3..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/litestruts/Struts.java +++ /dev/null @@ -1,117 +0,0 @@ -package zavier.week02.coderising.litestruts; - -import java.io.InputStream; -import java.lang.reflect.Method; -import java.util.HashMap; -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 { - - 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 { - - SAXReader reader = new SAXReader(); - InputStream struts = Struts.class.getResourceAsStream("struts.xml"); - Document document = null; - try { - document = reader.read(struts); - } catch (DocumentException e) { - e.printStackTrace(); - } - - String className = ""; // actionName对应的类名 - Element rootElement = document.getRootElement(); - Iterator iterator = rootElement.elementIterator("action"); - Element targetAction = null; // actionName对应的action - while (iterator.hasNext()) { - Element element = (Element) iterator.next(); - String name = element.attributeValue("name"); - if (name.equals(actionName)) { - className = element.attributeValue("class"); - targetAction = element; - break; - } - } - - - Class class1 = Class.forName(className); - Object instance = class1.newInstance(); - - Set keySet = parameters.keySet(); - for (String key : keySet) { - // 将变量名拼成对应的set方法名 - String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1); - Class type = class1.getDeclaredField(key).getType(); - Method method = class1.getDeclaredMethod(methodName, type); - // 依次调用对应的set方法 - method.invoke(instance, parameters.get(key)); - } - - String result = (String) class1.getDeclaredMethod("execute").invoke(instance); - - Method[] declaredMethods = class1.getDeclaredMethods(); - HashMap map = new HashMap<>(); - for (int i = 0; i < declaredMethods.length; i++) { - if (declaredMethods[i].getName().startsWith("get")) { - String fieldValue = (String) declaredMethods[i].invoke(instance); - String fieldName = methodNameToFieldName(declaredMethods[i].getName()); - map.put(fieldName, fieldValue); - } - } - - View view = new View(); - view.setParameters(map); - - Iterator elementIterator = targetAction.elementIterator("result"); - while (elementIterator.hasNext()) { - Element element = (Element) elementIterator.next(); - if (result.equals(element.attributeValue("name"))) { - view.setJsp(element.getText()); - } - } - - return view; - - - } catch (Exception e1) { - e1.printStackTrace(); - } - - return null; - } - - private static String methodNameToFieldName(String methodName) { - if (!methodName.startsWith("get") && !methodName.startsWith("set")) { - throw new IllegalArgumentException(); - } - - return methodName.substring(3, 4).toLowerCase() + methodName.substring(4); - } - -} diff --git a/group01/765324639/src/zavier/week02/coderising/litestruts/StrutsTest.java b/group01/765324639/src/zavier/week02/coderising/litestruts/StrutsTest.java deleted file mode 100644 index ba800c2fdc..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/litestruts/StrutsTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package zavier.week02.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/group01/765324639/src/zavier/week02/coderising/litestruts/View.java b/group01/765324639/src/zavier/week02/coderising/litestruts/View.java deleted file mode 100644 index f164c4bfc5..0000000000 --- a/group01/765324639/src/zavier/week02/coderising/litestruts/View.java +++ /dev/null @@ -1,26 +0,0 @@ -package zavier.week02.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/group01/765324639/src/zavier/week02/coderising/litestruts/struts.xml b/group01/765324639/src/zavier/week02/coderising/litestruts/struts.xml deleted file mode 100644 index ffe9110788..0000000000 --- a/group01/765324639/src/zavier/week02/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/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java b/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java deleted file mode 100644 index f94c97b8b1..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/DownloadThread.java +++ /dev/null @@ -1,44 +0,0 @@ -package zavier.week03.coderising.download; - -import java.io.IOException; -import java.io.RandomAccessFile; - -import zavier.week03.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; - - } - - @Override - public void run() { - byte[] data = new byte[endPos - startPos]; - try { - data = conn.read(startPos, endPos); - } catch (IOException e) { - e.printStackTrace(); - } - writeToFile(data); - } - - private void writeToFile(byte[] data) { - RandomAccessFile file; - try { - file = new RandomAccessFile("download20170311.jpg", "rw"); - file.seek(startPos); - file.write(data, 0, data.length); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java b/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java deleted file mode 100644 index ff2db12f50..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/FileDownloader.java +++ /dev/null @@ -1,87 +0,0 @@ -package zavier.week03.coderising.download; - -import zavier.week03.coderising.download.api.Connection; -import zavier.week03.coderising.download.api.ConnectionException; -import zavier.week03.coderising.download.api.ConnectionManager; -import zavier.week03.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 { - - conn = cm.open(this.url); - - int length = conn.getContentLength(); - - DownloadThread downloadThread1 = new DownloadThread(conn, 0, length / 3); - downloadThread1.start(); - DownloadThread downloadThread2 = - new DownloadThread(conn, length / 3 + 1, length / 3 * 2); - downloadThread2.start(); - DownloadThread downloadThread3 = - new DownloadThread(conn, length / 3 * 2 + 1, length - 1); - downloadThread3.start(); - try { - downloadThread1.join(); - downloadThread2.join(); - downloadThread3.join(); - listener.notifyFinished(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - } 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/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java b/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java deleted file mode 100644 index bf67e8d494..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/FileDownloaderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package zavier.week03.coderising.download; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import zavier.week03.coderising.download.api.ConnectionManager; -import zavier.week03.coderising.download.api.DownloadListener; -import zavier.week03.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://121.42.185.101/forum/test.jpg"; - - FileDownloader downloader = new FileDownloader(url); - - - ConnectionManager cm = new ConnectionManagerImpl(); - downloader.setConnectionManager(cm); - - downloader.setListener(new DownloadListener() { - @Override - public void notifyFinished() { - downloadFinished = true; - } - - }); - - new Thread() { - @Override - public void run() { - downloader.execute(); - } - }.start(); - - // 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - // 休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); - - - - } - -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java b/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java deleted file mode 100644 index 4763202fab..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/api/Connection.java +++ /dev/null @@ -1,26 +0,0 @@ -package zavier.week03.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/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java deleted file mode 100644 index 5df32804de..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionException.java +++ /dev/null @@ -1,5 +0,0 @@ -package zavier.week03.coderising.download.api; - -public class ConnectionException extends Exception { - -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java b/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java deleted file mode 100644 index 81f5f34f72..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/api/ConnectionManager.java +++ /dev/null @@ -1,11 +0,0 @@ -package zavier.week03.coderising.download.api; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * - * @param url - * @return - */ - public Connection open(String url) throws ConnectionException; -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java b/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java deleted file mode 100644 index f72ecd263d..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package zavier.week03.coderising.download.api; - -public interface DownloadListener { - public void notifyFinished(); -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java deleted file mode 100644 index b297beef54..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -package zavier.week03.coderising.download.impl; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; - -import zavier.week03.coderising.download.api.Connection; - -public class ConnectionImpl implements Connection { - - private URL url = null;; - - private HttpURLConnection conn = null; - - public ConnectionImpl(String url) { - try { - this.url = new URL(url); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } - - @Override - public byte[] read(int startPos, int endPos) throws IOException { - try { - conn = (HttpURLConnection) url.openConnection(); - } catch (IOException e) { - e.printStackTrace(); - } - conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - InputStream inputStream = conn.getInputStream(); - byte[] result = new byte[endPos - startPos + 1]; - byte[] data = new byte[1024]; - int read = -1; - int i = 0; - while ((read = inputStream.read(data, 0, data.length)) != -1) { - System.arraycopy(data, 0, result, i, read); - i += read; - } - return result; - } - - @Override - public int getContentLength() { - HttpURLConnection openConnection = null; - try { - openConnection = (HttpURLConnection) url.openConnection(); - } catch (IOException e) { - e.printStackTrace(); - } - int contentLength = openConnection.getContentLength(); - openConnection.disconnect(); - return contentLength; - } - - @Override - public void close() { - conn.disconnect(); - conn = null; - } - -} diff --git a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java b/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index d6828e7ae8..0000000000 --- a/group01/765324639/src/zavier/week03/coderising/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package zavier.week03.coderising.download.impl; - -import zavier.week03.coderising.download.api.Connection; -import zavier.week03.coderising.download.api.ConnectionException; -import zavier.week03.coderising.download.api.ConnectionManager; - -public class ConnectionManagerImpl implements ConnectionManager { - - @Override - public Connection open(String url) throws ConnectionException { - return new ConnectionImpl(url); - } - -} diff --git a/group01/765324639/src/zavier/week04/coderising/jvm/loader/ClassFileLoader.java b/group01/765324639/src/zavier/week04/coderising/jvm/loader/ClassFileLoader.java deleted file mode 100644 index 92a3fcfe02..0000000000 --- a/group01/765324639/src/zavier/week04/coderising/jvm/loader/ClassFileLoader.java +++ /dev/null @@ -1,72 +0,0 @@ -package zavier.week04.coderising.jvm.loader; - -import java.io.ByteArrayOutputStream; -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; - - - -public class ClassFileLoader { - - private List clzPaths = new ArrayList(); - - public byte[] readBinaryCode(String className) throws ClassNotFoundException { - File classFile = getClassFile(className); - return readFileToByteArray(classFile); - } - - private File getClassFile(String className) throws ClassNotFoundException { - File classFile = null; - String classFilePath = convertClassNameToFilePath(className); - for (String path : clzPaths) { - File file = new File(path, classFilePath); - if (file.exists()) { - classFile = file; - break; - } - } - - if (classFile == null) { // 文件不存在 - throw new ClassNotFoundException(); - } - return classFile; - } - - private byte[] readFileToByteArray(File classFile) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try (InputStream in = new FileInputStream(classFile);) { - byte[] data = new byte[1024]; - int len = -1; - while ((len = in.read(data)) != -1) { - out.write(data, 0, len); - } - } catch (FileNotFoundException e) { // 调用此函数时,已经确定文件是存在的 - e.printStackTrace(); - } catch (IOException e1) { - e1.printStackTrace(); - } - return out.toByteArray(); - } - - private String convertClassNameToFilePath(String fillClassName) { - return fillClassName.replace(".", "\\") + ".class"; - } - - public void addClassPath(String path) { - clzPaths.add(path); - } - - - - public String getClassPath() { - return String.join(";", clzPaths); - } - - - -} diff --git a/group01/765324639/src/zavier/week04/coderising/jvm/test/ClassFileloaderTest.java b/group01/765324639/src/zavier/week04/coderising/jvm/test/ClassFileloaderTest.java deleted file mode 100644 index 66855937f4..0000000000 --- a/group01/765324639/src/zavier/week04/coderising/jvm/test/ClassFileloaderTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package zavier.week04.coderising.jvm.test; - -import java.io.File; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import zavier.week04.coderising.jvm.loader.ClassFileLoader; - - - -public class ClassFileloaderTest { - - - static String path1 = new File(".", "bin").getAbsolutePath(); - static String path2 = "C:\\temp"; - - static String className = EmployeeV1.class.getName(); - - @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() throws ClassNotFoundException { - - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - - byte[] byteCodes = loader.readBinaryCode(className); - - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 - Assert.assertEquals(1076, byteCodes.length); - - } - - @Test(expected = ClassNotFoundException.class) - public void testClassNotFindException() throws ClassNotFoundException { - ClassFileLoader loader = new ClassFileLoader(); - loader.readBinaryCode(className); - } - - - @Test - public void testMagicNumber() throws ClassNotFoundException { - ClassFileLoader loader = new ClassFileLoader(); - loader.addClassPath(path1); - 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(); - } - -} diff --git a/group01/765324639/src/zavier/week04/coderising/jvm/test/EmployeeV1.java b/group01/765324639/src/zavier/week04/coderising/jvm/test/EmployeeV1.java deleted file mode 100644 index 57c7517767..0000000000 --- a/group01/765324639/src/zavier/week04/coderising/jvm/test/EmployeeV1.java +++ /dev/null @@ -1,31 +0,0 @@ -package zavier.week04.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(); - - } -} diff --git a/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrame.java b/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrame.java deleted file mode 100644 index eb82d94d5e..0000000000 --- a/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrame.java +++ /dev/null @@ -1,177 +0,0 @@ -package zavier.week04.coderising.linklist; - -/** - * 用双向链表实现LRU算法 - * - * @author liuxin - * - */ -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; - } - - /** - * 获取缓存中对象 - * - * @param key - * @return - */ - public void access(int pageNum) { - if (isEmpty()) { - initFirstNode(pageNum); - return; - } - - if (contains(pageNum)) { - moveToFirst(pageNum); - } else { - insert(pageNum); - } - } - - private void initFirstNode(int pageNum) { - Node node = new Node(pageNum); - first = last = node; - size++; - } - - private void moveToFirst(int pageNum) { - if (isFirst(pageNum)) { - return; - } - if (isLast(pageNum)) { - moveLastToFirst(); - } else { - moveMidToFirst(pageNum); - } - } - - private void moveLastToFirst() { - Node temp = last; - - removeLast(); - - addToFirst(temp); - } - - private void addToFirst(Node temp) { - temp.next = first; - first.prev = temp; - first = temp; - size++; - } - - private void moveMidToFirst(int pageNum) { - Node node = removeMidNode(pageNum); - addToFirst(node); - } - - private Node removeMidNode(int pageNum) { - Node temp = getNode(pageNum); - temp.prev.next = temp.next; - temp.next.prev = temp.prev; - - temp.next = null; - temp.prev = null; - - size--; - - return temp; - } - - private void insert(int pageNum) { - if (isFill()) { - removeLast(); - } - insertToFirst(pageNum); - } - - private void removeLast() { - last = last.prev; - last.next = null; - size--; - } - - private void insertToFirst(int pageNum) { - Node node = new Node(pageNum); - - addToFirst(node); - } - - private boolean contains(int pageNum) { - return indexOf(pageNum) != -1; - } - - private int indexOf(int num) { - Node temp = first; - for (int i = 0; i < size; i++) { - if (temp.pageNum == num) { - return i; - } - temp = temp.next; - } - return -1; - } - - private Node getNode(int pageNum) { - Node temp; - temp = first; - for (int i = 0; i < size; i++) { - if (temp.pageNum == pageNum) { - break; - } - temp = temp.next; - } - return temp; - } - - private boolean isEmpty() { - return size == 0; - } - - private boolean isFirst(int pageNum) { - return first.pageNum == pageNum; - } - - private boolean isLast(int pageNum) { - return last.pageNum == pageNum; - } - - private boolean isFill() { - return size == capacity; - } - - @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/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrameTest.java b/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrameTest.java deleted file mode 100644 index 9b69297e21..0000000000 --- a/group01/765324639/src/zavier/week04/coderising/linklist/LRUPageFrameTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package zavier.week04.coderising.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/group01/895457260/code/src/main/java/algorithm/ArrayUtil.java b/group01/895457260/code/src/main/java/algorithm/ArrayUtil.java index bb5a25a93a..4ac933f4f3 100644 --- a/group01/895457260/code/src/main/java/algorithm/ArrayUtil.java +++ b/group01/895457260/code/src/main/java/algorithm/ArrayUtil.java @@ -96,7 +96,7 @@ public int[] merge(int[] array1, int[] array2) { return newArray; } /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.size + size * 注意,老数组的元素在新数组中需要保持 * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 * [2,3,6,0,0,0] diff --git a/group01/895457260/code/src/main/java/algorithm/InfixExpr.java b/group01/895457260/code/src/main/java/algorithm/InfixExpr.java new file mode 100644 index 0000000000..1ddb740364 --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/InfixExpr.java @@ -0,0 +1,140 @@ +package algorithm; + +import datastructure.basic.Stack; + +import java.util.ArrayList; +import java.util.List; + +public class InfixExpr { + + Stack numbers = new Stack(); + Stack operators = new Stack(); + + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + operators.push("#"); + } + + public float evaluate() throws CalculateException { + numbers.clear(); + operators.clear(); + operators.push("#"); + + String[] split = split(expr); + String[] strs = new String[split.length + 1]; + strs[strs.length - 1] = "#"; + System.arraycopy(split, 0, strs, 0, split.length); + + for (int i = 0; !operators.isEmpty() && i < strs.length; ++i) { + String str = strs[i]; + try { + float number = Float.parseFloat(str); + putNumber(number); + } catch (NumberFormatException e) { + putOperator(str); + } + } + return numbers.isEmpty() ? 0 : (float) numbers.peek(); + } + + private String[] split(String expr) { + List list = new ArrayList<>(); + int startPos = 0; + for (int i = 0, j = 1; j < expr.length(); ++i, ++j) { + char cI = expr.charAt(i); + char cJ = expr.charAt(j); + if (isDigit(cI) ^ isDigit(cJ)) { + list.add(expr.substring(startPos, j)); + startPos = j; + } + } + list.add(expr.substring(startPos)); + return list.toArray(new String[list.size()]); + } + + private boolean isDigit(char c) { + return Character.isDigit(c) || c == '.'; + } + + private void putNumber(float num) { + numbers.push(num); + } + + private void putOperator(String op) throws CalculateException { + int compare = compare(op, (String) operators.peek()); + switch (compare) { + case 1: + operators.push(op); + break; + case 0: + operators.pop(); + break; + case -1: + float num1 = (float) numbers.pop(); + float num2 = (float) numbers.pop(); + String operator = (String) operators.pop(); + float result = calculate(num2, operator, num1); + numbers.push(result); + putOperator(op); + break; + } + } + + private float calculate(float num2, String op, float num1) throws CalculateException { + switch (op) { + case "+": + return num2 + num1; + case "-": + return num2 - num1; + case "*": + return num2 * num1; + case "/": + if (num1 != 0) { + return num2 / num1; + } + } + throw new CalculateException(); + } + + private int compare(String op, String peek) { + int opIndex = indexOf(op); + int peekIndex = indexOf(peek); + return table[opIndex][peekIndex]; + } + + private int indexOf(String op) { + switch (op) { + case "+": + return 0; + case "-": + return 1; + case "*": + return 2; + case "/": + return 3; + case "(": + return 4; + case ")": + return 5; + case "#": + return 6; + } + return 0; + } + + //优先级表 + private int[][] table = { + // + - * / ( ) # + {-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} // # + }; + + public static class CalculateException extends Exception {} +} diff --git a/group01/895457260/code/src/main/java/algorithm/StackUtil.java b/group01/895457260/code/src/main/java/algorithm/StackUtil.java new file mode 100644 index 0000000000..1b8ecf63de --- /dev/null +++ b/group01/895457260/code/src/main/java/algorithm/StackUtil.java @@ -0,0 +1,99 @@ +package algorithm; + +import datastructure.basic.Stack; + +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 reverse = new Stack(); + while (!s.isEmpty()) { + reverse.push(s.pop()); + } + Stack reverseAgain = new Stack(); + while (!reverse.isEmpty()) { + reverseAgain.push(reverse.pop()); + } + while (!reverseAgain.isEmpty()) { + s.push(reverseAgain.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack temp = new Stack(); + while (!s.isEmpty()) { + Object pop = s.pop(); + if (!pop.equals(o)) { + temp.push(pop); + } + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + Stack temp = new Stack(); + for (int i = 0; i < len && !s.isEmpty(); ++i) { + temp.push(s.pop()); + } + Object[] result = new Object[temp.size()]; + for (int i = 0; i < result.length; ++i) { + result[i] = temp.pop(); + s.push(result[i]); + } + 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 brackets = new Stack(); + char[] chars = s.toCharArray(); + + for (char c : chars) { + if (isBracket(c)) { + if (!brackets.isEmpty() && isPair((Character) brackets.peek(), c)) { + brackets.pop(); + } else { + brackets.push(c); + } + } + } + return brackets.isEmpty(); + } + + private static boolean isBracket(char c) { + return c == '(' || c == ')' + || c == '[' || c == ']' + || c == '{' || c == '}'; + } + + private static boolean isPair(char left, char right) { + return (left == '(' && right == ')') + || (left == '[' && right == ']') + || (left == '{' && right == '}'); + } +} 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 ab4fc874ae..eeb9c7afba 100644 --- a/group01/895457260/code/src/main/java/datastructure/basic/Stack.java +++ b/group01/895457260/code/src/main/java/datastructure/basic/Stack.java @@ -29,4 +29,8 @@ public boolean isEmpty() { public int size() { return elementData.size(); } + + public void clear() { + elementData = new ArrayList(); + } } diff --git a/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java b/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java index 53e401c119..ade626ad83 100644 --- a/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java +++ b/group01/895457260/code/src/main/java/jvm/ClassFileLoader.java @@ -1,9 +1,12 @@ package jvm; +import jvm.classfile.ClassFile; +import jvm.classfile.ClassParser; import jvm.exception.ClassDuplicateException; import jvm.exception.ClassNotExistsException; import jvm.exception.ReadClassException; import jvm.util.ArrayUtils; +import jvm.util.ByteUtils; import java.io.*; import java.util.ArrayList; @@ -69,12 +72,16 @@ public String getClassPath() { } boolean checkMagicNumber(byte[] bytes) { - String magicNumber = "CAFEBABE"; - String str = ""; - int byteNum = 4; - for (int i = 0; i < byteNum; ++i) { - str += Integer.toHexString(Byte.toUnsignedInt(bytes[i])); + String magicNumber = "cafebabe"; + String str = ByteUtils.toHexString(bytes, 0, 4); + return magicNumber.equals(str.toLowerCase()); + } + + public ClassFile load(String className) throws ReadClassException { + byte[] bytes = readBinaryCode(className); + if (checkMagicNumber(bytes)) { + return ClassParser.parse(bytes); } - return magicNumber.equals(str.toUpperCase()); + return null; } } diff --git a/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java b/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java new file mode 100644 index 0000000000..18c327fb0d --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/AccessFlag.java @@ -0,0 +1,30 @@ +package jvm.classfile; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class AccessFlag { + int flagValue; + + public AccessFlag() {} + + 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/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java new file mode 100644 index 0000000000..41f983a086 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassFile.java @@ -0,0 +1,75 @@ +package jvm.classfile; + + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.field.Field; +import jvm.classfile.method.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ClassFile { + ClassIndex classIndex; + AccessFlag accessFlag; + ConstantPool constantPool; + int minorVersion; + int majorVersion; + List interfaces = new ArrayList<>(); + List fields = new ArrayList<>(); + List methods = new ArrayList<>(); + List attributes = new ArrayList<>(); + + public List getInterfaces() { + return this.interfaces; + } + public List getFields() { + return this.fields; + } + public List getMethods() { + return methods; + } + public List getAttributes() { + return attributes; + } + + 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.classIndex.getThisClassIndex(); + ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + + private String getSuperClassName() { + ClassInfo superClass = (ClassInfo)this.getConstantPool() + .getConstantInfo(this.classIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + public int getMinorVersion() { + return minorVersion; + } + + public int getMajorVersion() { + return majorVersion; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ClassIndex getClzIndex() { + return classIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassIndex.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassIndex.java new file mode 100644 index 0000000000..dc3891698d --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassIndex.java @@ -0,0 +1,18 @@ +package jvm.classfile; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ClassIndex { + int thisClass; + int superClass; + + public int getThisClassIndex() { + return thisClass; + } + + public int getSuperClassIndex() { + return superClass; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java new file mode 100644 index 0000000000..fa3a07527d --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/ClassParser.java @@ -0,0 +1,113 @@ +package jvm.classfile; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.parser.AttributeParser; +import jvm.classfile.constant.item.IReference; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.item.impl.CountConstant; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.classfile.constant.parser.ConstantParserFactory; +import jvm.classfile.field.Field; +import jvm.classfile.method.Method; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ClassParser { + public static ClassFile parse(byte[] bytes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(bytes); + + iterator.skip(4); // skip magic number + + classFile.minorVersion = parseMinorVersion(iterator); + classFile.majorVersion = parseMajorVersion(iterator); + classFile.constantPool = parseConstantPool(iterator); + classFile.accessFlag = parseAccessFlag(iterator); + classFile.classIndex = parseClassIndex(iterator); + parseInterfaces(classFile, iterator); + parseFields(classFile, iterator); + parseMethods(classFile, iterator); + parseAttributes(classFile, iterator); + linkConstantReferences(classFile); + return classFile; + } + + private static void parseAttributes(ClassFile classFile, ByteCodeIterator iterator) { + int count = iterator.nextU2ToInt(); + for (int i = 0; i < count; ++i) { + AttributeInfo attribute = AttributeParser.parse(iterator, classFile.constantPool); + classFile.attributes.add(attribute); + } + } + + private static int parseMinorVersion(ByteCodeIterator iterator) { + return iterator.nextU2ToInt(); + } + + private static int parseMajorVersion(ByteCodeIterator iterator) { + return iterator.nextU2ToInt(); + } + + private static ConstantPool parseConstantPool(ByteCodeIterator iterator) { + ConstantPool constantPool = new ConstantPool(); + + int count = iterator.nextU2ToInt(); + constantPool.addConstantInfo(new CountConstant(count)); + + for (int i = 1; i < count; ++i) { + int tag = iterator.nextU1ToInt(); + ConstantParser parser = ConstantParserFactory.get(tag); + constantPool.addConstantInfo(parser.parse(iterator)); + } + return constantPool; + } + + private static AccessFlag parseAccessFlag(ByteCodeIterator iterator) { + AccessFlag accessFlag = new AccessFlag(); + accessFlag.flagValue = iterator.nextU2ToInt(); + return accessFlag; + } + + private static ClassIndex parseClassIndex(ByteCodeIterator iterator) { + ClassIndex classIndex = new ClassIndex(); + classIndex.thisClass = iterator.nextU2ToInt(); + classIndex.superClass = iterator.nextU2ToInt(); + return classIndex; + } + + private static void parseInterfaces(ClassFile classFile, ByteCodeIterator iterator) { + int count = iterator.nextU2ToInt(); + ConstantPool constantPool = classFile.constantPool; + for (int i = 0; i < count; ++i) { + int index = iterator.nextU2ToInt(); + ClassInfo info = (ClassInfo) constantPool.getConstantInfo(index); + classFile.interfaces.add(info); + } + } + + 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)); + } + } + + private static void parseMethods(ClassFile classFile, ByteCodeIterator iterator) { + int count = iterator.nextU2ToInt(); + for (int i = 0; i < count; ++i) { + classFile.methods.add(Method.parse(iterator, classFile.constantPool)); + } + } + + private static void linkConstantReferences(ClassFile classFile) { + ConstantPool constantPool = classFile.constantPool; + constantPool.forEach(c -> { + if (c instanceof IReference) { + ((IReference) c).linkReference(constantPool); + } + }); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java b/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java new file mode 100644 index 0000000000..b077ad83a4 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/ConstantPool.java @@ -0,0 +1,30 @@ +package jvm.classfile; + +import jvm.classfile.constant.item.Constant; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ConstantPool { + private List constantMap = new ArrayList<>(); + + public void forEach(Consumer action) { + constantMap.forEach(action); + } + + public int getSize() { + return constantMap.size() - 1; + } + + boolean addConstantInfo(Constant c) { + return constantMap.add(c); + } + public Constant getConstantInfo(int index) { + return constantMap.get(index); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java new file mode 100644 index 0000000000..595c12ac9b --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/AttributeInfo.java @@ -0,0 +1,18 @@ +package jvm.classfile.attribute.item; + +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/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java new file mode 100644 index 0000000000..75c7383bd8 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/CodeAttr.java @@ -0,0 +1,38 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +import java.util.ArrayList; +import java.util.List; + +public class CodeAttr extends AttributeInfo { + private int maxStack; + private int maxLocals; + private int codeLen; + private String code; + private List attributes = new ArrayList<>(); + //private ByteCodeCommand[] cmds ; + + //public ByteCodeCommand[] getCmds() { + // return cmds; + //} + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, + int codeLen, String code, List attributes /*ByteCodeCommand[] cmds*/) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + this.attributes = attributes; + //this.cmds = cmds; + } + + public String getCode() { + return code; + } + + public List getAttributes() { + return attributes; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LineNumberTableAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LineNumberTableAttr.java new file mode 100644 index 0000000000..c2a75a95c5 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LineNumberTableAttr.java @@ -0,0 +1,37 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTableAttr extends AttributeInfo { + private List items = new ArrayList<>(); + + public LineNumberTableAttr(int attrNameIndex, int attrLen, List items) { + super(attrNameIndex, attrLen); + this.items = items; + } + + public List getItems() { + return items; + } + + public static class LineNumberItem { + private int startPc; + private int lineNumber; + + public LineNumberItem(int startPc, int lineNumber) { + this.startPc = startPc; + this.lineNumber = lineNumber; + } + + public int getStartPc() { + return startPc; + } + + public int getLineNumber() { + return lineNumber; + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LocalVariableTableAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LocalVariableTableAttr.java new file mode 100644 index 0000000000..fce15e7365 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/LocalVariableTableAttr.java @@ -0,0 +1,52 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +import java.util.ArrayList; +import java.util.List; + +public class LocalVariableTableAttr extends AttributeInfo { + + List items = new ArrayList<>(); + + public LocalVariableTableAttr(int attrNameIndex, int attrLen, List items) { + super(attrNameIndex, attrLen); + this.items = items; + } + + public static 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) { + this.startPC = startPC; + this.length = length; + this.nameIndex = nameIndex; + this.descIndex = descIndex; + this.index = index; + } + + public int getStartPC() { + return startPC; + } + + public int getLength() { + return length; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescIndex() { + return descIndex; + } + + public int getIndex() { + return index; + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SourceFileAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SourceFileAttr.java new file mode 100644 index 0000000000..55921f5035 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/SourceFileAttr.java @@ -0,0 +1,16 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public class SourceFileAttr extends AttributeInfo { + private int sourceFileIndex; + + public SourceFileAttr(int attrNameIndex, int attrLen, int sourceFileIndex) { + super(attrNameIndex, attrLen); + this.sourceFileIndex = sourceFileIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/StackMapTableAttr.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/StackMapTableAttr.java new file mode 100644 index 0000000000..cda2709020 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/item/impl/StackMapTableAttr.java @@ -0,0 +1,12 @@ +package jvm.classfile.attribute.item.impl; + +import jvm.classfile.attribute.item.AttributeInfo; + +public class StackMapTableAttr extends AttributeInfo { + private String originalCode; + + public StackMapTableAttr(int attrNameIndex, int attrLen, String originalCode) { + super(attrNameIndex, attrLen); + this.originalCode = originalCode; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeInfoParser.java new file mode 100644 index 0000000000..7ac80cf179 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeInfoParser.java @@ -0,0 +1,14 @@ +package jvm.classfile.attribute.parser; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public interface AttributeInfoParser { + AttributeInfo parse(int attrNameIndex, int attrLen, + ByteCodeIterator iterator, ConstantPool constantPool); +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeParser.java new file mode 100644 index 0000000000..e67850037b --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/AttributeParser.java @@ -0,0 +1,37 @@ +package jvm.classfile.attribute.parser; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.UTF8Info; +import jvm.util.ByteCodeIterator; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Created by Haochen on 2017/4/12. + * TODO: + */ +public class AttributeParser { + public static AttributeInfo parse(ByteCodeIterator iterator, ConstantPool constantPool) { + int nameIndex = iterator.nextU2ToInt(); + String name = ((UTF8Info) constantPool.getConstantInfo(nameIndex)).getValue(); + int length = iterator.nextU4ToInt(); + + String className = AttributeParser.class.getPackage().getName() + + ".impl." + name + "Parser"; + try { + Class clazz = Class.forName(className); + Method parse = clazz.getMethod("parse", + int.class, int.class, ByteCodeIterator.class, ConstantPool.class); + byte[] bytes = iterator.getBytes(length); + ByteCodeIterator subIterator = new ByteCodeIterator(bytes); + return (AttributeInfo) parse.invoke(clazz.newInstance(), + nameIndex, length, subIterator, constantPool); + } catch (ClassNotFoundException | NoSuchMethodException + | IllegalAccessException | InvocationTargetException | InstantiationException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/CodeParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/CodeParser.java new file mode 100644 index 0000000000..2ee74f020a --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/CodeParser.java @@ -0,0 +1,36 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.parser.AttributeParser; +import jvm.classfile.attribute.item.impl.CodeAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public class CodeParser implements AttributeInfoParser { + @Override + public AttributeInfo parse(int attrNameIndex, int attrLen, + ByteCodeIterator iterator, ConstantPool constantPool) { + int maxStack = iterator.nextU2ToInt(); + int maxLocals = iterator.nextU2ToInt(); + int codeLen = iterator.nextU4ToInt(); + String code = iterator.nextHexString(codeLen); + + int exceptionTableLen = iterator.nextU2ToInt(); + iterator.skip(exceptionTableLen * 8); + + int attrCount = iterator.nextU2ToInt(); + List attributes = new ArrayList<>(); + for (int i = 0; i < attrCount; ++i) { + attributes.add(AttributeParser.parse(iterator, constantPool)); + } + return new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code, attributes); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LineNumberTableParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LineNumberTableParser.java new file mode 100644 index 0000000000..8586ada746 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LineNumberTableParser.java @@ -0,0 +1,33 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.LineNumberTableAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public class LineNumberTableParser implements AttributeInfoParser { + @Override + public AttributeInfo parse(int attrNameIndex, int attrLen, + ByteCodeIterator iterator, ConstantPool constantPool) { + int tableLength = iterator.nextU2ToInt(); + + List items = new ArrayList<>(); + + for (int i = 0; i < tableLength; ++i) { + int startPC = iterator.nextU2ToInt(); + int lineNumber = iterator.nextU2ToInt(); + LineNumberTableAttr.LineNumberItem item = + new LineNumberTableAttr.LineNumberItem(startPC, lineNumber); + items.add(item); + } + return new LineNumberTableAttr(attrNameIndex, attrLen, items); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LocalVariableTableParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LocalVariableTableParser.java new file mode 100644 index 0000000000..9507ae3f37 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/LocalVariableTableParser.java @@ -0,0 +1,37 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.LocalVariableTableAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public class LocalVariableTableParser implements AttributeInfoParser { + @Override + public AttributeInfo parse(int attrNameIndex, int attrLen, + ByteCodeIterator iterator, ConstantPool constantPool) { + int tableLen = iterator.nextU2ToInt(); + + List items = new ArrayList<>(); + + for (int i = 0; i < tableLen; ++i) { + int startPC = iterator.nextU2ToInt(); + int length = iterator.nextU2ToInt(); + int nameIndex = iterator.nextU2ToInt(); + int descIndex = iterator.nextU2ToInt(); + int index = iterator.nextU2ToInt(); + LocalVariableTableAttr.LocalVariableItem item = + new LocalVariableTableAttr.LocalVariableItem( + startPC, length, nameIndex, descIndex, index); + items.add(item); + } + return new LocalVariableTableAttr(attrNameIndex, attrLen ,items); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SourceFileParser.java b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SourceFileParser.java new file mode 100644 index 0000000000..0c8561b21c --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/SourceFileParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.SourceFileAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +public class SourceFileParser implements AttributeInfoParser { + @Override + public AttributeInfo parse(int attrNameIndex, int attrLen, + ByteCodeIterator iterator, ConstantPool constantPool) { + int sourceFileIndex = iterator.nextU2ToInt(); + return new SourceFileAttr(attrNameIndex, attrLen, sourceFileIndex); + } +} 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 new file mode 100644 index 0000000000..087edcffcf --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/attribute/parser/impl/StackMapTableParser.java @@ -0,0 +1,25 @@ +package jvm.classfile.attribute.parser.impl; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.item.impl.StackMapTableAttr; +import jvm.classfile.attribute.parser.AttributeInfoParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/13. + * TODO: + */ +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); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java new file mode 100644 index 0000000000..c83fbfbb28 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/Constant.java @@ -0,0 +1,9 @@ +package jvm.classfile.constant.item; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public interface Constant { + int size(); +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/IReference.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/IReference.java new file mode 100644 index 0000000000..89a819aa96 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/IReference.java @@ -0,0 +1,11 @@ +package jvm.classfile.constant.item; + +import jvm.classfile.ConstantPool; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public interface IReference { + void linkReference(ConstantPool constantPool); +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java new file mode 100644 index 0000000000..84657cd7e4 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/ClassInfo.java @@ -0,0 +1,39 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ClassInfo implements Constant, IReference { + private int nameIndex; + private String className; + + public ClassInfo(int nameIndex) { + this.nameIndex = nameIndex; + } + + @Override + public int size() { + return 3; + } + + @Override + public void linkReference(ConstantPool constantPool) { + Constant constant = constantPool.getConstantInfo(getUtf8Index()); + if (constant instanceof UTF8Info) { + this.className = ((UTF8Info) constant).getValue(); + } + } + + public int getUtf8Index() { + return nameIndex; + } + + public String getClassName() { + return className; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java new file mode 100644 index 0000000000..1d671fcbda --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/CountConstant.java @@ -0,0 +1,24 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class CountConstant implements Constant { + private int count; + + public CountConstant(int count) { + this.count = count; + } + + @Override + public int size() { + return 2; + } + + public int getCount() { + return count; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java new file mode 100644 index 0000000000..8fa38452f6 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/DoubleInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class DoubleInfo implements Constant { + private byte[] highBytes; + private byte[] lowBytes; + + public DoubleInfo(byte[] highBytes, byte[] lowBytes) { + this.highBytes = highBytes; + this.lowBytes = lowBytes; + } + + @Override + public int size() { + return 9; + } + + public byte[] getHighBytes() { + return highBytes; + } + + public byte[] getLowBytes() { + return lowBytes; + } +} 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 new file mode 100644 index 0000000000..a7f51f51ba --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FieldRefInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class FieldRefInfo implements Constant { + private int classIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(int classIndex, int nameAndTypeIndex) { + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public int size() { + return 5; + } + + public int getClassIndex() { + return classIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } +} 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 new file mode 100644 index 0000000000..1368c07674 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/FloatInfo.java @@ -0,0 +1,24 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class FloatInfo implements Constant { + private byte[] bytes; + + public FloatInfo(byte[] bytes) { + this.bytes = bytes; + } + + @Override + public int size() { + return 5; + } + + public byte[] getBytes() { + return 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 new file mode 100644 index 0000000000..e345f94994 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/IntegerInfo.java @@ -0,0 +1,24 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class IntegerInfo implements Constant { + private byte[] bytes; + + public IntegerInfo(byte[] bytes) { + this.bytes = bytes; + } + + @Override + public int size() { + return 5; + } + + public byte[] getBytes() { + return bytes; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java new file mode 100644 index 0000000000..e22f8d4a45 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InterfaceMethodRefInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class InterfaceMethodRefInfo implements Constant { + private int classIndex; + private int nameAndTypeIndex; + + public InterfaceMethodRefInfo(int classIndex, int nameAndTypeIndex) { + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public int size() { + return 5; + } + + public int getClassIndex() { + return classIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java new file mode 100644 index 0000000000..91caadbb46 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/InvokeDynamicInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class InvokeDynamicInfo implements Constant { + private int bootstrapMethodAttrIndex; + private int nameAndTypeIndex; + + public InvokeDynamicInfo(int bootstrapMethodAttrIndex, int nameAndTypeIndex) { + this.bootstrapMethodAttrIndex = bootstrapMethodAttrIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public int size() { + return 5; + } + + public int getBootstrapMethodAttrIndex() { + return bootstrapMethodAttrIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java new file mode 100644 index 0000000000..c740e39f30 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/LongInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class LongInfo implements Constant { + private byte[] highBytes; + private byte[] lowBytes; + + public LongInfo(byte[] highBytes, byte[] lowBytes) { + this.highBytes = highBytes; + this.lowBytes = lowBytes; + } + + @Override + public int size() { + return 9; + } + + public byte[] getHighBytes() { + return highBytes; + } + + public byte[] getLowBytes() { + return lowBytes; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java new file mode 100644 index 0000000000..c7b6fbe4ac --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodHandleInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodHandleInfo implements Constant { + private int referenceKind; + private int referenceIndex; + + public MethodHandleInfo(int referenceKind, int referenceIndex) { + this.referenceKind = referenceKind; + this.referenceIndex = referenceIndex; + } + + @Override + public int size() { + return 4; + } + + public int getReferenceKind() { + return referenceKind; + } + + public int getReferenceIndex() { + return referenceIndex; + } +} 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 new file mode 100644 index 0000000000..c52903956c --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodRefInfo.java @@ -0,0 +1,30 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodRefInfo implements Constant { + private int classIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(int classIndex, int nameAndTypeIndex) { + this.classIndex = classIndex; + this.nameAndTypeIndex = nameAndTypeIndex; + } + + @Override + public int size() { + return 5; + } + + public int getClassInfoIndex() { + return classIndex; + } + + public int getNameAndTypeIndex() { + return nameAndTypeIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java new file mode 100644 index 0000000000..9b7e7cba1f --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/MethodTypeInfo.java @@ -0,0 +1,24 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodTypeInfo implements Constant { + private int descriptorIndex; + + public MethodTypeInfo(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + @Override + public int size() { + return 3; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java new file mode 100644 index 0000000000..c783b969e7 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/NameAndTypeInfo.java @@ -0,0 +1,38 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class NameAndTypeInfo implements Constant { + private int nameIndex; + private int descriptorIndex; + + public NameAndTypeInfo(int nameIndex, int descriptorIndex) { + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + @Override + public int size() { + return 5; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public int getIndex1() { + return nameIndex; + } + + public int getIndex2() { + return descriptorIndex; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java new file mode 100644 index 0000000000..6e7548db05 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/StringInfo.java @@ -0,0 +1,33 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.IReference; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class StringInfo implements Constant, IReference { + private int stringIndex; + private String value; + + public StringInfo(int stringIndex) { + this.stringIndex = stringIndex; + } + + @Override + public int size() { + return 3; + } + + public String getValue() { + return value; + } + + @Override + public void linkReference(ConstantPool constantPool) { + UTF8Info info = (UTF8Info) constantPool.getConstantInfo(stringIndex); + value = info.getValue(); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java new file mode 100644 index 0000000000..86d139fb7c --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/item/impl/UTF8Info.java @@ -0,0 +1,36 @@ +package jvm.classfile.constant.item.impl; + +import jvm.classfile.constant.item.Constant; + +import java.io.UnsupportedEncodingException; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class UTF8Info implements Constant { + private int length; + private String value; + + public UTF8Info(int length, byte[] bytes) { + this.length = length; + try { + this.value = new String(bytes, "utf8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + + @Override + public int size() { + return 3 + length; + } + + public int getLength() { + return length; + } + + public String getValue() { + return value; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParser.java new file mode 100644 index 0000000000..9902724df0 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParser.java @@ -0,0 +1,12 @@ +package jvm.classfile.constant.parser; + +import jvm.classfile.constant.item.Constant; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public interface ConstantParser { + Constant parse(ByteCodeIterator iterator); +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParserFactory.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParserFactory.java new file mode 100644 index 0000000000..56583b2df7 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/ConstantParserFactory.java @@ -0,0 +1,60 @@ +package jvm.classfile.constant.parser; + +import jvm.classfile.constant.parser.impl.*; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ConstantParserFactory { + private static final int CONSTANT_CLASS = 7; + private static final int CONSTANT_FIELD_REF = 9; + private static final int CONSTANT_METHOD_REF = 10; + private static final int CONSTANT_INTERFACE_METHOD_REF = 11; + private static final int CONSTANT_STRING = 8; + private static final int CONSTANT_INTEGER = 3; + private static final int CONSTANT_FLOAT = 4; + private static final int CONSTANT_LONG = 5; + private static final int CONSTANT_DOUBLE = 6; + private static final int CONSTANT_NAME_AND_TYPE = 12; + private static final int CONSTANT_UTF8 = 1; + private static final int CONSTANT_METHOD_HANDLE = 15; + private static final int CONSTANT_METHOD_TYPE = 16; + private static final int CONSTANT_INVOKE_DYNAMIC = 18; + + public static ConstantParser get(int type) { + switch (type) { + case CONSTANT_CLASS: + return new ClassInfoParser(); + case CONSTANT_FIELD_REF: + return new FieldRefInfoParser(); + case CONSTANT_METHOD_REF: + return new MethodRefInfoParser(); + case CONSTANT_INTERFACE_METHOD_REF: + return new InterfaceMethodRefInfoParser(); + case CONSTANT_STRING: + return new StringInfoParser(); + case CONSTANT_INTEGER: + return new IntegerInfoParser(); + case CONSTANT_FLOAT: + return new FloatInfoParser(); + case CONSTANT_LONG: + return new LongInfoParser(); + case CONSTANT_DOUBLE: + return new DoubleInfoParser(); + case CONSTANT_NAME_AND_TYPE: + return new NameAndTypeInfoParser(); + case CONSTANT_UTF8: + return new UTF8InfoParser(); + case CONSTANT_METHOD_HANDLE: + return new MethodHandleInfoParser(); + case CONSTANT_METHOD_TYPE: + return new MethodTypeInfoParser(); + case CONSTANT_INVOKE_DYNAMIC: + return new InvokeDynamicInfoParser(); + default: + return null; + } + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/ClassInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/ClassInfoParser.java new file mode 100644 index 0000000000..78b9a3f03f --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/ClassInfoParser.java @@ -0,0 +1,18 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ClassInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + return new ClassInfo(iterator.nextU2ToInt()); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/DoubleInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/DoubleInfoParser.java new file mode 100644 index 0000000000..72caf2f799 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/DoubleInfoParser.java @@ -0,0 +1,19 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.DoubleInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class DoubleInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + byte[] high = iterator.getBytes(4); + byte[] low = iterator.getBytes(4); + return new DoubleInfo(high, low); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FieldRefInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FieldRefInfoParser.java new file mode 100644 index 0000000000..1a3feac724 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FieldRefInfoParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class FieldRefInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int classIndex = iterator.nextU2ToInt(); + int nameAndTypeIndex = iterator.nextU2ToInt(); + return new FieldRefInfo(classIndex, nameAndTypeIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FloatInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FloatInfoParser.java new file mode 100644 index 0000000000..bedd2fd963 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/FloatInfoParser.java @@ -0,0 +1,17 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.FloatInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class FloatInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + return new FloatInfo(iterator.getBytes(4)); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/IntegerInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/IntegerInfoParser.java new file mode 100644 index 0000000000..ac316580d7 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/IntegerInfoParser.java @@ -0,0 +1,17 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.IntegerInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class IntegerInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + return new IntegerInfo(iterator.getBytes(4)); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InterfaceMethodRefInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InterfaceMethodRefInfoParser.java new file mode 100644 index 0000000000..65a9ff4fdf --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InterfaceMethodRefInfoParser.java @@ -0,0 +1,21 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.constant.item.impl.InterfaceMethodRefInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class InterfaceMethodRefInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int classIndex = iterator.nextU2ToInt(); + int nameAndTypeIndex = iterator.nextU2ToInt(); + return new InterfaceMethodRefInfo(classIndex, nameAndTypeIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InvokeDynamicInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InvokeDynamicInfoParser.java new file mode 100644 index 0000000000..1f8e5a3809 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/InvokeDynamicInfoParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.InvokeDynamicInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class InvokeDynamicInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int bootstrapMethodAttrIndex = iterator.nextU2ToInt(); + int nameAndTypeIndex = iterator.nextU2ToInt(); + return new InvokeDynamicInfo(bootstrapMethodAttrIndex, nameAndTypeIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/LongInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/LongInfoParser.java new file mode 100644 index 0000000000..f58c092665 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/LongInfoParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.DoubleInfo; +import jvm.classfile.constant.item.impl.LongInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class LongInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + byte[] high = iterator.getBytes(4); + byte[] low = iterator.getBytes(4); + return new LongInfo(high, low); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodHandleInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodHandleInfoParser.java new file mode 100644 index 0000000000..9bff9c4285 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodHandleInfoParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.MethodHandleInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodHandleInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int referenceKind = iterator.nextU1ToInt(); + int referenceIndex = iterator.nextU2ToInt(); + return new MethodHandleInfo(referenceKind, referenceIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodRefInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodRefInfoParser.java new file mode 100644 index 0000000000..1dbe7f85c6 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodRefInfoParser.java @@ -0,0 +1,21 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.FieldRefInfo; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodRefInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int classIndex = iterator.nextU2ToInt(); + int nameAndTypeIndex = iterator.nextU2ToInt(); + return new MethodRefInfo(classIndex, nameAndTypeIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodTypeInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodTypeInfoParser.java new file mode 100644 index 0000000000..37a59f6422 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/MethodTypeInfoParser.java @@ -0,0 +1,19 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.MethodTypeInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class MethodTypeInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int descriptorIndex = iterator.nextU2ToInt(); + return new MethodTypeInfo(descriptorIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/NameAndTypeInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/NameAndTypeInfoParser.java new file mode 100644 index 0000000000..3472f87f56 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/NameAndTypeInfoParser.java @@ -0,0 +1,20 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.NameAndTypeInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class NameAndTypeInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int nameIndex = iterator.nextU2ToInt(); + int descriptorIndex = iterator.nextU2ToInt(); + return new NameAndTypeInfo(nameIndex, descriptorIndex); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/StringInfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/StringInfoParser.java new file mode 100644 index 0000000000..b29ccdf4aa --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/StringInfoParser.java @@ -0,0 +1,18 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.StringInfo; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; +import jvm.util.ByteUtils; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class StringInfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + return new StringInfo(iterator.nextU2ToInt()); + } +} diff --git a/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/UTF8InfoParser.java b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/UTF8InfoParser.java new file mode 100644 index 0000000000..58aa699c24 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/constant/parser/impl/UTF8InfoParser.java @@ -0,0 +1,19 @@ +package jvm.classfile.constant.parser.impl; + +import jvm.classfile.constant.item.Constant; +import jvm.classfile.constant.item.impl.UTF8Info; +import jvm.classfile.constant.parser.ConstantParser; +import jvm.util.ByteCodeIterator; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class UTF8InfoParser implements ConstantParser { + @Override + public Constant parse(ByteCodeIterator iterator) { + int length = iterator.nextU2ToInt(); + byte[] array = iterator.getBytes(length); + return new UTF8Info(length, array); + } +} 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 new file mode 100644 index 0000000000..dcf6975543 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/field/Field.java @@ -0,0 +1,65 @@ +package jvm.classfile.field; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.parser.AttributeParser; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.UTF8Info; +import jvm.util.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +public class Field { + private int 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.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + this.constantPool = constantPool; + } + + public static Field parse(ByteCodeIterator iterator, ConstantPool constantPool) { + int access = iterator.nextU2ToInt(); + int name = iterator.nextU2ToInt(); + int descriptor = iterator.nextU2ToInt(); + int attrCount = iterator.nextU2ToInt(); + + Field result = new Field(access, name, descriptor, constantPool); + for (int i = 0; i < attrCount; ++i) { + result.attributes.add(AttributeParser.parse(iterator, constantPool)); + } + return result; + } + + @Override + public String toString() { + String name = ((UTF8Info) constantPool.getConstantInfo(nameIndex)).getValue(); + String desc = ((UTF8Info) constantPool.getConstantInfo(descriptorIndex)).getValue(); + return name + ":" + desc; + } + + public int getAccessFlag() { + return accessFlag; + } + + public int getNameIndex() { + return nameIndex; + } + + public int getDescriptorIndex() { + return descriptorIndex; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public List getAttributes() { + return attributes; + } +} 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 new file mode 100644 index 0000000000..6068124fa3 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/classfile/method/Method.java @@ -0,0 +1,57 @@ +package jvm.classfile.method; + +import jvm.classfile.attribute.item.AttributeInfo; +import jvm.classfile.attribute.parser.AttributeParser; +import jvm.classfile.ConstantPool; +import jvm.util.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + + +public class Method { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + private ConstantPool constantPool; + private List attributes = new ArrayList<>(); + + 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, ConstantPool constantPool) { + int access = iterator.nextU2ToInt(); + int name = iterator.nextU2ToInt(); + int descriptor = iterator.nextU2ToInt(); + int attrCount = iterator.nextU2ToInt(); + Method result = new Method(access, name, descriptor, constantPool); + for (int i = 0; i < attrCount; ++i) { + result.attributes.add(AttributeParser.parse(iterator, constantPool)); + } + 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; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java b/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java new file mode 100644 index 0000000000..a385aee580 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/ByteCodeIterator.java @@ -0,0 +1,70 @@ +package jvm.util; + +import java.util.Arrays; + +public class ByteCodeIterator { + private byte[] codes; + private 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 currentIndex() { + return pos; + } + + public int nextU1ToInt() { + return nextInt(1); + } + + public int nextU2ToInt() { + return nextInt(2); + } + + public int nextU4ToInt() { + return nextInt(4); + } + + public String nextU4ToHexString() { + return nextHexString(4); + } + + public String nextHexString(int byteCount) { + String result = ByteUtils.toHexString(codes, pos, byteCount).toLowerCase(); + pos += byteCount; + return result; + } + + public int nextInt(int byteCount) { + int result = ByteUtils.toInt(codes, pos, byteCount); + pos += byteCount; + return result; + } + + public void skip(int n) { + this.pos += n; + } + + public void back(int n) { + this.pos -= n; + } + + public void seekTo(int n) { + this.pos = n; + } + + public void reset() { + this.pos = 0; + } +} diff --git a/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java new file mode 100644 index 0000000000..3a0e1fc0b6 --- /dev/null +++ b/group01/895457260/code/src/main/java/jvm/util/ByteUtils.java @@ -0,0 +1,19 @@ +package jvm.util; + +/** + * Created by Haochen on 2017/4/9. + * TODO: + */ +public class ByteUtils { + public static String toHexString(byte[] bytes, int off, int len) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < len; ++i) { + builder.append(Integer.toHexString(Byte.toUnsignedInt(bytes[off + i]))); + } + return builder.toString(); + } + + public static int toInt(byte[] bytes, int off, int len) { + return Integer.parseInt(toHexString(bytes, off, len), 16); + } +} diff --git a/group01/895457260/code/src/test/java/algorithm/InfixExprTest.java b/group01/895457260/code/src/test/java/algorithm/InfixExprTest.java new file mode 100644 index 0000000000..34480d6db7 --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/InfixExprTest.java @@ -0,0 +1,48 @@ +package algorithm; + +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() throws InfixExpr.CalculateException { + //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/group01/895457260/code/src/test/java/algorithm/StackUtilTest.java b/group01/895457260/code/src/test/java/algorithm/StackUtilTest.java new file mode 100644 index 0000000000..b66065dd4e --- /dev/null +++ b/group01/895457260/code/src/test/java/algorithm/StackUtilTest.java @@ -0,0 +1,99 @@ +package algorithm; + +import datastructure.basic.Stack; +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +import java.util.Arrays; + +/** + * StackUtil Tester. + * + * @author + * @version 1.0 + * @since
四月 9, 2017
+ */ +public class StackUtilTest { + + @Before + public void before() throws Exception { + } + + @After + public void after() throws Exception { + } + + private Stack build(Object... args) { + Stack stack = new Stack(); + Arrays.stream(args).forEach(stack::push); + return stack; + } + + private Object[] toArray(Stack stack) { + Object[] array = new Object[stack.size()]; + for (int i = array.length - 1; i >= 0; --i) { + array[i] = stack.pop(); + } + Arrays.stream(array).forEach(stack::push); + return array; + } + + /** + * Method: reverse(Stack s) + */ + @Test + public void testReverse() throws Exception { +//TODO: Test goes here... + Stack stack = build(1, 3, 5, 7, 9); + StackUtil.reverse(stack); + Assert.assertArrayEquals(new Object[] {9, 7, 5, 3, 1}, toArray(stack)); + } + + /** + * Method: remove(Stack s, Object o) + */ + @Test + public void testRemove() throws Exception { +//TODO: Test goes here... + Stack stack = build(1, 3, 5, 7, 9, 11, 13); + StackUtil.remove(stack, 0); + Assert.assertArrayEquals(new Object[] {1, 3, 5, 7, 9, 11, 13}, toArray(stack)); + StackUtil.remove(stack, 1); + Assert.assertArrayEquals(new Object[] {3, 5, 7, 9, 11, 13}, toArray(stack)); + StackUtil.remove(stack, 13); + Assert.assertArrayEquals(new Object[] {3, 5, 7, 9, 11}, toArray(stack)); + StackUtil.remove(stack, 7); + Assert.assertArrayEquals(new Object[] {3, 5, 9, 11}, toArray(stack)); + } + + /** + * Method: getTop(Stack s, int len) + */ + @Test + public void testGetTop() throws Exception { +//TODO: Test goes here... + Stack stack = build(1, 3, 5); + Object[] array = toArray(stack); + Assert.assertArrayEquals(new Object[] {}, StackUtil.getTop(stack, 0)); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, array); + Assert.assertArrayEquals(new Object[] {3, 5}, StackUtil.getTop(stack, 2)); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, array); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, StackUtil.getTop(stack, 3)); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, array); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, StackUtil.getTop(stack, 4)); + Assert.assertArrayEquals(new Object[] {1, 3, 5}, array); + } + + /** + * Method: isValidPairs(String s) + */ + @Test + public void testIsValidPairs() throws Exception { +//TODO: Test goes here... + Assert.assertTrue(StackUtil.isValidPairs("{sqrt[p*(p-a)*(p-b)*(p-c)]}")); + Assert.assertFalse(StackUtil.isValidPairs("{sqrt[p*[p-a)*(p-b]*(p-c)]}")); + } + +} diff --git a/group01/895457260/code/src/test/java/datastructure/LinkedListTest.java b/group01/895457260/code/src/test/java/datastructure/LinkedListTest.java index dee34c8b3f..d6437ec636 100644 --- a/group01/895457260/code/src/test/java/datastructure/LinkedListTest.java +++ b/group01/895457260/code/src/test/java/datastructure/LinkedListTest.java @@ -114,7 +114,7 @@ public void testRemoveFirstHalf() throws Exception { /** * - * Method: remove(int i, int length) + * Method: remove(int i, int size) * */ @Test diff --git a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java index ac48c1a4d6..23a2341d8f 100644 --- a/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java +++ b/group01/895457260/code/src/test/java/jvm/ClassFileLoaderTest.java @@ -1,22 +1,42 @@ package jvm; +import jvm.classfile.attribute.item.impl.CodeAttr; +import jvm.classfile.ClassFile; +import jvm.classfile.ClassIndex; +import jvm.classfile.ConstantPool; +import jvm.classfile.constant.item.impl.ClassInfo; +import jvm.classfile.constant.item.impl.MethodRefInfo; +import jvm.classfile.constant.item.impl.NameAndTypeInfo; +import jvm.classfile.constant.item.impl.UTF8Info; import jvm.exception.ReadClassException; +import jvm.classfile.field.Field; +import jvm.classfile.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 = "jvm/EmployeeV1"; + private static final String LOAD_CLASS_NAME = "jvm.EmployeeV1"; private static ClassFileLoader loader; private static String path1 = "target/classes"; private static String path2 = "target/test-classes"; + + private static ClassFile clzFile = null; @Before public void setUp() throws Exception { loader = new ClassFileLoader(); loader.addClassPath(path1); loader.addClassPath(path2); + + if (clzFile == null) { + clzFile = loader.load(LOAD_CLASS_NAME); + } } @After @@ -30,20 +50,18 @@ public void testClassPath() { @Test public void testClassFileLength() throws ReadClassException { - String className = "jvm.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); + byte[] byteCodes = loader.readBinaryCode(LOAD_CLASS_NAME); // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 Assert.assertEquals(1016, byteCodes.length); } @Test public void testMagicNumber() throws ReadClassException { - String className = "jvm.EmployeeV1"; - byte[] byteCodes = loader.readBinaryCode(className); + byte[] byteCodes = loader.readBinaryCode(LOAD_CLASS_NAME); byte[] codes = new byte[] {byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; - - String actualValue = this.byteToHexString(codes); - Assert.assertEquals("cafebabe", actualValue); + + boolean check = loader.checkMagicNumber(codes); + Assert.assertTrue(check); } private String byteToHexString(byte[] codes) { @@ -58,4 +76,166 @@ private String byteToHexString(byte[] codes) { } 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(7); + Assert.assertEquals(44, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(44); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(11); + Assert.assertEquals(48, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(48); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(12); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(13); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(14); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(15); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(16); + Assert.assertEquals("", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(17); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(18); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(1); + Assert.assertEquals(11, methodRef.getClassInfoIndex()); + Assert.assertEquals(36, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(36); + Assert.assertEquals(16, nameAndType.getIndex1()); + Assert.assertEquals(28, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo)pool.getConstantInfo(9); + Assert.assertEquals(7, methodRef.getClassInfoIndex()); + Assert.assertEquals(46, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(35); + 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", + "2ab7012a2bb5022a1cb503b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb502b1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb503b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b204125b606b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool,m, + "main", + "([Ljava/lang/String;)V", + "bb0759128101db7094c2bb60ab1"); + } + } + + private void assertMethodEquals(ConstantPool pool, Method m, + String expectedName, String expectedDesc,String expectedCode) { + String methodName = ((UTF8Info) pool.getConstantInfo(m.getNameIndex())).getValue(); + String methodDesc = ((UTF8Info) pool.getConstantInfo(m.getDescriptorIndex())).getValue(); + String code = ((CodeAttr) m.getAttributes().get(0)).getCode(); + Assert.assertEquals(expectedName, methodName); + Assert.assertEquals(expectedDesc, methodDesc); + Assert.assertEquals(expectedCode, code); + } } diff --git a/group01/895457260/code/src/test/java/jvm/EmployeeV1.java b/group01/895457260/code/src/test/java/jvm/EmployeeV1.java index 0ab0e5bd1f..84cdf0d4e6 100644 --- a/group01/895457260/code/src/test/java/jvm/EmployeeV1.java +++ b/group01/895457260/code/src/test/java/jvm/EmployeeV1.java @@ -1,29 +1,28 @@ package jvm; 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() { + System.out.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/group05/1094051862/mini-jvm/.classpath b/group05/1094051862/mini-jvm/.classpath index 9b2ed0d520..e16a825a8f 100644 --- a/group05/1094051862/mini-jvm/.classpath +++ b/group05/1094051862/mini-jvm/.classpath @@ -4,5 +4,7 @@ + + diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java rename to group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java 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 new file mode 100644 index 0000000000..0e0e46f925 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,96 @@ +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.sun.org.apache.bcel.internal.classfile.Attribute; + + +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:" + code); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.nextU2toInt(); + if (exceptionTableLen > 0) { + String exTable = iter.nextUxToHexString(exceptionTableLen); + //TODO parse exception_table + System.out.println("exception_table has not been parsed !"); + + } + + int subAttrCount = iter.nextU2toInt(); + System.out.println("subAttrCount:"+subAttrCount); + for (int i = 0; i < subAttrCount; i++) { + int subAttrIndex = iter.nextU2toInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrIndex); + System.out.println("subAttrName:" + subAttrName); + + iter.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equals(subAttrName)) { + LineNumberTable t = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(t); + + } else if (AttributeInfo.LOCAL_VAR_TABLE.equals(subAttrName)) { + LocalVariableTable t = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(t); + } else if (AttributeInfo.STACK_MAP_TABLE.equals(subAttrName)) { + StackMapTable t = StackMapTable.parse(iter); + codeAttr.setStackMapTable(t); + } else { + throw new RuntimeException("Need to parse " + subAttrName); + } + } + return codeAttr; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..c6813a07a2 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,56 @@ +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 t = new LineNumberTable(attrNameIndex, attrLen); + + int linNumTableLen = iter.nextU2toInt(); + + for(int i = 0; i < linNumTableLen; i++) { + LineNumberItem m = new LineNumberItem(); + m.setStartPC(iter.nextU2toInt()); + m.setLineNum(iter.nextU2toInt()); + + t.addLineNumberItem(m); + } + + return t; + } + + + +} diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java rename to group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..1b1233f748 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,45 @@ +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); + } + + 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 = 0; 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; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..caff593698 --- /dev/null +++ b/group05/1094051862/mini-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/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..cdb8f8859a --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..e38d3091e4 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,94 @@ +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 com.coding.basic.ArrayList; +import com.coding.basic.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 addField(Field f) { + fields.add(f); + } + + public List getFields() { + return fields; + } + + public List getMethods() { + return 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()); + + + } + + 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 void addMethod(Method m) { + methods.add(m); + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..df22981441 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..92ae6bd6f6 --- /dev/null +++ b/group05/1094051862/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 ;//name_index + 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/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..2e3bef0a4e --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,30 @@ +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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..0e940b78d0 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ff9d5fb77 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..0feffa65b5 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..dcac7f97c4 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fa90d110fe --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d01065fd53 --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..b7407d146f --- /dev/null +++ b/group05/1094051862/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/group05/1094051862/mini-jvm/src/com/coderising/jvm/field/Field.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..d0009dc59c --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.field; + +import javax.management.RuntimeErrorException; + +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 attributesCount = iter.nextU2toInt(); + System.out.println("Field AttributesCount: "+attributesCount); + + Field f = new Field(accessFlag, nameIndex, descriptorIndex, pool); + + if (attributesCount > 0) { + throw new RuntimeException("Field attributes have not been parsed !"); + } + + return f; + } + + public String toString() { + StringBuffer s = new StringBuffer(); + s.append(pool.getUTF8String(nameIndex)); + s.append(':'); + s.append(pool.getUTF8String(descriptorIndex)); + return s.toString(); + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..69593e37f4 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,56 @@ +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/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java index 86f1100e6c..b9c66be7e7 100644 --- a/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -10,13 +10,32 @@ 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) throws ClassNotFoundException, IOException { + 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; + /* if (clzPaths.size() == 0) { - return new byte[0]; + throw new ClassNotFoundException(className); } String actualPath = getActualPath(className); @@ -46,31 +65,41 @@ public byte[] readBinaryCode(String className) throws ClassNotFoundException, IO } finally { is.close(); bos.close(); - } + } */ } - private String getActualPath(String className) { + private byte[] loadClassFile(String clzFileName) { + File f = new File(clzFileName); + try { + return IOUtils.toByteArray(new FileInputStream(f)); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + /*private String getActualPath(String className) { String fileName = className.substring(className.lastIndexOf(".") + 1) + ".class"; String dirPath = className.substring(0, className.lastIndexOf(".")).replace(".", "\\"); return clzPaths.get(clzPaths.size() - 1) + "\\" + dirPath + "\\" + fileName; //classPath 取最近添加的一个 - } + }*/ public void addClassPath(String path) { - if (path == null) { + if (this.clzPaths.contains(path)) { return; } - clzPaths.add(path); + this.clzPaths.add(path); } public String getClassPath() { - if (clzPaths.size() == 0) { + /*if (clzPaths.size() == 0) { return ""; } @@ -81,8 +110,18 @@ public String getClassPath() { buffer.append(";"); } - return buffer.substring(0, buffer.length() - 1);// 去除最后一个分号 + return buffer.substring(0, buffer.length() - 1);*/// 去除最后一个分号 + 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/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..09354e7f5f --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,153 @@ +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; +import com.coderising.jvm.field.Field; +import com.coderising.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); + + clzFile.setAccessFlag(parseAccessFlag(iter)); + clzFile.setClassIndex(parseClassIndex(iter)); + + parseInterfaces(iter);//如果实现接口,需要进一步解析 + + parseFields(clzFile, iter); + + parseMethods(clzFile, iter); + return clzFile; + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + int methodCount = iter.nextU2toInt(); + System.out.println("methodCount:" + methodCount); + for (int i = 0; i < methodCount; i++) { + System.out.println("method :" + (i+1)); + Method m = Method.parse(clzFile, iter); + clzFile.addMethod(m); + } + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + int fieldCount = iter.nextU2toInt(); + System.out.println("fieldCount:" + fieldCount); + for (int i = 0; i < fieldCount; i++) { + Field f = Field.parse(clzFile.getConstantPool(), iter); + clzFile.addField(f); + } + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + //int flagValue = iter.nextU2toInt(); + return new AccessFlag(iter.nextU2toInt()); + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextU2toInt()); + classIndex.setSuperClassIndex(iter.nextU2toInt()); + + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constantPoolIndexCount = iter.nextU2toInt(); + System.out.println("Constant Pool Index Count:" + constantPoolIndexCount); + ConstantPool pool = new ConstantPool(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= constantPoolIndexCount - 1; i++) { + int tag = iter.nextU1toInt(); + if (tag == 7) {//Class Info + int nameIndex = iter.nextU2toInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(nameIndex); + + pool.addConstantInfo(clzInfo); + } else if (tag == 1) {//Utf8 Info + 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 utf8Info = new UTF8Info(pool); + utf8Info.setLength(length); + utf8Info.setValue(value); + + pool.addConstantInfo(utf8Info); + } else if (tag == 8) {// String Info + int strIndex = iter.nextU2toInt(); + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(strIndex); + + pool.addConstantInfo(stringInfo); + } else if (tag == 9) {// Fieldref Info + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2toInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2toInt()); + + pool.addConstantInfo(fieldRefInfo); + } else if (tag == 10) {// Methodref Info + int classIndex = iter.nextU2toInt(); + int nameAndTypeIndex = iter.nextU2toInt(); + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(classIndex); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + pool.addConstantInfo(methodRefInfo); + } else if (tag == 12) { //NameAndType Info + int nameIndex = iter.nextU2toInt(); + int descriptorIndex = iter.nextU2toInt(); + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(nameIndex); + nameAndTypeInfo.setIndex2(descriptorIndex); + + pool.addConstantInfo(nameAndTypeInfo); + } + else { + throw new RuntimeException("The constant pool has not realized at tag=" + tag); + } + } + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2toInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + +} 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 new file mode 100644 index 0000000000..13a8e41994 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,80 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.clz.ClassFile; + +import javax.management.RuntimeErrorException; + +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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int accessFlag = iter.nextU2toInt(); + int nameIndex = iter.nextU2toInt(); + int descriptorIndex = iter.nextU2toInt(); + int attributesCount = iter.nextU2toInt(); + + System.out.println("Method AttributesCount:"+ attributesCount); + + Method m = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); + + for (int i = 0; i < attributesCount; i++) { + int attrNameIndex = iter.nextU2toInt(); + iter.back(2); //解析attrNameIndex就是下面一个属性的一部分,所以下面要解析属性,指针应该回退。 + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + System.out.println("attrName:"+attrName); + if (AttributeInfo.CODE.equals(attrName)) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + m.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("The attribute '"+ attrName +"' has not been implemented, " + + "the only implemented attribute is Code attribute !"); + } + + } + return m; + + } +} 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 b15eb7e99d..db02c29132 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 @@ -7,7 +7,17 @@ import org.junit.Before; import org.junit.Test; +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.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; +import com.coding.basic.List; @@ -15,11 +25,20 @@ public class ClassFileloaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; static String path1 = "E:\\practise\\group05\\1094051862\\mini-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); + clzFile.print(); + } @Before public void setUp() throws Exception { @@ -60,7 +79,6 @@ public void testClassFileLength() throws ClassNotFoundException, IOException { @Test public void testMagicNumber() throws ClassNotFoundException, IOException{ - ClassFileLoader loader = new ClassFileLoader(); loader.addClassPath(path1); String className = "com.coderising.jvm.test.EmployeeV1"; @@ -91,5 +109,169 @@ private String byteToHexString(byte[] codes ){ } 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 = (Field) fields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", f.toString()); + } + { + Field f = (Field) fields.get(1); + Assert.assertEquals("age:I", f.toString()); + } + } + @Test + public void testMethods(){ + + List methods = clzFile.getMethods(); + ConstantPool pool = clzFile.getConstantPool(); + + { + Method m = (Method) methods.get(0); + assertMethodEquals(pool,m, + "", + "(Ljava/lang/String;I)V", + "2ab7000c2a2bb5000f2a1cb50011b1"); + + } + { + Method m = (Method) methods.get(1); + assertMethodEquals(pool,m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + Method m = (Method) methods.get(2); + assertMethodEquals(pool,m, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + Method m = (Method) methods.get(3); + assertMethodEquals(pool,m, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + Method m = (Method) 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); + } } diff --git a/group05/1094051862/mini-jvm/src/com/coderising/jvm/util/Util.java b/group05/1094051862/mini-jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..176f70d002 --- /dev/null +++ b/group05/1094051862/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 implements List { + + private int size = 0; + + private Object[] elementData = new Object[10]; + + private int increaseSize = 10; + private void increaseArray() { + Object[] newData = Arrays.copyOf(elementData, elementData.length + increaseSize); + elementData = newData; + } + public void add(T o){ + if (size == elementData.length) { + increaseArray(); + elementData[size++] = o; + } else { + elementData[size++] = o; + } + } + public void add(int index, T o){ + if (index < 0 || index > size) { + System.out.println("错误提示:index > size || index < 0"); + return; + } + T temp; + for (int i = index; i < size; i++) { + temp = (T) elementData[i]; + elementData[i] = o; + o = temp; + } + elementData[size ++] = o; + } + + public T get(int index){ + if (index < 0 || index > size ){ + return null; + } + return (T) elementData[index]; + } + + public T remove(int index){ + if (index < 0 || index > size ){ + return null; + } + Object result = elementData[index]; + for (int i = index; i < size-1; i++) { + elementData[i] = elementData[i + 1]; + } + elementData[size-1] = null; + size --; + return (T) result; + } + + public int size(){ + return size; + } + + public Iterator iterator(){ + return new Iterator() { + private int cusor = 0; + @Override + public Object next() { + if (!hasNext()) { + System.out.println("next: !hasNext"); + return null; + } + return elementData[cusor ++]; + } + @Override + public boolean hasNext() { + return cusor < size; + } + }; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/ArrayListTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/ArrayListTest.java new file mode 100644 index 0000000000..c733e4e7a9 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/ArrayListTest.java @@ -0,0 +1,31 @@ +package com.coding.basic; + +import org.junit.Assert; +import org.junit.Test; + +public class ArrayListTest { + + @Test + public void test() { + List list = new ArrayList(); + for(int i = 0; i < 10; i++) { + list.add(i); + } + Assert.assertEquals(10, list.size()); + list.add(11); + list.add(3,99); + Assert.assertEquals(99, list.get(3)); + Assert.assertEquals(12, list.size()); + Assert.assertEquals(99, list.remove(3)); + Assert.assertEquals(11, list.size()); + Iterator iterator = list.iterator(); + for (int i = 0; i< list.size(); i++) { + System.out.println(list.get(i)); + } + System.out.println("======"); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/BinaryTreeNode.java b/group05/1094051862/mini-jvm/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..266eff3d56 --- /dev/null +++ b/group05/1094051862/mini-jvm/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/group05/1094051862/mini-jvm/src/com/coding/basic/Iterator.java b/group05/1094051862/mini-jvm/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..dbe8b9afb2 --- /dev/null +++ b/group05/1094051862/mini-jvm/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/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedList.java b/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedList.java new file mode 100644 index 0000000000..e05587dd02 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedList.java @@ -0,0 +1,334 @@ +package com.coding.basic; + +import java.util.Arrays; + +public class LinkedList implements List { + + private Node head; + private Node last; + private int size = 0; + + public void add(Object o) { + if (head == null) { + head = new Node(o, null); + size++; + return; + } + Node n = new Node(o, null); + if (last == null) { + last = n; + head.next = last; + } + last.next = n; + last = n; + size++; + } + + public void add(int index, Object o) { + if (index < 0 || index > size) { + System.out.println("linkedList.add: index < 0 || index > size"); + return; + } + if (index == size) { + add(o); + return; + } + if (index == 0) { + addFirst(o); + return; + } + Node pre = head; + for (int i = 1; i < index; i++) { + pre = pre.next; + } + Node post = pre.next; + Node n = new Node(o, post); + pre.next = n; + size++; + } + + public Object get(int index) { + return this.getNode(index).data; + } + + public Node getNode(int index) { + if (index == 0) { + return this.head; + } + Node n = head; + for (int i = 1; i <= index; i++) { + n = n.next; + } + return n; + } + + public Object remove(int index) { + if (index < 0 || index >= size) { + System.out.println("remove :index < 0 || index >= size"); + return null; + } + if (index == 0) { + return removeFirst(); + } + if (index == size - 1) { + return removeLast(); + } + Node pre = head; + for (int i = 1; i < index; i++) { + pre = pre.next; + } + Node n = pre.next; + Node post = n.next; + n.next = null; + pre.next = post; + size--; + return n.data; + } + + public int size() { + return size; + } + + public void addFirst(Object o) { + Node n = new Node(o, head); + head = n; + size++; + return; + } + + public void addLast(Object o) { + Node n = new Node(o, null); + last.next = n; + last = n; + size++; + return; + } + + public Object removeFirst() { + Object o = head.data; + Node n = head.next; + head.next = null; + head = n; + size--; + return o; + } + + public Object removeLast() { + Node preLast = head; + for (int i = 1; i < size; i++) { + preLast = preLast.next; + } + preLast.next = null; + Object o = last.data; + last = preLast; + size--; + return o; + } + + public Iterator iterator() { + return new Iterator() { + int cusor = 0; + Node current = head; + + @Override + public Object next() { + if (!hasNext()) { + System.out.println("next : !hasNext"); + return null; + } + Object o = current.data; + current = current.next; + cusor++; + return o; + } + + @Override + public boolean hasNext() { + return cusor < size; + } + }; + } + + 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 (this.size() < 2) { + return; + } + for (int i = this.size() - 1; i > 0; i--) { + this.getNode(i).next = this.getNode(i - 1); + } + Node temp = this.last; + this.last = this.head; + this.head = temp; + } + + /** + * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 + * ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + + int delSize = this.size() >> 1; + + Node temp = this.getNode(delSize);// getNode(index) + // 方法依赖前面元素的next指针,所以此语句在for循环前面 + + for (int i = delSize - 1; i >= 0; i--) { + this.getNode(i).next = null; + this.size--; + } + + this.head = temp;// 由于getNode(index) 方法如果index传入0 + // ,返回head,所以此语句要方法for循环后面 + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + if (i < 0 || length < 0 || this.size() < i + length) { + return; + } + if (i == 0 && this.size() == length) { + this.head = null; + this.size = 0; + this.last = null; + return; + } + Node iNode = this.getNode(i - 1); + Node pre = this.getNode(i + length - 1); + Node post = this.getNode(i + length); + pre.next = null; + iNode.next = post; + this.size = this.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) { + Iterator select = list.iterator(); + Iterator original = this.iterator(); + int[] result = new int[this.size()]; + int cosur = 0; + while (select.hasNext()) { + int s = (int) select.next(); + String selStr = String.valueOf(s); + while (original.hasNext()) { + int o = (int) original.next(); + String oriStr = String.valueOf(o); + if (oriStr.contains(selStr)) { + result[0] = o; + cosur++; + break; + } + } + } + return Arrays.copyOf(result, cosur - 1); + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + Iterator select = list.iterator(); + Iterator original = this.iterator(); + int[] result = new int[this.size()]; + int cosur = 0; + while (select.hasNext()) { + int sel = (int) select.next(); + + while (original.hasNext()) { + int ori = (int) original.next(); + cosur++; + if (ori == sel) { + remove(cosur); + } + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + if (this.size() == 0) { + return; + } + for (int i = this.size(); i > 0; i--) { + if ((int) get(i) == (int) get(i - 1)) { + this.remove(i); + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + int minIndex = 0; + int maxIndex = 0; + for (int i = this.size(); i > 0; i--) { + if (max > (int) get(i)) { + maxIndex = i; + } + } + for (int i = 0; i < maxIndex; i++) { + if (min < (int) get(i)) { + minIndex = i; + } + } + remove(minIndex, maxIndex - minIndex); + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList result = new LinkedList(); + Iterator select = list.iterator(); + Iterator original = this.iterator(); + + int sel = (int) select.next(); + int ori = (int) original.next(); + while (original.hasNext() && select.hasNext()) { + if (ori == sel) { + result.add(ori); + } else if (ori < sel) { + ori = (int) original.next(); + } else { + sel = (int) select.next(); + } + } + return result; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedListTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedListTest.java new file mode 100644 index 0000000000..db55063435 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/LinkedListTest.java @@ -0,0 +1,79 @@ +package com.coding.basic; + +import junit.framework.Assert; + +import org.junit.Test; + +public class LinkedListTest extends LinkedList { + + @Test + public void test() { + List list = new LinkedList(); + list.add(0); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(3, 33); + list.add(0, 100); + list.add(8,800); + Assert.assertEquals(9, list.size()); + Assert.assertEquals(100, list.get(0)); + Assert.assertEquals(0, list.get(1)); + Assert.assertEquals(1, list.get(2)); + Assert.assertEquals(2, list.get(3)); + Assert.assertEquals(33, list.get(4)); + Assert.assertEquals(3, list.get(5)); + Assert.assertEquals(4, list.get(6)); + Assert.assertEquals(800, list.get(8)); + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + System.out.println(iterator.next()); + } + } + @Test + public void testReverse() { + LinkedList list = new LinkedList(); + list.add(1); + list.add(2); + list.add(3); + list.add(4); + list.add(5); + list.add(6); + list.add(7); + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + System.out.print(iterator.next()); + } + System.out.println(); + list.reverse(); + Iterator iterator2 = list.iterator(); + while (iterator2.hasNext()) { + System.out.print(iterator2.next()); + } + System.out.println(); + list.removeFirstHalf(); + Iterator iterator3 = list.iterator(); + while (iterator3.hasNext()) { + System.out.print(iterator3.next()); + } + System.out.println(); + + } + @Test + public void testRemove() { + LinkedList list = new LinkedList(); + int i = 0; + while( i < 20) { + list.add(i); + i ++; + } + list.remove(3, 10); + Iterator iterator = list.iterator(); + while (iterator.hasNext()) { + System.out.print(iterator.next()); + } + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/List.java b/group05/1094051862/mini-jvm/src/com/coding/basic/List.java new file mode 100644 index 0000000000..c52c1aef0e --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/List.java @@ -0,0 +1,10 @@ +package com.coding.basic; + +public interface List { + public void add(T t); + public void add(int index, T t); + public Object get(int index); + public Object remove(int index); + public int size(); + public Iterator iterator(); +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/Queue.java b/group05/1094051862/mini-jvm/src/com/coding/basic/Queue.java new file mode 100644 index 0000000000..e16a80b13c --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/Queue.java @@ -0,0 +1,25 @@ +package com.coding.basic; + +public class Queue { + private List list = new ArrayList(); + private int size = 0; + public void enQueue(Object o){ + list.add(o); + size ++; + } + + public Object deQueue(){ + if (size == 0) + return null; + size --; + return list.remove(0); + } + + public boolean isEmpty(){ + return size == 0; + } + + public int size(){ + return size; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/QueueTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/QueueTest.java new file mode 100644 index 0000000000..1feee8dde1 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/QueueTest.java @@ -0,0 +1,24 @@ +package com.coding.basic; + +import static org.junit.Assert.*; +import junit.framework.Assert; + +import org.junit.Test; + +public class QueueTest { + + @Test + public void test() { + Queue queue = new Queue(); + for (int i = 0; i < 100; i++) { + queue.enQueue(i); + } + Assert.assertEquals(100, queue.size()); + for (int i = 0; i < 100; i++) { + Assert.assertEquals(i, queue.deQueue()); + } + Assert.assertEquals(0, queue.size()); + + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/Stack.java b/group05/1094051862/mini-jvm/src/com/coding/basic/Stack.java new file mode 100644 index 0000000000..57eae3d31d --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/Stack.java @@ -0,0 +1,28 @@ +package com.coding.basic; + +public class Stack { + private List elementData = new ArrayList(); + private int size = 0; + public void push(Object o){ + elementData.add(o); + size ++; + } + + public Object pop(){ + if (size == 0) + return null; + return elementData.remove(--size); + } + + public Object peek(){ + if (size == 0) + return null; + return elementData.get(size - 1); + } + public boolean isEmpty(){ + return size == 0; + } + public int size(){ + return size; + } +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/StackTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/StackTest.java new file mode 100644 index 0000000000..e3eabe44a1 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/StackTest.java @@ -0,0 +1,26 @@ +package com.coding.basic; + +import static org.junit.Assert.*; +import junit.framework.Assert; + +import org.junit.BeforeClass; +import org.junit.Test; + +public class StackTest { + + @Test + public void test() { + Stack stack = new Stack(); + for (int i = 0; i < 100; i++) { + stack.push(i); + } + Assert.assertEquals(100, stack.size()); + Assert.assertEquals(99, stack.pop()); + for (int i = 98; i >= 0; i--) { + Assert.assertEquals(i, stack.peek()); + Assert.assertEquals(i, stack.pop()); + } + Assert.assertEquals(0, stack.size()); + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/Stack.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..5abd9499d5 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,42 @@ +package com.coding.basic.stack; + +import com.coding.basic.ArrayList; +import com.coding.basic.List; + +public class Stack { + private List elementData = new ArrayList(); + private int size = 0; + public void push(Object o){ + elementData.add(o); + size ++; + } + + public Object pop(){ + if (size == 0) + return null; + return elementData.remove(--size); + } + + public Object peek(){ + if (size == 0) + return null; + return elementData.get(size - 1); + } + public boolean isEmpty(){ + return size == 0; + } + public int size(){ + return size; + } + public String toString() { + StringBuffer join = new StringBuffer("["); + for(int i = 0; i < size; i++) { + join.append(elementData.get(i)); + if (i != size - 1) { + join.append(","); + } + } + join.append("]"); + return join.toString(); + } +} 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 new file mode 100644 index 0000000000..cdb09886fa --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,108 @@ +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.size() == 0) { + return; + } + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + reverseTo(s, s1); + reverseTo(s1, s2); + reverseTo(s2, s); + } + + private static void reverseTo(Stack s, Stack s1) { + while(!s.isEmpty()) { + s1.push(s.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if (o == null || s == null || s.size() == 0) { + return; + } + Stack temp = new Stack(); + reverseTo(s,temp); + while(!temp.isEmpty()) { + if (temp.peek().equals(o)) { + temp.pop(); + continue; + } + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (len <= 0 || s == null || s.size() < len) { + return null; + } + Object[] objs = new Object[len]; + for(int i = 0; i < len; i++) { + objs[i] = s.pop(); + } + for(int i = len-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; + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + char[] c = s.toCharArray(); + Stack tag = new Stack(); + for (int i = 0; i < c.length; i++) { + switch(c[i]) { + case '(': + case '[': + case '{': + tag.push(c[i]); + break; + case ')': + if (tag.isEmpty() || '(' != (char)tag.pop()) { + return false; + } + break; + case '}': + if (tag.isEmpty() || '{' != (char)tag.pop()) { + return false; + } + break; + case ']': + if (tag.isEmpty() || '[' != (char)tag.pop()) { + return false; + } + break; + } + } + if (!tag.isEmpty()) { + return false; + } + return true; + } + +} diff --git a/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtilTest.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..31c0d72dc1 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,61 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.apache.commons.lang3.ArrayUtils; +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); + System.out.println(stack.toString()); + StackUtil.reverse(stack); + System.out.println(stack.toString()); + } + + @Test + public void testRemove() { + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + System.out.println(stack.toString()); + StackUtil.remove(stack, 5); + System.out.println(stack.toString()); + StackUtil.remove(stack, 2); + System.out.println(stack.toString()); + } + + @Test + public void testGetTop() { + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + System.out.println(stack.toString()); + Object[] top = StackUtil.getTop(stack, 3); + System.out.println(ArrayUtils.toString(top, null)); + System.out.println(stack.toString()); + } + + @Test + public void testIsValidPairs() { + String str = "sdf{sdf[sdf]sdfsdff}"; + String str2 = "[sdf(sdf{sdf]}sdf)"; + Assert.assertTrue(StackUtil.isValidPairs(str)); + Assert.assertTrue(!StackUtil.isValidPairs(str2)); + } + +} 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 new file mode 100644 index 0000000000..dc51c6adf3 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,74 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +import com.coding.basic.stack.Stack; +import com.coding.basic.stack.StackUtil; + +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 t : tokens) { + if (t.isOperator()) { + 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); + } + } + } else if (t.isDigit()) { + numStack.push(Float.valueOf(t.getValue())); + } + } + /*StackUtil.reverse(numStack); + StackUtil.reverse(opStack);*/ + while (!opStack.isEmpty()) { + Float f1 = (Float) numStack.pop(); + Float f2 = (Float) numStack.pop(); + Token opr = (Token) opStack.pop(); + numStack.push(calculate(opr.getValue(), f2, f1)); + } + return (Float) numStack.pop(); + //return 0.0f; + } + + 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; + } + return 0.0f; + } + +} 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 new file mode 100644 index 0000000000..a6c3d24012 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,54 @@ +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); + } + + } + @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/Token.java b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..b8abf39546 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/Token.java @@ -0,0 +1,61 @@ +package com.coding.basic.stack.expr; + +public class Token { + + public static final int OPRATOR = 0; + public static final int NUMBER = 1; + + private int signal; + private String value; + + public Token(int signal, String digit) { + this.signal = signal; + this.value = digit; + } + + public boolean isOperator() { + return this.signal == Token.OPRATOR; + } + + public boolean isDigit() { + return this.signal == Token.NUMBER; + } + + public int getSignal() { + return signal; + } + + public void setSignal(int signal) { + this.signal = signal; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public int comparePriority(Token topOperator) { + int topOptrPriority = 0; + int optPriority = 0; + if (topOperator.getValue().indexOf('*')>=0 || topOperator.getValue().indexOf('/')>=0) { + topOptrPriority = 1; + } + if (topOperator.getValue().indexOf('+')>=0 || topOperator.getValue().indexOf('-')>=0) { + topOptrPriority = 0; + } + if (this.getValue().indexOf('+')>=0 || this.getValue().indexOf('-')>=0) { + optPriority = 0; + } + if (this.getValue().indexOf('*')>=0 || this.getValue().indexOf('/')>=0) { + optPriority = 1; + } + + + return optPriority - topOptrPriority; + } + + +} 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 new file mode 100644 index 0000000000..447894d7f4 --- /dev/null +++ b/group05/1094051862/mini-jvm/src/com/coding/basic/stack/expr/TokenParser.java @@ -0,0 +1,52 @@ +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 (charIsOperator(c)) { + Token t = new Token(Token.OPRATOR, String.valueOf(c)); + tokens.add(t); + i ++; + } else if (charIsDigit(c)) { + int nextOperatorIndex = indexOfNextOperator(i,expr); + String value = expr.substring(i, nextOperatorIndex); + Token t = new Token(Token.NUMBER, value); + tokens.add(t); + i = nextOperatorIndex; + } + 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; + } + } + return expr.length();//如果后面没有操作符,返回字符串长度,用于截取数字 + } + + private boolean charIsDigit(char c) { + return c>='0' && c<='9'; + } + + private boolean charIsOperator(char c) { + + return c=='+' || c=='-' || c=='*' || c=='/'; + } + +} diff --git a/group05/1094051862/test01/.classpath b/group05/1094051862/test01/.classpath index 6f95a0c3bd..2ffae0aee1 100644 --- a/group05/1094051862/test01/.classpath +++ b/group05/1094051862/test01/.classpath @@ -4,5 +4,6 @@ + diff --git a/group05/1094051862/test01/src/com/coding/basic/stack/Stack.java b/group05/1094051862/test01/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..dd23c0c422 --- /dev/null +++ b/group05/1094051862/test01/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,42 @@ +package com.coding.basic.stack; + +import com.coding.basic.ArrayList; +import com.coding.basic.List; + +public class Stack { + private List elementData = new ArrayList(); + private int size = 0; + public void push(Object o){ + elementData.add(o); + size ++; + } + + public Object pop(){ + if (size == 0) + return null; + return elementData.remove(--size); + } + + public Object peek(){ + if (size == 0) + return null; + return elementData.get(size - 1); + } + public boolean isEmpty(){ + return size == 0; + } + public int size(){ + return size; + } + public String toString() { + StringBuffer join = new StringBuffer("["); + for(int i = 0; i < size; i++) { + join.append(elementData.get(i)); + if (i != size - 1) { + join.append(","); + } + } + join.append("]"); + return join.toString(); + } +} diff --git a/group05/1094051862/test01/src/com/coding/basic/stack/StackUtil.java b/group05/1094051862/test01/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..cdb09886fa --- /dev/null +++ b/group05/1094051862/test01/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,108 @@ +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.size() == 0) { + return; + } + Stack s1 = new Stack(); + Stack s2 = new Stack(); + + reverseTo(s, s1); + reverseTo(s1, s2); + reverseTo(s2, s); + } + + private static void reverseTo(Stack s, Stack s1) { + while(!s.isEmpty()) { + s1.push(s.pop()); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if (o == null || s == null || s.size() == 0) { + return; + } + Stack temp = new Stack(); + reverseTo(s,temp); + while(!temp.isEmpty()) { + if (temp.peek().equals(o)) { + temp.pop(); + continue; + } + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (len <= 0 || s == null || s.size() < len) { + return null; + } + Object[] objs = new Object[len]; + for(int i = 0; i < len; i++) { + objs[i] = s.pop(); + } + for(int i = len-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; + * @param s + * @return + */ + public static boolean isValidPairs(String s) { + char[] c = s.toCharArray(); + Stack tag = new Stack(); + for (int i = 0; i < c.length; i++) { + switch(c[i]) { + case '(': + case '[': + case '{': + tag.push(c[i]); + break; + case ')': + if (tag.isEmpty() || '(' != (char)tag.pop()) { + return false; + } + break; + case '}': + if (tag.isEmpty() || '{' != (char)tag.pop()) { + return false; + } + break; + case ']': + if (tag.isEmpty() || '[' != (char)tag.pop()) { + return false; + } + break; + } + } + if (!tag.isEmpty()) { + return false; + } + return true; + } + +} diff --git a/group05/1094051862/test01/src/com/coding/basic/stack/StackUtilTest.java b/group05/1094051862/test01/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..31c0d72dc1 --- /dev/null +++ b/group05/1094051862/test01/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,61 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.apache.commons.lang3.ArrayUtils; +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); + System.out.println(stack.toString()); + StackUtil.reverse(stack); + System.out.println(stack.toString()); + } + + @Test + public void testRemove() { + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + System.out.println(stack.toString()); + StackUtil.remove(stack, 5); + System.out.println(stack.toString()); + StackUtil.remove(stack, 2); + System.out.println(stack.toString()); + } + + @Test + public void testGetTop() { + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + System.out.println(stack.toString()); + Object[] top = StackUtil.getTop(stack, 3); + System.out.println(ArrayUtils.toString(top, null)); + System.out.println(stack.toString()); + } + + @Test + public void testIsValidPairs() { + String str = "sdf{sdf[sdf]sdfsdff}"; + String str2 = "[sdf(sdf{sdf]}sdf)"; + Assert.assertTrue(StackUtil.isValidPairs(str)); + Assert.assertTrue(!StackUtil.isValidPairs(str2)); + } + +} diff --git a/group05/284422826/src/com/coderising/jvm/loader/ClassFileLoader.java b/group05/284422826/src/com/coderising/jvm/loader/ClassFileLoader.java deleted file mode 100644 index a15237f0cb..0000000000 --- a/group05/284422826/src/com/coderising/jvm/loader/ClassFileLoader.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.coderising.jvm.loader; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - - -public class ClassFileLoader { - - private List clzPaths = new ArrayList<>(); - - public byte[] readBinaryCode(String className) { - String name = this.getClassPath() + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; - File file = new File(name); - byte[] bytes = new byte[(int)file.length()]; - try { - BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); - while (bis.read(bytes) != -1) { - System.out.println(Arrays.toString(bytes)); - } - } catch (IOException e) { - e.printStackTrace(); - } - return bytes; - } - - - public void addClassPath(String path) { - clzPaths.add(path); - } - - - public String getClassPath() { - StringBuilder path = new StringBuilder(); - for (String str : clzPaths) { - path.append(str).append(";"); - } - return path.substring(0, path.length() - 1); - } - - -} diff --git a/group05/284422826/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group05/284422826/src/com/coderising/jvm/test/ClassFileloaderTest.java deleted file mode 100644 index ca669de57a..0000000000 --- a/group05/284422826/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.coderising.jvm.test; - -import com.coderising.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:\\git\\coding2017\\group05\\284422826\\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 ){ - StringBuilder buffer = new StringBuilder(); - for (byte b : codes) { - 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/group05/284422826/src/com/coderising/litestruts/struts.xml b/group05/284422826/src/com/coderising/litestruts/struts.xml deleted file mode 100644 index a7cb57e188..0000000000 --- a/group05/284422826/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/group05/284422826/src/com/coding2017/basic/Iterator.java b/group05/284422826/src/com/coding2017/basic/Iterator.java deleted file mode 100644 index 19e214cfbb..0000000000 --- a/group05/284422826/src/com/coding2017/basic/Iterator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.coding2017.basic; - -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group05/284422826/src/com/coding2017/basic/List.java b/group05/284422826/src/com/coding2017/basic/List.java deleted file mode 100644 index 25c197cc18..0000000000 --- a/group05/284422826/src/com/coding2017/basic/List.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.coding2017.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/group05/284422826/src/com/coding2017/basic/array/ArrayList.java b/group05/284422826/src/com/coding2017/basic/array/ArrayList.java deleted file mode 100644 index 3baaf4e597..0000000000 --- a/group05/284422826/src/com/coding2017/basic/array/ArrayList.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.coding2017.basic; - -/** - * 功能:实现ArrayList. - * @author zhanglifeng. - */ -public class ArrayList implements List { - private int size = 0; //当前数组大小 - - private Object[] elementData = new Object[5]; //初始数组 - - /** - * 将对象o添加到ArrayList中. - * @param o:需要添加的对象. - */ - public void add(Object o) { - ensureCapacity(size + 1); //确保数组的容量可以装的下size + 1个元素,如果不够则扩容 - - elementData[size] = o; //将o添加到数组中 - size++; //数组大小增加1 - } - - /** - * 将对象o添加到ArrayList的指定位置. - * @param index: 指定位置. - * @param o: 需要添加的对象. - */ - public void add(int index, Object o) { - ensureCapacity(size + 1); //确保数组的容量可以装的下size + 1个元素,如果不够则扩容 - - System.arraycopy(elementData, index, elementData, index + 1, size - index); //将index位置到结束位置所有的数组往后移动一个位置 - elementData[index] = o; //将对象o添加到index位置 - size++;//数组大小增加1 - } - - public Object get(int index) { - rangeCheck(index); - return elementData[index]; - } - - public Object remove(int index) { - rangeCheck(index); - - if (index != elementData.length - 1) { - System.arraycopy(elementData, index + 1, elementData, index, size - 1 - index); - } - - size--; - return elementData; - } - - public int size() { - return size; - } - - public Iterator iterator() { - return new ArrayListIterator(this); - } - - private void ensureCapacity(int number) { - if (number > elementData.length) { - elementData = grow(elementData, 1); - } - } - - public Object[] grow(Object[] src, int step) { - Object[] target = new Object[src.length + step]; - System.arraycopy(src, 0, target, 0, src.length); - return target; - } - - public void rangeCheck(int index){ - if (index > size || index < 0) { - throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); - } - } - - private class ArrayListIterator implements Iterator { - ArrayList arrayList = null; - int current = 0; - - private ArrayListIterator(ArrayList arrayList) { - this.arrayList = arrayList; - } - - @Override - public boolean hasNext() { - current++; - return current > arrayList.size() ? false : true; - } - - @Override - public Object next() { - return elementData[current]; - } - - } - - public static void main(String[] args) { - ArrayList arrayList = new ArrayList(); - arrayList.add("s1"); - arrayList.add("s2"); - arrayList.add("s3"); - arrayList.add("s4"); - arrayList.add(3, "s33"); - arrayList.add("s5"); - - System.out.println(arrayList.size()); - - System.out.println(arrayList.get(2)); - - arrayList.remove(3); - - System.out.println(arrayList.size()); - - arrayList.add("s1"); - System.out.println(arrayList.size()); - arrayList.remove(5); - System.out.println(arrayList.size()); - - Iterator it = arrayList.iterator(); - while(it.hasNext()){ - System.out.print(it.next() + " "); - } - System.out.println(); - } - -} diff --git a/group05/284422826/src/com/coderising/download/DownloadThread.java b/group05/284422826/src/main/java/com/coderising/download/DownloadThread.java similarity index 100% rename from group05/284422826/src/com/coderising/download/DownloadThread.java rename to group05/284422826/src/main/java/com/coderising/download/DownloadThread.java diff --git a/group05/284422826/src/com/coderising/download/FileDownloader.java b/group05/284422826/src/main/java/com/coderising/download/FileDownloader.java similarity index 100% rename from group05/284422826/src/com/coderising/download/FileDownloader.java rename to group05/284422826/src/main/java/com/coderising/download/FileDownloader.java diff --git a/group05/284422826/src/com/coderising/download/FileDownloaderTest.java b/group05/284422826/src/main/java/com/coderising/download/FileDownloaderTest.java similarity index 100% rename from group05/284422826/src/com/coderising/download/FileDownloaderTest.java rename to group05/284422826/src/main/java/com/coderising/download/FileDownloaderTest.java diff --git a/group05/284422826/src/main/java/com/coderising/download/api/Connection.java b/group05/284422826/src/main/java/com/coderising/download/api/Connection.java new file mode 100644 index 0000000000..622dc26bc6 --- /dev/null +++ b/group05/284422826/src/main/java/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 + */ + byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + int getContentLength(); + + /** + * 关闭连接 + */ + void close(); +} diff --git a/group05/284422826/src/com/coderising/download/api/ConnectionException.java b/group05/284422826/src/main/java/com/coderising/download/api/ConnectionException.java similarity index 100% rename from group05/284422826/src/com/coderising/download/api/ConnectionException.java rename to group05/284422826/src/main/java/com/coderising/download/api/ConnectionException.java diff --git a/group05/284422826/src/main/java/com/coderising/download/api/ConnectionManager.java b/group05/284422826/src/main/java/com/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..a478bd3d2d --- /dev/null +++ b/group05/284422826/src/main/java/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + Connection open(String url) throws ConnectionException; +} diff --git a/group05/284422826/src/main/java/com/coderising/download/api/DownloadListener.java b/group05/284422826/src/main/java/com/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..de81b7607d --- /dev/null +++ b/group05/284422826/src/main/java/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + void notifyFinished(); +} diff --git a/group05/284422826/src/com/coderising/download/impl/ConnectionImpl.java b/group05/284422826/src/main/java/com/coderising/download/impl/ConnectionImpl.java similarity index 100% rename from group05/284422826/src/com/coderising/download/impl/ConnectionImpl.java rename to group05/284422826/src/main/java/com/coderising/download/impl/ConnectionImpl.java diff --git a/group05/284422826/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group05/284422826/src/main/java/com/coderising/download/impl/ConnectionManagerImpl.java similarity index 100% rename from group05/284422826/src/com/coderising/download/impl/ConnectionManagerImpl.java rename to group05/284422826/src/main/java/com/coderising/download/impl/ConnectionManagerImpl.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group05/284422826/src/main/java/com/coderising/jvm/clz/AccessFlag.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java rename to group05/284422826/src/main/java/com/coderising/jvm/clz/AccessFlag.java diff --git a/group05/284422826/src/main/java/com/coderising/jvm/clz/ClassFile.java b/group05/284422826/src/main/java/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group05/284422826/src/main/java/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/liuxin/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group05/284422826/src/main/java/com/coderising/jvm/clz/ClassIndex.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java rename to group05/284422826/src/main/java/com/coderising/jvm/clz/ClassIndex.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/ClassInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/ClassInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/ConstantInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/ConstantInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/ConstantPool.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/ConstantPool.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/FieldRefInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/MethodRefInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/NameAndTypeInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/NullConstantInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/StringInfo.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/StringInfo.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group05/284422826/src/main/java/com/coderising/jvm/constant/UTF8Info.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java rename to group05/284422826/src/main/java/com/coderising/jvm/constant/UTF8Info.java diff --git a/group05/284422826/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java b/group05/284422826/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..d15af81630 --- /dev/null +++ b/group05/284422826/src/main/java/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,54 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.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 = 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 < len; i++) { + temp[i] = codes[pos++]; + } + return Util.byteToHexString(temp).toLowerCase(); + } + + public void back(int n){ + pos = pos - n; + } + +} diff --git a/group05/284422826/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java b/group05/284422826/src/main/java/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..0560d27c8a --- /dev/null +++ b/group05/284422826/src/main/java/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 com.coderising.jvm.clz.ClassFile; + +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); + + } + + + + // ------------------------------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/group05/284422826/src/com/coderising/jvm/test/EmployeeV1.java b/group05/284422826/src/main/java/com/coderising/jvm/test/EmployeeV1.java similarity index 100% rename from group05/284422826/src/com/coderising/jvm/test/EmployeeV1.java rename to group05/284422826/src/main/java/com/coderising/jvm/test/EmployeeV1.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/util/Util.java b/group05/284422826/src/main/java/com/coderising/jvm/util/Util.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/util/Util.java rename to group05/284422826/src/main/java/com/coderising/jvm/util/Util.java diff --git a/group05/284422826/src/com/coderising/litestruts/LoginAction.java b/group05/284422826/src/main/java/com/coderising/litestruts/LoginAction.java similarity index 100% rename from group05/284422826/src/com/coderising/litestruts/LoginAction.java rename to group05/284422826/src/main/java/com/coderising/litestruts/LoginAction.java diff --git a/group05/284422826/src/com/coderising/litestruts/Struts.java b/group05/284422826/src/main/java/com/coderising/litestruts/Struts.java similarity index 100% rename from group05/284422826/src/com/coderising/litestruts/Struts.java rename to group05/284422826/src/main/java/com/coderising/litestruts/Struts.java diff --git a/group05/284422826/src/com/coderising/litestruts/StrutsTest.java b/group05/284422826/src/main/java/com/coderising/litestruts/StrutsTest.java similarity index 100% rename from group05/284422826/src/com/coderising/litestruts/StrutsTest.java rename to group05/284422826/src/main/java/com/coderising/litestruts/StrutsTest.java diff --git a/group05/284422826/src/com/coderising/litestruts/View.java b/group05/284422826/src/main/java/com/coderising/litestruts/View.java similarity index 100% rename from group05/284422826/src/com/coderising/litestruts/View.java rename to group05/284422826/src/main/java/com/coderising/litestruts/View.java diff --git a/group05/284422826/src/com/coding2017/basic/BinaryTreeNode.java b/group05/284422826/src/main/java/com/coding2017/basic/BinaryTreeNode.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/BinaryTreeNode.java rename to group05/284422826/src/main/java/com/coding2017/basic/BinaryTreeNode.java diff --git a/group05/284422826/src/main/java/com/coding2017/basic/Iterator.java b/group05/284422826/src/main/java/com/coding2017/basic/Iterator.java new file mode 100644 index 0000000000..939c382551 --- /dev/null +++ b/group05/284422826/src/main/java/com/coding2017/basic/Iterator.java @@ -0,0 +1,7 @@ +package com.coding2017.basic; + +public interface Iterator { + boolean hasNext(); + Object next(); + +} diff --git a/group05/284422826/src/main/java/com/coding2017/basic/List.java b/group05/284422826/src/main/java/com/coding2017/basic/List.java new file mode 100644 index 0000000000..0b6a48e7e4 --- /dev/null +++ b/group05/284422826/src/main/java/com/coding2017/basic/List.java @@ -0,0 +1,9 @@ +package com.coding2017.basic; + +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/group05/284422826/src/com/coding2017/basic/Queue.java b/group05/284422826/src/main/java/com/coding2017/basic/Queue.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/Queue.java rename to group05/284422826/src/main/java/com/coding2017/basic/Queue.java diff --git a/group05/284422826/src/main/java/com/coding2017/basic/array/ArrayList.java b/group05/284422826/src/main/java/com/coding2017/basic/array/ArrayList.java new file mode 100644 index 0000000000..236b3006ac --- /dev/null +++ b/group05/284422826/src/main/java/com/coding2017/basic/array/ArrayList.java @@ -0,0 +1,128 @@ +package com.coding2017.basic; + +/** + * 功能:实现ArrayList. + * @author zhanglifeng. + */ +public class ArrayList implements List { + private int size = 0; //当前数组大小 + + private Object[] elementData = new Object[5]; //初始数组 + + /** + * 将对象o添加到ArrayList中. + * @param o:需要添加的对象. + */ + public void add(Object o) { + ensureCapacity(size + 1); //确保数组的容量可以装的下size + 1个元素,如果不够则扩容 + + elementData[size] = o; //将o添加到数组中 + size++; //数组大小增加1 + } + + /** + * 将对象o添加到ArrayList的指定位置. + * @param index: 指定位置. + * @param o: 需要添加的对象. + */ + public void add(int index, Object o) { + ensureCapacity(size + 1); //确保数组的容量可以装的下size + 1个元素,如果不够则扩容 + + System.arraycopy(elementData, index, elementData, index + 1, size - index); //将index位置到结束位置所有的数组往后移动一个位置 + elementData[index] = o; //将对象o添加到index位置 + size++;//数组大小增加1 + } + + public Object get(int index) { + rangeCheck(index); + return elementData[index]; + } + + public Object remove(int index) { + rangeCheck(index); + + if (index != elementData.length - 1) { + System.arraycopy(elementData, index + 1, elementData, index, size - 1 - index); + } + + size--; + return elementData; + } + + public int size() { + return size; + } + + public Iterator iterator() { + return new ArrayListIterator(this); + } + + private void ensureCapacity(int number) { + if (number > elementData.length) { + elementData = grow(elementData, 1); + } + } + + public Object[] grow(Object[] src, int step) { + Object[] target = new Object[src.length + step]; + System.arraycopy(src, 0, target, 0, src.length); + return target; + } + + public void rangeCheck(int index){ + if (index > size || index < 0) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); + } + } + + private class ArrayListIterator implements Iterator { + ArrayList arrayList = null; + int current = 0; + + private ArrayListIterator(ArrayList arrayList) { + this.arrayList = arrayList; + } + + @Override + public boolean hasNext() { + current++; + return current <= arrayList.size(); + } + + @Override + public Object next() { + return elementData[current]; + } + + } + + public static void main(String[] args) { + ArrayList arrayList = new ArrayList(); + arrayList.add("s1"); + arrayList.add("s2"); + arrayList.add("s3"); + arrayList.add("s4"); + arrayList.add(3, "s33"); + arrayList.add("s5"); + + System.out.println(arrayList.size()); + + System.out.println(arrayList.get(2)); + + arrayList.remove(3); + + System.out.println(arrayList.size()); + + arrayList.add("s1"); + System.out.println(arrayList.size()); + arrayList.remove(5); + System.out.println(arrayList.size()); + + Iterator it = arrayList.iterator(); + while(it.hasNext()){ + System.out.print(it.next() + " "); + } + System.out.println(); + } + +} diff --git a/group05/284422826/src/com/coding2017/basic/array/ArrayUtil.java b/group05/284422826/src/main/java/com/coding2017/basic/array/ArrayUtil.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/array/ArrayUtil.java rename to group05/284422826/src/main/java/com/coding2017/basic/array/ArrayUtil.java diff --git a/group05/284422826/src/com/coding2017/basic/array/ArrayUtilTest.java b/group05/284422826/src/main/java/com/coding2017/basic/array/ArrayUtilTest.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/array/ArrayUtilTest.java rename to group05/284422826/src/main/java/com/coding2017/basic/array/ArrayUtilTest.java diff --git a/group05/284422826/src/com/coding2017/basic/linklist/LRUPageFrame.java b/group05/284422826/src/main/java/com/coding2017/basic/linklist/LRUPageFrame.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/linklist/LRUPageFrame.java rename to group05/284422826/src/main/java/com/coding2017/basic/linklist/LRUPageFrame.java diff --git a/group05/284422826/src/com/coding2017/basic/linklist/LRUPageFrameTest.java b/group05/284422826/src/main/java/com/coding2017/basic/linklist/LRUPageFrameTest.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/linklist/LRUPageFrameTest.java rename to group05/284422826/src/main/java/com/coding2017/basic/linklist/LRUPageFrameTest.java diff --git a/group05/284422826/src/com/coding2017/basic/linklist/LinkedList.java b/group05/284422826/src/main/java/com/coding2017/basic/linklist/LinkedList.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/linklist/LinkedList.java rename to group05/284422826/src/main/java/com/coding2017/basic/linklist/LinkedList.java diff --git a/group05/284422826/src/com/coding2017/basic/Stack.java b/group05/284422826/src/main/java/com/coding2017/basic/stack/Stack.java similarity index 100% rename from group05/284422826/src/com/coding2017/basic/Stack.java rename to group05/284422826/src/main/java/com/coding2017/basic/stack/Stack.java diff --git a/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtil.java b/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtil.java new file mode 100644 index 0000000000..c14ddd9039 --- /dev/null +++ b/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtil.java @@ -0,0 +1,116 @@ +package com.coding2017.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 == 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 tempStack = new Stack(); + while(!s.isEmpty()){ + Object value = s.pop(); + if (!value.equals(o)) { + tempStack.push(value); + } + } + + while(!tempStack.isEmpty()){ + s.push(tempStack.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; + } + + Object[] result = new Object[len]; + int i = 0; + while(!s.isEmpty()){ + Object value = s.pop(); + result[i++] = value; + if(i == len){ + break; + } + } + + 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 < 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/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtilTest.java b/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..96179918cb --- /dev/null +++ b/group05/284422826/src/main/java/com/coding2017/basic/stack/StackUtilTest.java @@ -0,0 +1,78 @@ +package com.coding2017.basic.stack; + +import static org.junit.Assert.fail; + +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/group05/578505552/578505552.iml b/group05/578505552/578505552.iml deleted file mode 100644 index 95e7551d7a..0000000000 --- a/group05/578505552/578505552.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/group05/578505552/pom.xml b/group05/578505552/pom.xml index 62eed92daf..ea3686ca26 100644 --- a/group05/578505552/pom.xml +++ b/group05/578505552/pom.xml @@ -7,7 +7,6 @@ 1.0-SNAPSHOT jar - basic http://maven.apache.org diff --git a/group05/578505552/src/main/java/com/coderising/array/ArrayUtil.java b/group05/578505552/src/main/java/com/coderising/array/ArrayUtil.java deleted file mode 100644 index 2c248db331..0000000000 --- a/group05/578505552/src/main/java/com/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,242 +0,0 @@ -package com.coderising.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 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){ - 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 < 0){ - 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.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(); - } - -} diff --git a/group05/578505552/src/main/java/com/coderising/download/DownloadThread.java b/group05/578505552/src/main/java/com/coderising/download/DownloadThread.java deleted file mode 100644 index feefc27cfc..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/DownloadThread.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.coderising.download; - -import com.coderising.download.api.Connection; -import 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/com/coderising/download/FileDownloader.java b/group05/578505552/src/main/java/com/coderising/download/FileDownloader.java deleted file mode 100644 index d399381a7a..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/FileDownloader.java +++ /dev/null @@ -1,66 +0,0 @@ -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; - -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/com/coderising/download/FileDownloaderTest.java b/group05/578505552/src/main/java/com/coderising/download/FileDownloaderTest.java deleted file mode 100644 index 6f740c3882..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/FileDownloaderTest.java +++ /dev/null @@ -1,50 +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 = "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/main/java/com/coderising/download/api/Connection.java b/group05/578505552/src/main/java/com/coderising/download/api/Connection.java deleted file mode 100644 index 494c713b27..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/api/Connection.java +++ /dev/null @@ -1,23 +0,0 @@ -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/src/main/java/com/coderising/download/api/ConnectionException.java b/group05/578505552/src/main/java/com/coderising/download/api/ConnectionException.java deleted file mode 100644 index 5954d22409..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/api/ConnectionException.java +++ /dev/null @@ -1,20 +0,0 @@ -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/src/main/java/com/coderising/download/impl/ConnectionImpl.java b/group05/578505552/src/main/java/com/coderising/download/impl/ConnectionImpl.java deleted file mode 100644 index 0561318d7a..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -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/src/main/java/com/coderising/download/impl/ConnectionManagerImpl.java b/group05/578505552/src/main/java/com/coderising/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index 3ea9a95517..0000000000 --- a/group05/578505552/src/main/java/com/coderising/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -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/com/coderising/litestruts/Configuration.java b/group05/578505552/src/main/java/com/coderising/litestruts/Configuration.java deleted file mode 100644 index 90d8a0c6a1..0000000000 --- a/group05/578505552/src/main/java/com/coderising/litestruts/Configuration.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.coderising.litestruts; - -/** - * Created by songbao.yang on 2017/3/10. - */ -public class Configuration { -} diff --git a/group05/578505552/src/main/java/com/coderising/litestruts/LoginAction.java b/group05/578505552/src/main/java/com/coderising/litestruts/LoginAction.java deleted file mode 100644 index b74dfa425d..0000000000 --- a/group05/578505552/src/main/java/com/coderising/litestruts/LoginAction.java +++ /dev/null @@ -1,38 +0,0 @@ -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/com/coderising/litestruts/Struts.java b/group05/578505552/src/main/java/com/coderising/litestruts/Struts.java deleted file mode 100644 index 95b4d37a52..0000000000 --- a/group05/578505552/src/main/java/com/coderising/litestruts/Struts.java +++ /dev/null @@ -1,131 +0,0 @@ -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("/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/com/coderising/litestruts/View.java b/group05/578505552/src/main/java/com/coderising/litestruts/View.java deleted file mode 100644 index 0194c681f6..0000000000 --- a/group05/578505552/src/main/java/com/coderising/litestruts/View.java +++ /dev/null @@ -1,23 +0,0 @@ -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/src/main/java/com/coding/basic/ArrayList.java b/group05/578505552/src/main/java/com/coding/basic/ArrayList.java deleted file mode 100644 index 54d8f05f02..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/ArrayList.java +++ /dev/null @@ -1,103 +0,0 @@ -package 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(Object 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, Object o){ - indexCheck(index); - ensureCapacity(size+1); - System.arraycopy(elementData, index, elementData, index+1, size-index); - elementData[index] = o; - size++; - } - - public Object get(int index){ - indexCheck(index); - return elementData[index]; - } - - private void indexCheck(int index){ - if(index < 0){ - throw new IllegalArgumentException("illegal index: " + index); - } - if(index >= size){ - throw new IndexOutOfBoundsException(); - } - } - - public Object remove(int index){ - indexCheck(index); - Object rm = elementData[index]; - System.arraycopy(elementData, index+1, elementData, index, size-index-1); - size--; - return 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/com/coding/basic/BinaryTreeNode.java b/group05/578505552/src/main/java/com/coding/basic/BinaryTreeNode.java deleted file mode 100644 index 3a36db4031..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/BinaryTreeNode.java +++ /dev/null @@ -1,60 +0,0 @@ -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/src/main/java/com/coding/basic/Iterator.java b/group05/578505552/src/main/java/com/coding/basic/Iterator.java deleted file mode 100644 index 6765eae519..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/Iterator.java +++ /dev/null @@ -1,11 +0,0 @@ -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/src/main/java/com/coding/basic/LinkedList.java b/group05/578505552/src/main/java/com/coding/basic/LinkedList.java deleted file mode 100644 index d1fa42bf4c..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/LinkedList.java +++ /dev/null @@ -1,156 +0,0 @@ -package 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(Object 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 , Object 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 Object get(int index){ - indexRangeCheck(index); - Node cursor = head; - for (int i = 0; i < index; i++) { - cursor = cursor.next; - } - return cursor.next.data; - } - - public Object 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 indexNode; - } - - public int size(){ - return elementCount; - } - - public void addFirst(Object o){ - Node node = new Node(); - node.data = o; - node.next = head.next; - head.next = node; - elementCount++; - } - - public void addLast(Object 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 Object removeFirst(){ - - if (size() == 0){ - throw new RuntimeException("no element in list"); - } - Node firstNode = head.next; - head.next = head.next.next; - elementCount--; - return firstNode; - } - - public Object 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 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{ - Object data; - Node next; - } -} diff --git a/group05/578505552/src/main/java/com/coding/basic/List.java b/group05/578505552/src/main/java/com/coding/basic/List.java deleted file mode 100644 index e26fbe7c98..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/List.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.coding.basic; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -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(); - public Iterator iterator(); -} diff --git a/group05/578505552/src/main/java/com/coding/basic/Queue.java b/group05/578505552/src/main/java/com/coding/basic/Queue.java deleted file mode 100644 index ec31573ee7..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/Queue.java +++ /dev/null @@ -1,90 +0,0 @@ -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/src/main/java/com/coding/basic/Stack.java b/group05/578505552/src/main/java/com/coding/basic/Stack.java deleted file mode 100644 index ffc4915bef..0000000000 --- a/group05/578505552/src/main/java/com/coding/basic/Stack.java +++ /dev/null @@ -1,63 +0,0 @@ -package 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/coderising/array/ArrayUtil.java b/group05/578505552/src/main/java/dataStruct/com/coderising/array/ArrayUtil.java new file mode 100644 index 0000000000..4a034abf2c --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/array/ArrayUtil.java @@ -0,0 +1,263 @@ +package dataStruct.com.coderising.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/src/main/java/dataStruct/com/coderising/download/DownloadThread.java b/group05/578505552/src/main/java/dataStruct/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..c837e08f8b --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/DownloadThread.java @@ -0,0 +1,47 @@ +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 new file mode 100644 index 0000000000..324ba4d29d --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/FileDownloader.java @@ -0,0 +1,66 @@ +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 new file mode 100644 index 0000000000..da33f7360c --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/Connection.java @@ -0,0 +1,23 @@ +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 new file mode 100644 index 0000000000..2efc59eec6 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,20 @@ +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 new file mode 100644 index 0000000000..2ac9aa5ac9 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +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 new file mode 100644 index 0000000000..8daca6846c --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +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 new file mode 100644 index 0000000000..c9b1c7c103 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,49 @@ +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 new file mode 100644 index 0000000000..e8e5a85aeb --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,25 @@ +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/com/coderising/litestruts/Action.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java similarity index 89% rename from group05/578505552/src/main/java/com/coderising/litestruts/Action.java rename to group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java index 743f452030..1c9ad259ad 100644 --- a/group05/578505552/src/main/java/com/coderising/litestruts/Action.java +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Action.java @@ -1,38 +1,38 @@ -package com.coderising.litestruts; - - -import java.util.Map; - -/** - * Created by songbao.yang on 2017/3/1. - * - */ -public class Action { - private String name; - private String className; - private Map results; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getClassName() { - return className; - } - - public void setClassName(String className) { - this.className = className; - } - - public Map getResults() { - return results; - } - - public void setResults(Map results) { - this.results = results; - } -} +package dataStruct.com.coderising.litestruts; + + +import java.util.Map; + +/** + * Created by songbao.yang on 2017/3/1. + * + */ +public class Action { + private String name; + private String className; + private Map results; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public Map getResults() { + return results; + } + + public void setResults(Map results) { + this.results = results; + } +} 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 new file mode 100644 index 0000000000..c85b40029f --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Configuration.java @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000000..b7789abf28 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/LoginAction.java @@ -0,0 +1,38 @@ +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/com/coderising/litestruts/ReflectUtils.java b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java similarity index 81% rename from group05/578505552/src/main/java/com/coderising/litestruts/ReflectUtils.java rename to group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java index c11c5632f3..cb35e59963 100644 --- a/group05/578505552/src/main/java/com/coderising/litestruts/ReflectUtils.java +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/ReflectUtils.java @@ -1,4 +1,4 @@ -package com.coderising.litestruts; +package dataStruct.com.coderising.litestruts; import java.lang.reflect.Method; 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 new file mode 100644 index 0000000000..00bc5a446f --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/Struts.java @@ -0,0 +1,131 @@ +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 new file mode 100644 index 0000000000..bb6f39e9a9 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coderising/litestruts/View.java @@ -0,0 +1,23 @@ +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 new file mode 100644 index 0000000000..cdbb1107a0 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/ArrayList.java @@ -0,0 +1,103 @@ +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 new file mode 100644 index 0000000000..ee0351da07 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/BinaryTreeNode.java @@ -0,0 +1,60 @@ +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 new file mode 100644 index 0000000000..1755e82202 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Iterator.java @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000000..9238a5c7a0 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/LinkedList.java @@ -0,0 +1,390 @@ +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 new file mode 100644 index 0000000000..20d7a6daf9 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/List.java @@ -0,0 +1,14 @@ +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 new file mode 100644 index 0000000000..2b3a62a5d3 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Queue.java @@ -0,0 +1,90 @@ +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 new file mode 100644 index 0000000000..4f41c69a9e --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/Stack.java @@ -0,0 +1,63 @@ +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 new file mode 100644 index 0000000000..cebc4bc739 --- /dev/null +++ b/group05/578505552/src/main/java/dataStruct/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,105 @@ +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 new file mode 100644 index 0000000000..97dc361c12 --- /dev/null +++ b/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,68 @@ +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 new file mode 100644 index 0000000000..edae33a2aa --- /dev/null +++ b/group05/578505552/src/main/java/miniJvm/com/coderising/jvm/loader/EmployeeV1.java @@ -0,0 +1,31 @@ +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 index 0a44e0927e..0dc7b6de98 100644 --- a/group05/578505552/src/main/resources/struts.xml +++ b/group05/578505552/src/main/resources/struts.xml @@ -1,6 +1,6 @@ - + /jsp/homepage.jsp /jsp/showLogin.jsp diff --git a/group05/578505552/src/test/java/com/coderising/array/ArrayUtilTest.java b/group05/578505552/src/test/java/com/coderising/array/ArrayUtilTest.java deleted file mode 100644 index 607f4fed5b..0000000000 --- a/group05/578505552/src/test/java/com/coderising/array/ArrayUtilTest.java +++ /dev/null @@ -1,206 +0,0 @@ -package com.coderising.array; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -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/com/coderising/litestruts/StrutsTest.java b/group05/578505552/src/test/java/com/coderising/litestruts/StrutsTest.java deleted file mode 100644 index 6df05450b6..0000000000 --- a/group05/578505552/src/test/java/com/coderising/litestruts/StrutsTest.java +++ /dev/null @@ -1,40 +0,0 @@ -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/src/test/java/com/coding/basic/BinaryTreeNodeTest.java b/group05/578505552/src/test/java/com/coding/basic/BinaryTreeNodeTest.java deleted file mode 100644 index d1e408554e..0000000000 --- a/group05/578505552/src/test/java/com/coding/basic/BinaryTreeNodeTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.coding.basic; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * 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/com/coding/basic/QueueTest.java b/group05/578505552/src/test/java/com/coding/basic/QueueTest.java deleted file mode 100644 index 905054670d..0000000000 --- a/group05/578505552/src/test/java/com/coding/basic/QueueTest.java +++ /dev/null @@ -1,75 +0,0 @@ -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); - Assert.assertEquals(i+1, queue.size()); - } - } - - @Test - public void deQueue1() throws Exception { - enQueue(); - - int i = 0; - int startSize = queue.size(); - while (!queue.isEmpty()) { - Assert.assertEquals(startSize - i, queue.size()); - Object o = queue.deQueue(); - Assert.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(); - Assert.assertEquals(startSize - 1, queue.size()); - queue.enQueue(i+1000); - Assert.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/com/coding/basic/StackTest.java b/group05/578505552/src/test/java/com/coding/basic/StackTest.java deleted file mode 100644 index b65d446c97..0000000000 --- a/group05/578505552/src/test/java/com/coding/basic/StackTest.java +++ /dev/null @@ -1,65 +0,0 @@ -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 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); - Assert.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(); - Assert.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/coderising/array/ArrayUtilTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/array/ArrayUtilTest.java new file mode 100644 index 0000000000..b09f2efcd0 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coderising/array/ArrayUtilTest.java @@ -0,0 +1,205 @@ +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/com/coderising/download/DownloadThreadTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java similarity index 80% rename from group05/578505552/src/test/java/com/coderising/download/DownloadThreadTest.java rename to group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java index eaa651776c..dbbb80a91a 100644 --- a/group05/578505552/src/test/java/com/coderising/download/DownloadThreadTest.java +++ b/group05/578505552/src/test/java/dataStruct/com/coderising/download/DownloadThreadTest.java @@ -1,16 +1,15 @@ -package com.coderising.download; +package dataStruct.com.coderising.download; -import com.coderising.download.api.Connection; -import com.coderising.download.api.DownloadListener; -import com.coderising.download.impl.ConnectionManagerImpl; +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; -import static org.junit.Assert.*; - /** * Created by songbao.yang on 2017/3/11. */ 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 new file mode 100644 index 0000000000..cb5748f4e6 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coderising/download/FileDownloaderTest.java @@ -0,0 +1,49 @@ +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/com/coderising/download/impl/ConnectionImplTest.java b/group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java similarity index 85% rename from group05/578505552/src/test/java/com/coderising/download/impl/ConnectionImplTest.java rename to group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java index 142540943e..967b4520a2 100644 --- a/group05/578505552/src/test/java/com/coderising/download/impl/ConnectionImplTest.java +++ b/group05/578505552/src/test/java/dataStruct/com/coderising/download/impl/ConnectionImplTest.java @@ -1,13 +1,11 @@ -package com.coderising.download.impl; +package dataStruct.com.coderising.download.impl; -import com.coderising.download.api.Connection; -import com.coderising.download.api.ConnectionManager; +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; -import static org.junit.Assert.*; - /** * Created by songbao.yang on 2017/3/11. */ 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 new file mode 100644 index 0000000000..bdb0334ae5 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,40 @@ +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 new file mode 100644 index 0000000000..ee7ecd6e36 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coding/basic/BinaryTreeNodeTest.java @@ -0,0 +1,36 @@ +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/com/coding/basic/ListTest.java b/group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java similarity index 94% rename from group05/578505552/src/test/java/com/coding/basic/ListTest.java rename to group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java index 0c786de96c..9196c37f4c 100644 --- a/group05/578505552/src/test/java/com/coding/basic/ListTest.java +++ b/group05/578505552/src/test/java/dataStruct/com/coding/basic/ListTest.java @@ -1,100 +1,100 @@ -package com.coding.basic; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by songbao.yang on 2017/2/21. - * - */ -public class ListTest { - - private List list; - - public static final int SIZE = 10000; - - @Before - public void setUp() throws Exception { - -// list = new ArrayList(); - list = new LinkedList(); - } - - @After - public void tearDown() throws Exception { - - } - - @Test - public void add() throws Exception { - - for (int i = 0; i < SIZE; i++) { - list.add(i); - Assert.assertEquals(i+1, list.size()); - } - } - - @Test - public void add1() throws Exception { - - add(); - for (int i = 0; i < 1000; i++) { - int oldSize = list.size(); - int randomIndex = (int)Math.floor(Math.random() * oldSize); - - list.add(randomIndex, randomIndex); - int newSize = list.size(); - - Assert.assertEquals(newSize, oldSize+1); - Assert.assertEquals(list.get(randomIndex), randomIndex); - } - } - - @Test - public void get() throws Exception { - - add(); - for (int i = 0; i < SIZE * 100; i++) { - int randomIndex = (int)Math.floor(Math.random() * list.size()); - if(randomIndex < 0 || randomIndex >= SIZE){ - System.out.println("illegal index: " + randomIndex); - throw new RuntimeException(); - } - int o = (Integer) list.get(randomIndex); - Assert.assertEquals(randomIndex, o); - } - } - - @Test - public void remove() throws Exception { - - add(); - for (int i = 0; i < SIZE; i++) { - int oldSize = list.size(); - int randomIndex = (int)Math.floor(Math.random() * oldSize); - list.remove(randomIndex); - int newSize = list.size(); - Assert.assertEquals(newSize, oldSize-1); - } - } - - @Test - public void size() throws Exception { - - } - - @Test - public void iterator() throws Exception { - add(); - Iterator iterator1 = list.iterator(); - int i = 0; - while (iterator1.hasNext()){ - Object next = iterator1.next(); - Assert.assertEquals(i, next); - i++; - } - } - +package dataStruct.com.coding.basic; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by songbao.yang on 2017/2/21. + * + */ +public class ListTest { + + private List list; + + public static final int SIZE = 10000; + + @Before + public void setUp() throws Exception { + +// list = new ArrayList(); + list = new LinkedList(); + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void add() throws Exception { + + for (int i = 0; i < SIZE; i++) { + list.add(i); + Assert.assertEquals(i+1, list.size()); + } + } + + @Test + public void add1() throws Exception { + + add(); + for (int i = 0; i < 1000; i++) { + int oldSize = list.size(); + int randomIndex = (int)Math.floor(Math.random() * oldSize); + + list.add(randomIndex, randomIndex); + int newSize = list.size(); + + Assert.assertEquals(newSize, oldSize+1); + Assert.assertEquals(list.get(randomIndex), randomIndex); + } + } + + @Test + public void get() throws Exception { + + add(); + for (int i = 0; i < SIZE * 100; i++) { + int randomIndex = (int)Math.floor(Math.random() * list.size()); + if(randomIndex < 0 || randomIndex >= SIZE){ + System.out.println("illegal index: " + randomIndex); + throw new RuntimeException(); + } + int o = (Integer) list.get(randomIndex); + Assert.assertEquals(randomIndex, o); + } + } + + @Test + public void remove() throws Exception { + + add(); + for (int i = 0; i < SIZE; i++) { + int oldSize = list.size(); + int randomIndex = (int)Math.floor(Math.random() * oldSize); + list.remove(randomIndex); + int newSize = list.size(); + Assert.assertEquals(newSize, oldSize-1); + } + } + + @Test + public void size() throws Exception { + + } + + @Test + public void iterator() throws Exception { + add(); + Iterator iterator1 = list.iterator(); + int i = 0; + while (iterator1.hasNext()){ + Object next = iterator1.next(); + Assert.assertEquals(i, next); + i++; + } + } + } \ 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 new file mode 100644 index 0000000000..856258a713 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coding/basic/QueueTest.java @@ -0,0 +1,75 @@ +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 new file mode 100644 index 0000000000..c58643c31a --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coding/basic/StackTest.java @@ -0,0 +1,65 @@ +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 new file mode 100644 index 0000000000..ffeaa4a747 --- /dev/null +++ b/group05/578505552/src/test/java/dataStruct/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +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 new file mode 100644 index 0000000000..97410772aa --- /dev/null +++ b/group05/578505552/src/test/java/miniJvm/com/coderising/jvm/loader/ClassFileloaderTest.java @@ -0,0 +1,70 @@ +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 map = new HashMap<>(); - Struts.runAction("login", map); - - } -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coderising/array/ArrayUtil.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/array/ArrayUtil.java deleted file mode 100644 index f94d5d01c4..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.coderising.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 static void reverseArray(int[] origin){ - if (origin == null) { - return; - } - - int length = origin.length; - int[] temp = new int[length]; - for (int i = 0; i < length; i++) - temp[i] = origin[i]; - for (int i = length - 1, j = 0; i >= 0 && j < length; i--, j++) - origin[j] = temp[i]; - } - - /** - * 现在有如下的一个数组: 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 null; - } - - int zeroCount = 0; - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] == 0) - zeroCount++; - } - int[] newArray = new int[oldArray.length-zeroCount]; - for (int i = 0, j = 0; i < oldArray.length && j < newArray.length; i++) { - if (oldArray[i] != 0) { - newArray[j] = oldArray[i]; - j++; - } - } - 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){ - if (array1 == null && array2 == null) - return null; - int index1 = 0, index2 = 0; - int[] array3 = new int[array1.length + array2.length]; - int index = 0; - while (index1 != array1.length && index2 != array2.length) { - if (array1[index1] < array2[index2]) { - array3[index++] = array1[index1++]; - } else if (array1[index1] > array2[index2]) { - array3[index++] = array2[index2++]; - } else if (array1[index1] == array2[index2]){ - array3[index++] = array1[index1++]; - index2++; - } - } - - if (index1 == array1.length && index2 != array2.length) { - for (int i = index2; i < array2.length; i++) - array3[index++] = array2[i]; - } else if (index2 == array2.length && index1 != array1.length) { - for (int i = index1; i < array1.length; i++) { - array3[index++] = array1[i]; - } - } - - int[] newArray = new int[index]; - for (int i = 0; i < newArray.length; i++) - newArray[i] = array3[i]; - return newArray; - } - /** - * 把一个已经存满数据的数组 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 (size <= 0) - return null; - 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 null; - if (max == 1) - return null; - int[] array = new int[max]; - int i = 0; - int value = fibonaccis(i+1); - while ( value < max) { - array[i++] = value; - value = fibonaccis(i+1); - } - int[] newArray = new int[i]; - for (int j = 0; j < newArray.length; j++) { - newArray[j] = array[j]; - } - return newArray; - } - - private static int fibonaccis(int n) { - if (n <=0) - return 0; - if (n == 1 || n ==2 ) - return 1; - return fibonaccis(n-1)+fibonaccis(n-2); - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * @param max - * @return - */ - public static int[] getPrimes(int max){ - if (max <= 1) { - return null; - } - int[] array = new int[max]; - int index = 0; - for (int i = 2; i < max; i++) { - if (i == 2 || i == 3 || i == 5 || i == 7) - array[index++] = i; - if (i%2 !=0 && i%3 != 0 && i%5 != 0 && i%7 != 0) - array[index++] = i; - } - int[] newArray = new int[index]; - for (int i = 0; i < newArray.length; i++) { - newArray[i] = array[i]; - } - - return newArray; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * @param max - * @return - */ - public static int[] getPerfectNumbers(int max){ - if (max <= 0) - return null; - int[] array = new int[max]; - int index = 0; - for (int i = 1; i < max; i++) { - if (isPerfectNumber(i)) - array[index++] = i; - } - - int[] newArray = new int[index]; - for (int i = 0; i < newArray.length; i++) - newArray[i] = array[i]; - - return newArray; - } - - private static boolean isPerfectNumber(int n) { - int sum = 0; - int i = 1; - while (i < n) { - if (n%i == 0) - sum += i; - i++; - } - if (sum == n) - return true; - return false; - } - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" - * @param array - * @param s - * @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]); - else - str.append(array[i] + seperator); - } - return str.toString(); - } - - -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/.Struts.java.swp b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/.Struts.java.swp deleted file mode 100644 index 1f45a5f25e..0000000000 Binary files a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/.Struts.java.swp and /dev/null differ diff --git a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/LoginAction.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/LoginAction.java deleted file mode 100644 index 1005f35a29..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/LoginAction.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.coderising.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/1178243325/DataStructure/src/main/java/com/coderising/litestruts/Struts.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/Struts.java deleted file mode 100644 index b3bd421435..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/Struts.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.coderising.litestruts; - -import java.util.Map; -import java.util.HashMap; -import java.lang.reflect.Method; -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 { - String targetClassName = XmlUtil.parseXML("struts.xml", actionName); - Class targetClass = Class.forName(targetClassName); - - Method setName = targetClass.getMethod("setName", String.class); - Method setPassword = targetClass.getMethod("setPassword", String.class); - Object object = targetClass.newInstance(); - - setName.invoke(object, parameters.get("name")); - setPassword.invoke(object, parameters.get("password")); - - Method execute = targetClass.getMethod("execute"); - String result = (String)execute.invoke(object); - - Method getMessage = targetClass.getMethod("getMessage"); - String message = (String)getMessage.invoke(object); - - Map params = new HashMap(); - params.put("message", message); - String jspUrl = XmlUtil.getJspUrl("struts.xml", actionName, result); - View view = new View(); - view.setJsp(jspUrl); - view.setParameters(params); - return view; - - } catch (Exception e) { - e.printStackTrace(); - } - - - return null; - } - -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/StrutsTest.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/StrutsTest.java deleted file mode 100644 index a44c1878ac..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/StrutsTest.java +++ /dev/null @@ -1,43 +0,0 @@ -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/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/View.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/View.java deleted file mode 100644 index 0194c681f6..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/View.java +++ /dev/null @@ -1,23 +0,0 @@ -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/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/XmlUtil.java b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/XmlUtil.java deleted file mode 100644 index d200452cc8..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/XmlUtil.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.coderising.litestruts; - -import java.io.*; -import java.util.*; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -public class XmlUtil { - - public static String parseXML(String filePath, String actionName) { - try { - File file = new File(filePath); - SAXReader reader = new SAXReader(); - Document doc = reader.read(file); - Element root = doc.getRootElement(); - for (Iterator iter = root.elementIterator("action"); iter.hasNext();) { - Element element = (Element)iter.next(); - Attribute nameAttr = element.attribute("name"); - if (nameAttr.getValue().equals(actionName)) { - Attribute classAttr = element.attribute("class"); - return classAttr.getValue(); - } - } - } catch (Exception e) { - e.printStackTrace(); - System.out.println("parse error"); - } - return null; - } - - public static String getJspUrl(String filePath, String actionName, String resultName) { - try { - File file = new File(filePath); - SAXReader reader = new SAXReader(); - Document doc = reader.read(file); - Element root = doc.getRootElement(); - for (Iterator iter = root.elementIterator("action"); iter.hasNext();) { - Element element = (Element)iter.next(); - Attribute nameAttr = element.attribute("name"); - if (nameAttr.getValue().equals(actionName)) { - for (Iterator ite = element.elementIterator("result"); ite.hasNext();) { - Element ele = (Element)ite.next(); - Attribute resultAttr = ele.attribute("name"); - if (resultAttr.getValue().equals(resultName)) { - return ele.getText(); - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/struts.xml b/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/struts.xml deleted file mode 100644 index ae0ce37fd8..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coderising/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/ArrayList.java b/group11/1178243325/DataStructure/src/main/java/com/coding/basic/ArrayList.java deleted file mode 100644 index f6cd4c38fc..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/ArrayList.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.exception.*; -public class ArrayList implements List { - - private int size; - private Object[] elementData; - - public ArrayList () { - size = 0; - elementData = new Object[100]; - } - - public void add(Object o){ - add(size(), o); - } - - public void add(int index, Object o){ - if (size() == elementData.length) - ensureCapacity( size() * 2 + 1); - if (index > size() || index < 0) { //index == size时相当于在尾后插入 - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - for (int i = size; i > index; i--) { - elementData[i] = elementData[i-1]; - } - elementData[index] = o; - size++; - - } - - private void ensureCapacity(int newCapacity) { - if (newCapacity < size()) - return; - Object[] old = elementData; - elementData = new Object[newCapacity]; - for (int i = 0; i < size(); i++) { - elementData[i] = old[i]; - } - } - - public Object get(int index){ - if (index >= size() || index < 0) { //获取时,index==size()越界 - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - return elementData[index]; - } - - private String outOfBoundsMsg(int index) { - return "Index:" + index + ", Size:" + size; - } - - public Object remove(int index){ - if (index >= size() || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - Object old = elementData[index]; - for (int i = index; i < size(); i++) { - elementData[i] = elementData[i+1]; - } - size--; - return old; - } - - /*获取表内容量*/ - public int size(){ - return size; - } - - public Iterator iterator(){ - return new ArrayListIterator(); - } - - public class ArrayListIterator implements Iterator { - private final int ONLY_CAPACITY = size; - private int index; - public ArrayListIterator() { - index = 0; - } - - @Override - public boolean hasNext() { - if (ONLY_CAPACITY != size) - throw new ConcurrentModificationException("此对象没有进行修改同步"); - return index != size; - } - - @Override - public Object next() { - if (ONLY_CAPACITY != size) - throw new ConcurrentModificationException("此对象没有进行修改同步"); - if (index >= ONLY_CAPACITY) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - return elementData[index++]; - } - } -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/BinaryTreeNode.java b/group11/1178243325/DataStructure/src/main/java/com/coding/basic/BinaryTreeNode.java deleted file mode 100644 index 1cf38aee30..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/BinaryTreeNode.java +++ /dev/null @@ -1,33 +0,0 @@ -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; - } - -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/LinkedList.java b/group11/1178243325/DataStructure/src/main/java/com/coding/basic/LinkedList.java deleted file mode 100644 index d82349089b..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/LinkedList.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.exception.*; -public class LinkedList implements List { - - 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() { - if (capacity != size) - throw new ConcurrentModificationException("此对象没有修改同步"); - return index < capacity; - } - - @Override - public Object next() { - if (capacity != size) - throw new ConcurrentModificationException("此对象没有修改同步"); - if (index >= capacity) - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - return get(index++); - } - } - - 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; - } - - void setData(Object data) { - this.data = data; - } - - Object getData() { - return data; - } - - void setNext(Node next) { - this.next = next; - } - - Object getNext() { - return next; - } - } -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Queue.java b/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Queue.java deleted file mode 100644 index a5c31f5a09..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Queue.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.coding.basic; -import com.coding.basic.exception.*; -public class Queue { - - private LinkedList elementData; - - public Queue() { - elementData = new LinkedList(); - } - - public void enQueue(Object o){ - elementData.addLast(o); - } - - public Object deQueue(){ - if (isEmpty()) { - throw new EmptyQueueException("队空"); - } - Object result = elementData.removeFirst(); - return result; - } - - public boolean isEmpty(){ - return elementData.size() == 0; - } - - public int size(){ - return elementData.size(); - } -} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Stack.java b/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Stack.java deleted file mode 100644 index e41c662792..0000000000 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Stack.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.coding.basic; - -import com.coding.basic.exception.*; -public class Stack { - - private ArrayList elementData; - public Stack() { - elementData = new ArrayList(); - } - - public void push(Object o){ - elementData.add(o); - } - - public Object pop(){ - if (isEmpty()) { - throw new EmptyStackException("栈空"); - } - Object result = elementData.get(size()-1); - elementData.remove(size()-1); - return result; - } - - public Object peek(){ - if (isEmpty()) { - throw new EmptyStackException("栈空"); - } - return elementData.get(0); - } - - public boolean isEmpty(){ - return elementData.size() == 0; - } - - public int size(){ - return elementData.size(); - } -} diff --git a/group11/1178243325/DataStructure/src/main/resources/struts.xml b/group11/1178243325/DataStructure/src/main/resources/struts.xml deleted file mode 100644 index ae0ce37fd8..0000000000 --- a/group11/1178243325/DataStructure/src/main/resources/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group11/1178243325/DataStructure/struts.xml b/group11/1178243325/DataStructure/struts.xml deleted file mode 100644 index 0582b7d4ea..0000000000 --- a/group11/1178243325/DataStructure/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group11/1178243325/week01/build.gradle b/group11/1178243325/week01/build.gradle new file mode 100644 index 0000000000..50d1380b3f --- /dev/null +++ b/group11/1178243325/week01/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java' + +repositories { + mavenCentral(); +} + +dependencies { + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week01/readme.md b/group11/1178243325/week01/readme.md new file mode 100644 index 0000000000..314098dd59 --- /dev/null +++ b/group11/1178243325/week01/readme.md @@ -0,0 +1,16 @@ +## 讲课内容: +- 17-2-15: 社群kickoff +- 17-2-19:讲解Java自测题和基本数据结构 +- 17-2-22:计算机组成原理和计算机编程语言 +- 17-2-26:程序的机器级表示 + +## 第一周作业(2-15 至 2-26) +- 实现各种基本数据结构(ArrayList, Stack, LinkedList, Queue, Tree, Iterator) +- 写一篇介绍CPU,内存,硬盘,指令以及他们之间的关系 + +## 完成情况: +- 基本数据结构已完成 +- [文章地址](http://www.jianshu.com/p/8d8379aa1281) + +## 我的收获: +- [漫谈计算机组成原理和编程语言](http://www.jianshu.com/p/07df48adf338) diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/Iterator.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/Iterator.java new file mode 100644 index 0000000000..1e73a2a4b9 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/Iterator.java @@ -0,0 +1,6 @@ +package com.sprint.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/ConcurrentModificationException.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/ConcurrentModificationException.java new file mode 100644 index 0000000000..c91c388bbd --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/ConcurrentModificationException.java @@ -0,0 +1,9 @@ +package com.sprint.basic.exception; + +public class ConcurrentModificationException extends RuntimeException { + public ConcurrentModificationException() {} + public ConcurrentModificationException(String msg) { + super(msg); + } +} + diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyQueueException.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyQueueException.java similarity index 81% rename from group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyQueueException.java rename to group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyQueueException.java index 2ee7aa4ee7..ddf89ac120 100644 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyQueueException.java +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyQueueException.java @@ -1,4 +1,4 @@ -package com.coding.basic.exception; +package com.sprint.basic.exception; public class EmptyQueueException extends RuntimeException { public EmptyQueueException() {} diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyStackException.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyStackException.java similarity index 81% rename from group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyStackException.java rename to group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyStackException.java index 2a5ae4055d..d654c7cd16 100644 --- a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/EmptyStackException.java +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/exception/EmptyStackException.java @@ -1,4 +1,4 @@ -package com.coding.basic.exception; +package com.sprint.basic.exception; public class EmptyStackException extends RuntimeException { public EmptyStackException() {} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/list/ArrayList.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/ArrayList.java new file mode 100644 index 0000000000..fb64e93f36 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/ArrayList.java @@ -0,0 +1,99 @@ +package com.sprint.basic.list; + +import com.sprint.basic.exception.ConcurrentModificationException; +import com.sprint.basic.Iterator; +public class ArrayList implements List { + + private int size; + private Object[] elementData; + + public ArrayList () { + size = 0; + elementData = new Object[100]; + } + + public boolean add(Object o) { + add(size(), o); + return true; + } + + public boolean add(int index, Object o){ + if (size() == elementData.length) + ensureCapacity( size() * 2 + 1); + if (index > size() || index < 0) { //index == size时相当于在尾后插入 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + for (int i = size; i > index; i--) { + elementData[i] = elementData[i-1]; + } + elementData[index] = o; + size++; + return true; + } + + private void ensureCapacity(int newCapacity) { + if (newCapacity < size()) + return; + Object[] old = elementData; + elementData = new Object[newCapacity]; + for (int i = 0; i < size(); i++) { + elementData[i] = old[i]; + } + } + + public Object get(int index){ + if (index >= size() || index < 0) { //获取时,index==size()越界 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + return elementData[index]; + } + + private String outOfBoundsMsg(int index) { + return "Index:" + index + ", Size:" + size; + } + + public Object remove(int index){ + if (index >= size() || index < 0) { + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + Object old = elementData[index]; + for (int i = index; i < size(); i++) { + elementData[i] = elementData[i+1]; + } + size--; + return old; + } + + /*获取表内容量*/ + public int size(){ + return size; + } + + public Iterator iterator(){ + return new ArrayListIterator(); + } + + public class ArrayListIterator implements Iterator { + private final int ONLY_CAPACITY = size; + private int index; + public ArrayListIterator() { + index = 0; + } + + @Override + public boolean hasNext() { + if (ONLY_CAPACITY != size) + throw new ConcurrentModificationException("此对象没有进行修改同步"); + return index != size; + } + + @Override + public Object next() { + if (ONLY_CAPACITY != size) + throw new ConcurrentModificationException("此对象没有进行修改同步"); + if (index >= ONLY_CAPACITY) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + return elementData[index++]; + } + } +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/list/LinkedList.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/LinkedList.java new file mode 100644 index 0000000000..503f41f65b --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/LinkedList.java @@ -0,0 +1,160 @@ +package com.sprint.basic.list; + +import com.sprint.basic.exception.ConcurrentModificationException; +import com.sprint.basic.Iterator; +import java.util.Objects; +public class LinkedList implements List { + + private Node head; + private int size; + public LinkedList() { + head = new Node(null, null); + size = 0; + } + + public boolean add(Object o) { + add(size, o); + return true; + } + + public boolean 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++; + return true; + } + + /*getNode getPreNodeByElement getNextNodeByElement的效率低些*/ + private Node getNode(int index) { + Node node = head; + int i = 0; + while(node.next != null && i <= index) { + node = node.next; + i++; + } + return node; + } + + private Node getPreNodeByElement(Object obj) { + if (obj != null) { + for (int i = 0; i < size(); i++) { + if (getNode(i).data == obj) { + return getNode(i-1); + } + } + } + return null; + } + + private Node getNextNodeByElement(Object obj) { + if (obj != null) { + for (int i = 0; i < size(); i++) { + if (getNode(i).data == obj) { + return getNode(i+1); + } + } + } + return null; + } + + 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() { + if (capacity != size) + throw new ConcurrentModificationException("此对象没有修改同步"); + return index < capacity; + } + + @Override + public Object next() { + if (capacity != size) + throw new ConcurrentModificationException("此对象没有修改同步"); + if (index >= capacity) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + return get(index++); + } + } + + 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; + } + + void setData(Object data) { + this.data = data; + } + + Object getData() { + return data; + } + + void setNext(Node next) { + this.next = next; + } + + Object getNext() { + return next; + } + } +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/list/List.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/List.java new file mode 100644 index 0000000000..0e90471a48 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/list/List.java @@ -0,0 +1,10 @@ +package com.sprint.basic.list; +import com.sprint.basic.Iterator; +public interface List { + public boolean add(Object o); + public boolean add(int index, Object o); + public Object get(int index); + public Object remove(int index); + public int size(); + public Iterator iterator(); +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/queue/Queue.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/queue/Queue.java new file mode 100644 index 0000000000..47f7b98d96 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/queue/Queue.java @@ -0,0 +1,32 @@ +package com.sprint.basic.queue; +import com.sprint.basic.exception.EmptyQueueException; +import com.sprint.basic.list.LinkedList; +public class Queue { + + private LinkedList elementData; + + public Queue() { + elementData = new LinkedList(); + } + + public boolean enQueue(Object o){ + elementData.addLast(o); + return true; + } + + public Object deQueue(){ + if (isEmpty()) { + throw new EmptyQueueException("队空"); + } + Object result = elementData.removeFirst(); + return result; + } + + public boolean isEmpty(){ + return elementData.size() == 0; + } + + public int size(){ + return elementData.size(); + } +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/stack/Stack.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/stack/Stack.java new file mode 100644 index 0000000000..e399dcb850 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/stack/Stack.java @@ -0,0 +1,40 @@ +package com.sprint.basic.stack; + +import com.sprint.basic.exception.EmptyStackException; +import com.sprint.basic.list.ArrayList; +public class Stack { + + private ArrayList elementData; + public Stack() { + elementData = new ArrayList(); + } + + public boolean push(Object o){ + elementData.add(o); + return true; + } + + public Object pop(){ + if (isEmpty()) { + throw new EmptyStackException("栈空"); + } + Object result = elementData.get(size()-1); + elementData.remove(size()-1); + return result; + } + + public Object peek(){ + if (isEmpty()) { + throw new EmptyStackException("栈空"); + } + return elementData.get(0); + } + + public boolean isEmpty(){ + return elementData.size() == 0; + } + + public int size(){ + return elementData.size(); + } +} diff --git a/group11/1178243325/week01/src/main/java/com/sprint/basic/tree/BinaryTreeNode.java b/group11/1178243325/week01/src/main/java/com/sprint/basic/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..efaf261521 --- /dev/null +++ b/group11/1178243325/week01/src/main/java/com/sprint/basic/tree/BinaryTreeNode.java @@ -0,0 +1,122 @@ +package com.sprint.basic.tree; + +public class BinaryTreeNode { + + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + private int size; + + 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(T data) { + if (this.data == null) { + this.data = data; + return this; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + if (this.left == null) { + this.left = new BinaryTreeNode(); + this.left.data = data; + return this.left; + } else { + return this.left.insert(data); + } + } else if (compareResult < 0) { + if (this.right == null) { + this.right = new BinaryTreeNode(); + this.right.data = data; + return this.right; + } else { + return this.right.insert(data); + } + } else { + return this; + } + } + + /*没看懂*/ + public BinaryTreeNode delete(T data) { + BinaryTreeNode treeNode = search(data); + if (treeNode == null) { + return null; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + return this.left.delete(data); + } else if (compareResult < 0) { + return this.right.delete(data); + } else { + if (treeNode.right == null) { + if (this.left == null) { + this.data = null; + } else { + this.left = this; + } + } else { + this.data = (T) this.right.findMin().data; + + this.right.delete(this.data); + } + } + + return this; + } + + private BinaryTreeNode findMin() { + if (this.data == null) { + return null; + } + if (this.left == null) { + return this; + } + return this.left.findMin(); + } + + public BinaryTreeNode search(T data) { + if (this.data == null) { + return null; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + if (this.left == null) { + return null; + } else { + return this.left.search(data); + } + } else if (compareResult < 0) { + if (this.right == null) { + return null; + } else { + return this.right.search(data); + } + } else { + return this; + } + } + + +} diff --git a/group11/1178243325/week01/src/test/java/com/sprint/basic/list/ArrayListTest.java b/group11/1178243325/week01/src/test/java/com/sprint/basic/list/ArrayListTest.java new file mode 100644 index 0000000000..63936c288c --- /dev/null +++ b/group11/1178243325/week01/src/test/java/com/sprint/basic/list/ArrayListTest.java @@ -0,0 +1,56 @@ +package com.sprint.basic.list; + +import com.sprint.basic.Iterator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ArrayListTest { + private List list; + + @Before + public void init() { + list = new ArrayList(); + } + + @Test + public void add() { + for (int i = 0; i < 5; i++) { + list.add(i); + } + /*Assert.assertTrue(args): if (args != true) to failed*/ + System.out.println(list); + Assert.assertTrue(list.add(5)); + Assert.assertEquals(6, list.size()); + Assert.assertTrue(list.add(3, 10)); + Assert.assertEquals(7, list.size()); + + } + + @Test + public void remove() { + add(); + Assert.assertEquals(5, list.remove(6)); + Assert.assertEquals(6, list.size()); + } + + @Test + public void get() { + add(); + Assert.assertEquals(5, list.get(6)); + } + + @Test + public void testIterator() { + for (int i = 0; i < 10; i++) { + Assert.assertTrue(list.add(i)); + } + Iterator iter = list.iterator(); + int count = 0; + while(iter.hasNext()) { + Assert.assertEquals(count, iter.next()); + count++; + } + } + +} diff --git a/group11/1178243325/week01/src/test/java/com/sprint/basic/list/LinkedListTest.java b/group11/1178243325/week01/src/test/java/com/sprint/basic/list/LinkedListTest.java new file mode 100644 index 0000000000..c5ab12aa4e --- /dev/null +++ b/group11/1178243325/week01/src/test/java/com/sprint/basic/list/LinkedListTest.java @@ -0,0 +1,56 @@ +package com.sprint.basic.list; + +import com.sprint.basic.Iterator; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + private List list; + + @Before + public void init() { + list = new LinkedList(); + } + + @Test + public void add() { + for (int i = 0; i < 5; i++) { + list.add(i); + } + /*Assert.assertTrue(args): if (args != true) to failed*/ + System.out.println(list); + Assert.assertTrue(list.add(5)); + Assert.assertEquals(6, list.size()); + Assert.assertTrue(list.add(3, 10)); + Assert.assertEquals(7, list.size()); + + } + + @Test + public void remove() { + add(); + Assert.assertEquals(5, list.remove(6)); + Assert.assertEquals(6, list.size()); + } + + @Test + public void get() { + add(); + Assert.assertEquals(5, list.get(6)); + } + + @Test + public void testIterator() { + for (int i = 0; i < 10; i++) { + Assert.assertTrue(list.add(i)); + } + Iterator iter = list.iterator(); + int count = 0; + while(iter.hasNext()) { + Assert.assertEquals(count, iter.next()); + count++; + } + } + +} diff --git a/group11/1178243325/week01/src/test/java/com/sprint/basic/queue/QueueTest.java b/group11/1178243325/week01/src/test/java/com/sprint/basic/queue/QueueTest.java new file mode 100644 index 0000000000..b7cfe4b32f --- /dev/null +++ b/group11/1178243325/week01/src/test/java/com/sprint/basic/queue/QueueTest.java @@ -0,0 +1,20 @@ +package com.sprint.basic.queue; + +import org.junit.Assert; +import org.junit.Test; +public class QueueTest { + + private Queue queue = new Queue(); + + @Test + public void testQueueApi() { + Assert.assertTrue(queue.enQueue(1)); + Assert.assertTrue(queue.enQueue(2)); + Assert.assertFalse(queue.isEmpty()); + Assert.assertEquals(2, queue.size()); + Assert.assertEquals(1, queue.deQueue()); + Assert.assertEquals(2, queue.deQueue()); + Assert.assertEquals(0, queue.size()); + Assert.assertTrue(queue.isEmpty()); + } +} diff --git a/group11/1178243325/week01/src/test/java/com/sprint/basic/stack/StackTest.java b/group11/1178243325/week01/src/test/java/com/sprint/basic/stack/StackTest.java new file mode 100644 index 0000000000..e267c59971 --- /dev/null +++ b/group11/1178243325/week01/src/test/java/com/sprint/basic/stack/StackTest.java @@ -0,0 +1,23 @@ +package com.sprint.basic.stack; + +import org.junit.Assert; +import org.junit.Test; + +public class StackTest { + + private Stack stack = new Stack(); + + @Test + public void testStack() { + Assert.assertTrue(stack.push(1)); + Assert.assertEquals(1, stack.pop()); + Assert.assertTrue(stack.push(2)); + Assert.assertTrue(stack.push(3)); + Assert.assertTrue(stack.push(4)); + Assert.assertEquals(4, stack.pop()); + Assert.assertEquals(2, stack.peek()); + Assert.assertEquals(2, stack.size()); + Assert.assertFalse(stack.isEmpty()); + } + +} diff --git a/group11/1178243325/week01/src/test/java/com/sprint/basic/tree/BinaryTreeNodeTest.java b/group11/1178243325/week01/src/test/java/com/sprint/basic/tree/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..d9a27ab211 --- /dev/null +++ b/group11/1178243325/week01/src/test/java/com/sprint/basic/tree/BinaryTreeNodeTest.java @@ -0,0 +1,54 @@ +package com.sprint.basic.tree; + +import org.junit.Assert; +/*参考程序*/ +public class BinaryTreeNodeTest { + + private BinaryTreeNode treeNode; + + @org.junit.Before + public void setUp() throws Exception { + treeNode = new BinaryTreeNode<>(); + treeNode.insert(5); + treeNode.insert(3); + treeNode.insert(7); + treeNode.insert(1); + treeNode.insert(4); + treeNode.insert(2); + treeNode.insert(8); + treeNode.insert(6); + } + + @org.junit.Test + public void insert() { + Assert.assertEquals(treeNode.getData().intValue(), 5); + Assert.assertEquals(treeNode.getLeft().getData(), 3); + Assert.assertEquals(treeNode.getRight().getData(), 7); + Assert.assertEquals(treeNode.getLeft().getLeft().getData(), 1); + Assert.assertEquals(treeNode.getLeft().getRight().getData(), 4); + Assert.assertEquals(treeNode.getLeft().getLeft().getRight().getData(), 2); + Assert.assertEquals(treeNode.getRight().getRight().getData(), 8); + Assert.assertEquals(treeNode.getRight().getLeft().getData(), 6); + } + + @org.junit.Test + public void delete() throws Exception { + treeNode.delete(3); + for (int i = 1; i < 9; i++) { + if (i != 3) { + Assert.assertNotNull(treeNode.search(i)); + } else { + Assert.assertNull(treeNode.search(i)); + } + } + } + + @org.junit.Test + public void search() throws Exception { + for (int i = 1; i < 9; i++) { + Assert.assertNotNull(treeNode.search(i)); + } + Assert.assertNull(treeNode.search(0)); + Assert.assertNull(treeNode.search(9)); + } +} diff --git a/group11/1178243325/week02/build.gradle b/group11/1178243325/week02/build.gradle new file mode 100644 index 0000000000..f6ebbb892e --- /dev/null +++ b/group11/1178243325/week02/build.gradle @@ -0,0 +1,12 @@ +apply plugin: 'java' + + +repositories { + maven { url "http://maven.aliyun.com/nexus/content/groups/public" } + mavenCentral() +} + +dependencies { + compile("org.jdom:jdom2:2.0.5") + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week02/readme.md b/group11/1178243325/week02/readme.md new file mode 100644 index 0000000000..a4f9adc15a --- /dev/null +++ b/group11/1178243325/week02/readme.md @@ -0,0 +1,23 @@ +## 讲课内容: +- 17-03-01:第一周作业讲评 +- 17-03-05:漫谈进程和线程和布置第三周作业 + +## 第二周作业(2-27 至 3-5) +- 实现第一个大作业:读取struts.xml,执行Action +- 5道数据结构习题 + +## 完成情况: +- struts大作业完成 +- 数据结构习题完成 + +## 我的收获: +- TDD +- 操作系统抽象概念 +- 进程在虚拟存储器表示 +- 进程调度 +- 进程同步 +- 线程 + + +![99.jpg](http://upload-images.jianshu.io/upload_images/2031765-d3740acf4d284e93.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) + diff --git a/group11/1178243325/week02/src/main/java/com/sprint/array/ArrayUtil.java b/group11/1178243325/week02/src/main/java/com/sprint/array/ArrayUtil.java new file mode 100644 index 0000000000..01d7d5f0da --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/array/ArrayUtil.java @@ -0,0 +1,229 @@ +package com.sprint.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 static void reverseArray(int[] origin){ + if (origin == null) { + return; + } + + int length = origin.length; + int[] temp = new int[length]; + for (int i = 0; i < length; i++) + temp[i] = origin[i]; + for (int i = length - 1, j = 0; i >= 0 && j < length; i--, j++) + origin[j] = temp[i]; + } + + /** + * 现在有如下的一个数组: 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 new int[0]; + } + + int zeroCount = 0; + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] == 0) + zeroCount++; + } + int[] newArray = new int[oldArray.length-zeroCount]; + for (int i = 0, j = 0; i < oldArray.length && j < newArray.length; i++) { + if (oldArray[i] != 0) { + newArray[j] = oldArray[i]; + j++; + } + } + 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){ + if (array1 == null && array2 == null) + return new int[0]; + int index1 = 0, index2 = 0; + int[] array3 = new int[array1.length + array2.length]; + int index = 0; + while (index1 != array1.length && index2 != array2.length) { + if (array1[index1] < array2[index2]) { + array3[index++] = array1[index1++]; + } else if (array1[index1] > array2[index2]) { + array3[index++] = array2[index2++]; + } else if (array1[index1] == array2[index2]){ + array3[index++] = array1[index1++]; + index2++; + } + } + + if (index1 == array1.length && index2 != array2.length) { + for (int i = index2; i < array2.length; i++) + array3[index++] = array2[i]; + } else if (index2 == array2.length && index1 != array1.length) { + for (int i = index1; i < array1.length; i++) { + array3[index++] = array1[i]; + } + } + + int[] newArray = new int[index]; + for (int i = 0; i < newArray.length; i++) + newArray[i] = array3[i]; + return newArray; + } + /** + * 把一个已经存满数据的数组 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 (size <= 0) + return new int[0]; + 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]; + if (max == 1) + return new int[0]; + int[] array = new int[max]; + int i = 0; + int value = fibonaccis(i+1); + while ( value < max) { + array[i++] = value; + value = fibonaccis(i+1); + } + int[] newArray = new int[i]; + for (int j = 0; j < newArray.length; j++) { + newArray[j] = array[j]; + } + return newArray; + } + + private static int fibonaccis(int n) { + if (n <=0) + return 0; + if (n == 1 || n ==2 ) + return 1; + return fibonaccis(n-1)+fibonaccis(n-2); + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public static int[] getPrimes(int max){ + if (max <= 1) { + return new int[0]; + } + int[] array = new int[max]; + int index = 0; + for (int i = 2; i < max; i++) { + if (i == 2 || i == 3 || i == 5 || i == 7) + array[index++] = i; + if (i%2 !=0 && i%3 != 0 && i%5 != 0 && i%7 != 0) + array[index++] = i; + } + int[] newArray = new int[index]; + for (int i = 0; i < newArray.length; i++) { + newArray[i] = array[i]; + } + + return newArray; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public static int[] getPerfectNumbers(int max){ + if (max <= 0) + return new int[0]; + int[] array = new int[max]; + int index = 0; + for (int i = 1; i < max; i++) { + if (isPerfectNumber(i)) + array[index++] = i; + } + + int[] newArray = new int[index]; + for (int i = 0; i < newArray.length; i++) + newArray[i] = array[i]; + + return newArray; + } + + private static boolean isPerfectNumber(int n) { + int sum = 0; + int i = 1; + while (i < n) { + if (n%i == 0) + sum += i; + i++; + } + if (sum == n) + return true; + return false; + } + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param s + * @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]); + else + str.append(array[i] + seperator); + } + return str.toString(); + } + + +} diff --git a/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Configuration.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Configuration.java new file mode 100644 index 0000000000..0f10458fc3 --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Configuration.java @@ -0,0 +1,86 @@ +package com.sprint.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) { + InputStream is = this.getClass().getClassLoader().getResourceAsStream(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 actionName) { + ActionConfig ac = this.actions.get(actionName); + if(ac == null) { + return null; + } + return ac.getClassName(); + } + + public String getResultView(String actionName, String resultName) { + ActionConfig ac = this.actions.get(actionName); + 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/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ConfigurationException.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ConfigurationException.java new file mode 100644 index 0000000000..25c6784f43 --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ConfigurationException.java @@ -0,0 +1,18 @@ +package com.sprint.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/group11/1178243325/week02/src/main/java/com/sprint/litestruts/LoginAction.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/LoginAction.java new file mode 100644 index 0000000000..4b4f2b8e38 --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/LoginAction.java @@ -0,0 +1,40 @@ +package com.sprint.litestruts; + +/** + * 这是一个展示业务逻辑的类,其中用户名是硬编码 + * @author xingzhaohu + */ + +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 void setName(String name) { + this.name = name; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getName() { + return name; + } + + public String getPassword() { + return password; + } + + public String getMessage() { + return message; + } +} diff --git a/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtil.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtil.java new file mode 100644 index 0000000000..822355655b --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtil.java @@ -0,0 +1,70 @@ +package com.sprint.litestruts; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +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 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 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 e) { + throw new ReflectionUtilException(e); + } catch (IllegalArgumentException e) { + throw new ReflectionUtilException(e); + } catch (InvocationTargetException e) { + throw new ReflectionUtilException(e); + } + } + } + } + + } + + public static Map getParameterMap(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 e) { + throw new ReflectionUtilException(e); + } catch (IllegalArgumentException e) { + throw new ReflectionUtilException(e); + } catch (InvocationTargetException e) { + throw new ReflectionUtilException(e); + } + } + return params; + } + +} diff --git a/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtilException.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtilException.java new file mode 100644 index 0000000000..65cbfdf322 --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/ReflectionUtilException.java @@ -0,0 +1,20 @@ +package com.sprint.litestruts; + +import java.lang.reflect.InvocationTargetException; +public class ReflectionUtilException extends RuntimeException { + + public ReflectionUtilException(String msg) { + super(msg); + } + public ReflectionUtilException(IllegalAccessException e) { + super(e); + } + + public ReflectionUtilException(IllegalArgumentException e) { + super(e); + } + + public ReflectionUtilException(InvocationTargetException e) { + super(e); + } +} diff --git a/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Struts.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Struts.java new file mode 100644 index 0000000000..bff4dec33b --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/Struts.java @@ -0,0 +1,53 @@ +package com.sprint.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) { + /* + + 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字段中。 + + */ + + 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.getParameterMap(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/group11/1178243325/week02/src/main/java/com/sprint/litestruts/View.java b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/View.java new file mode 100644 index 0000000000..fb380de515 --- /dev/null +++ b/group11/1178243325/week02/src/main/java/com/sprint/litestruts/View.java @@ -0,0 +1,24 @@ +package com.sprint.litestruts; + +import java.util.Map; +public class View { + private String jsp; + private Map parameters; + + public void setJsp(String jsp) { + this.jsp = jsp; + } + + public String getJsp() { + return jsp; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public Map getParameters() { + return parameters; + } + +} diff --git a/group11/1178243325/week02/src/main/resources/struts.xml b/group11/1178243325/week02/src/main/resources/struts.xml new file mode 100644 index 0000000000..c82c7d1574 --- /dev/null +++ b/group11/1178243325/week02/src/main/resources/struts.xml @@ -0,0 +1,12 @@ + + + + /jsp/homepage.jsp + /jsp/showLogin.jsp + + + /jsp/welcome.jsp + /jsp/error.jsp + + + diff --git a/group11/1178243325/week02/src/test/java/com/sprint/array/ArrayUtilTest.java b/group11/1178243325/week02/src/test/java/com/sprint/array/ArrayUtilTest.java new file mode 100644 index 0000000000..9cba21f7cf --- /dev/null +++ b/group11/1178243325/week02/src/test/java/com/sprint/array/ArrayUtilTest.java @@ -0,0 +1,76 @@ +package com.sprint.array; + +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Test; +public class ArrayUtilTest { + + @Test + public void testReverseArray() { + int[] a = new int[]{7, 9, 30, 3}; + int[] expected = new int[]{3, 30, 9, 7}; + ArrayUtil.reverseArray(a); + Assert.assertArrayEquals(a, expected); + a = new int[]{7, 9, 30, 3, 4}; + expected = new int[]{4, 3, 30, 9, 7}; + ArrayUtil.reverseArray(a); + Assert.assertArrayEquals(a, expected); + } + + @Test + public void testRemoveZero() { + int[] oldArr = new int[]{1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; + int[] expected = new int[]{1,3,4,5,6,6,5,4,7,6,7,5}; + Assert.assertArrayEquals(ArrayUtil.removeZero(oldArr), expected); + oldArr = new int[]{1, 0, 2, 0, 3, 0}; + expected = new int[]{1, 2, 3}; + Assert.assertArrayEquals(ArrayUtil.removeZero(oldArr), expected); + } + + @Test + public void testMerge() { + int[] a1 = {3, 5, 7, 8}; + int[] a2 = {4, 5, 6, 7}; + int[] a3 = {3, 4, 5, 6, 7, 8}; + Assert.assertArrayEquals(ArrayUtil.merge(a1, a2), a3); + } + + @Test + public void testGrow() { + int[] oldArray = new int[]{2, 3, 6}; + int[] expected = new int[]{2, 3, 6, 0, 0, 0}; + Assert.assertArrayEquals(ArrayUtil.grow(oldArray, 3), expected); + } + + @Test + public void testFibonacci() { + int[] expected = new int[]{1, 1, 2, 3, 5, 8, 13}; + Assert.assertArrayEquals(ArrayUtil.fibonacci(15), expected); + expected = new int[0]; + Assert.assertArrayEquals(ArrayUtil.fibonacci(1), expected); + /*GET 新技能: [] == new int[0]*/ + System.out.println(Arrays.toString(expected)); + } + + @Test + public void testGetPrimes() { + int[] expected = new int[]{2,3,5,7,11,13,17,19}; + Assert.assertArrayEquals(ArrayUtil.getPrimes(23), expected); + } + + @Test + public void testGetPerfectNumbers() { + int[] result = new int[]{6}; + int length = ArrayUtil.getPerfectNumbers(7).length; + System.out.println(length); + Assert.assertArrayEquals(ArrayUtil.getPerfectNumbers(7), result); + } + + @Test + public void tetJoin() { + String result = "3-8-9"; + int[] array = {3, 8, 9}; + Assert.assertEquals(ArrayUtil.join(array, "-"), result); + } + +} diff --git a/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ConfigurationTest.java b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ConfigurationTest.java new file mode 100644 index 0000000000..f4b5f91668 --- /dev/null +++ b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ConfigurationTest.java @@ -0,0 +1,31 @@ +package com.sprint.litestruts; + +import org.junit.Test; +import org.junit.Assert; +public class ConfigurationTest { + Configuration cfg = new Configuration("struts.xml"); + + @Test + public void testGetClassName() { + String clzName = cfg.getClassName("login"); + Assert.assertEquals("com.sprint.litestruts.LoginAction", clzName); + clzName = cfg.getClassName("logout"); + Assert.assertEquals("com.sprint.litestruts.LoginAction", 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/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ReflectionUtilTest.java b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ReflectionUtilTest.java new file mode 100644 index 0000000000..c6fb04bda6 --- /dev/null +++ b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/ReflectionUtilTest.java @@ -0,0 +1,92 @@ +package com.sprint.litestruts; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.HashSet; +import java.util.HashMap; +import java.util.Set; +import java.util.Map; + + +import org.junit.Test; +import org.junit.Assert; +public class ReflectionUtilTest { + + @Test + public void testGetSetterMethod() throws Exception{ + String name = "com.sprint.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 testGetGetterMethod() throws Exception { + String name = "com.sprint.litestruts.LoginAction"; + Class clz = Class.forName(name); + List methods = ReflectionUtil.getGetterMethods(clz); + + Assert.assertEquals(3, methods.size()); + + List expectedNames = new ArrayList<>(); + expectedNames.add("getName"); + expectedNames.add("getPassword"); + expectedNames.add("getMessage"); + + 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.sprint.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 testGetParameters() throws Exception { + String name = "com.sprint.litestruts.LoginAction"; + Class clz = Class.forName(name); + LoginAction action = (LoginAction)clz.newInstance(); + action.setName("test"); + action.setPassword("123456"); + + Map params = ReflectionUtil.getParameterMap(action); + Assert.assertEquals(3, params.size()); + Assert.assertEquals(null, params.get("message")); + Assert.assertEquals("test", params.get("name")); + Assert.assertEquals("123456", params.get("password")); + + } + +} diff --git a/group11/1178243325/week02/src/test/java/com/sprint/litestruts/StrutsTest.java b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/StrutsTest.java new file mode 100644 index 0000000000..d8c68d2807 --- /dev/null +++ b/group11/1178243325/week02/src/test/java/com/sprint/litestruts/StrutsTest.java @@ -0,0 +1,32 @@ +package com.sprint.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/1178243325/week03/build.gradle b/group11/1178243325/week03/build.gradle new file mode 100644 index 0000000000..c4da624f95 --- /dev/null +++ b/group11/1178243325/week03/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + testCompile("junit:junit:4.12") +} diff --git a/group11/1178243325/week03/readme.md b/group11/1178243325/week03/readme.md new file mode 100644 index 0000000000..5de5dada98 --- /dev/null +++ b/group11/1178243325/week03/readme.md @@ -0,0 +1,16 @@ +## 讲课内容: +- 17-03-07:答疑(YY) +- 17-03-09:TDD和第二次作业讲解 +- 17-03-12:职场15年 + +## 第三周作业(3-6 至 3-12) +- 实现第二个大作业:多线程下载文件,支持断点续传 +- 5道数据结构习题 + +## 完成情况: +- 多线程完成 +- 待重构 + +## 我的收获: +- TTD大法好 +- 面向对象的思想以及抽象化,更深刻 diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/Iterator.java b/group11/1178243325/week03/src/main/java/com/sprint/basic/Iterator.java similarity index 100% rename from group11/1178243325/DataStructure/src/main/java/com/coding/basic/Iterator.java rename to group11/1178243325/week03/src/main/java/com/sprint/basic/Iterator.java diff --git a/group11/1178243325/week03/src/main/java/com/sprint/basic/LinkedList.java b/group11/1178243325/week03/src/main/java/com/sprint/basic/LinkedList.java new file mode 100644 index 0000000000..ac4128fe80 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/basic/LinkedList.java @@ -0,0 +1,319 @@ +package com.sprint.basic; + +import com.sprint.basic.exception.ConcurrentModificationException; +import java.util.Objects; +public class LinkedList implements List { + + 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++; + + } + + /*getNode getPreNodeByElement getNextNodeByElement的效率低些*/ + private Node getNode(int index) { + Node node = head; + int i = 0; + while(node.next != null && i <= index) { + node = node.next; + i++; + } + return node; + } + + private Node getPreNodeByElement(Object obj) { + if (obj != null) { + for (int i = 0; i < size(); i++) { + if (getNode(i).data == obj) { + return getNode(i-1); + } + } + } + return null; + } + + private Node getNextNodeByElement(Object obj) { + if (obj != null) { + for (int i = 0; i < size(); i++) { + if (getNode(i).data == obj) { + return getNode(i+1); + } + } + } + return null; + } + 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() { + if (capacity != size) + throw new ConcurrentModificationException("此对象没有修改同步"); + return index < capacity; + } + + @Override + public Object next() { + if (capacity != size) + throw new ConcurrentModificationException("此对象没有修改同步"); + if (index >= capacity) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + return get(index++); + } + } + + 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; + } + + void setData(Object data) { + this.data = data; + } + + Object getData() { + return data; + } + + void setNext(Node next) { + this.next = next; + } + + Object getNext() { + return next; + } + } + + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Object[] oldData = new Object[size]; + Node temp = head; + int index = 1; + while(temp.next != null) { + temp = temp.next; + oldData[size - index] = temp.data; + index++; + } + + index = 0; + temp = head; + while(temp.next != null) { + temp = temp.next; + temp.data = oldData[index]; + index++; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + + public void removeFirstHalf(){ + int count = size; + if (count % 2 != 0) { + for (int i = 0; i <= count/2; i++) { + removeFirst(); + } + } else { + for (int i = 0; i < count/2; i++) { + removeFirst(); + } + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + + public void remove(int i, int length){ + if (i < 0 || length < 0) { + return; + } + if (i == 0) { + for (int k = 0; k < length; k++) + removeFirst(); + } else { + while (length > 0) { + remove(i-1); + 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 (list.size() == 0) { + return new int[0]; + } + int[] array = new int[list.size()]; + int index = 0; + for (int i = 0; i < list.size(); i++) { + array[i] = (int)get((int)list.get(i)); + } + return array; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + * @param list + */ + public void subtract(LinkedList list){ + if (list.size() == 0) { + return; + } + for (int i = 0; i < list.size(); i++) { + removeElement(list.get(i)); + } + } + + private Object removeElement(Object obj) { + if (obj == null) { + return null; + } + Node preNode = getPreNodeByElement(obj); + Node nextNode = getNextNodeByElement(obj); + if (preNode == null && nextNode == null) + return null; + preNode.next = nextNode; + return obj; + } + + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + + public void removeDuplicateValues(){ + if (size == 0 || size == 1) { + return; + } + + Node p1 = head; + Node p2 = head.next; + + while (p1 != null && p2 != null) { + if (Objects.equals(p1.data, p2.data)) { + p2 = p2.next; + p1.next = p2; + size--; + } else { + p1 = p2; + p2 = p2.next; + } + } + } + + + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于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/group11/1178243325/DataStructure/src/main/java/com/coding/basic/List.java b/group11/1178243325/week03/src/main/java/com/sprint/basic/List.java similarity index 100% rename from group11/1178243325/DataStructure/src/main/java/com/coding/basic/List.java rename to group11/1178243325/week03/src/main/java/com/sprint/basic/List.java diff --git a/group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/ConcurrentModificationException.java b/group11/1178243325/week03/src/main/java/com/sprint/basic/exception/ConcurrentModificationException.java similarity index 100% rename from group11/1178243325/DataStructure/src/main/java/com/coding/basic/exception/ConcurrentModificationException.java rename to group11/1178243325/week03/src/main/java/com/sprint/basic/exception/ConcurrentModificationException.java diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/DownloadThread.java b/group11/1178243325/week03/src/main/java/com/sprint/download/DownloadThread.java new file mode 100644 index 0000000000..434b60e7be --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/DownloadThread.java @@ -0,0 +1,36 @@ +package com.sprint.download; + +import com.sprint.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; + } + + @Override + 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(); + barrier.await(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/FileDownloader.java b/group11/1178243325/week03/src/main/java/com/sprint/download/FileDownloader.java new file mode 100644 index 0000000000..9a817aefaf --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/FileDownloader.java @@ -0,0 +1,89 @@ +package com.sprint.download; + +import com.sprint.download.api.Connection; +import com.sprint.download.api.ConnectionManager; +import com.sprint.download.api.DownloadListener; +import java.util.concurrent.CyclicBarrier; +import java.io.RandomAccessFile; +import java.io.IOException; +public class FileDownloader { + private String url; + private String localFile; + + DownloadListener listener; + ConnectionManager cm; + + private static final int DOWNLOAD_THREAD_NUM = 3; + + public FileDownloader(String _url, String localFile) { + this.url = _url; + this.localFile = localFile; + } + + public void execute() { + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_THREAD_NUM, new Runnable() { + public void run() { + listener.notifyFinished(); + } + }); + + Connection conn = null; + + try { + conn = cm.open(this.url); + int length = conn.getContentLength(); + createPlaceHolderFile(this.localFile, length); + int[][] ranges = allocateDownloadRange(DOWNLOAD_THREAD_NUM, length); + for (int i = 0; i < DOWNLOAD_THREAD_NUM; i++) { + DownloadThread thread = new DownloadThread( + cm.open(url), + ranges[i][0], + ranges[i][1], + localFile, + barrier); + thread.start(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (conn != null) { + conn.close(); + } + } + } + + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException { + RandomAccessFile file = new RandomAccessFile(fileName, "rw"); + for (int i = 0; i < contentLen; i++) { + file.write(0); + } + file.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 listener; + } +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/api/Connection.java b/group11/1178243325/week03/src/main/java/com/sprint/download/api/Connection.java new file mode 100644 index 0000000000..958a0b1ce3 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/api/Connection.java @@ -0,0 +1,26 @@ +package com.sprint.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/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionException.java b/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionException.java new file mode 100644 index 0000000000..f9ec627440 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionException.java @@ -0,0 +1,7 @@ +package com.sprint.download.api; + +public class ConnectionException extends Exception { + public ConnectionException(Exception e) { + super(e); + } +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionManager.java b/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionManager.java new file mode 100644 index 0000000000..f20bbacc87 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/api/ConnectionManager.java @@ -0,0 +1,11 @@ +package com.sprint.download.api; + +public interface ConnectionManager { + /** + * 给定一个url, 打开一个连接 + * @param url + * @return + */ + + public Connection open(String url) throws ConnectionException; +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/api/DownloadListener.java b/group11/1178243325/week03/src/main/java/com/sprint/download/api/DownloadListener.java new file mode 100644 index 0000000000..fc95ba8199 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.sprint.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionImpl.java b/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..c6c1f32cb4 --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionImpl.java @@ -0,0 +1,68 @@ +package com.sprint.download.impl; + +import com.sprint.download.api.Connection; +import com.sprint.download.api.ConnectionException; +import java.util.Arrays; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.HttpURLConnection; + +public class ConnectionImpl implements Connection { + + URL url; + static final int BUFFER_SIZE = 1024; + + ConnectionImpl(String _url) throws ConnectionException { + try { + 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 is = httpConn.getInputStream(); + 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 (IOException e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + } +} diff --git a/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionManagerImpl.java b/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..7a012808ef --- /dev/null +++ b/group11/1178243325/week03/src/main/java/com/sprint/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,14 @@ +package com.sprint.download.impl; + +import com.sprint.download.api.Connection; +import com.sprint.download.api.ConnectionException; +import com.sprint.download.api.ConnectionManager; +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } +} + + diff --git a/group11/1178243325/week03/src/test/java/com/sprint/download/FileDownloaderTest.java b/group11/1178243325/week03/src/test/java/com/sprint/download/FileDownloaderTest.java new file mode 100644 index 0000000000..6e3bccd2dc --- /dev/null +++ b/group11/1178243325/week03/src/test/java/com/sprint/download/FileDownloaderTest.java @@ -0,0 +1,41 @@ +package com.sprint.download; + +import com.sprint.download.api.ConnectionManager; +import com.sprint.download.api.DownloadListener; +import com.sprint.download.impl.ConnectionManagerImpl; + +import org.junit.Assert; +import org.junit.Test; +public class FileDownloaderTest { + boolean downloadFinished = false; + + @Test + public void testDownload() { + String url = "http://images2015.cnblogs.com/blog/610238/201604/610238-20160421154632101-286208268.png"; + FileDownloader downloader = new FileDownloader(url, "/home/sprint/xxx/test.jpg");// 保存地址时我的本地地址 + + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = false; + } + }); + + downloader.execute(); + + //等待多线程下载 + while (!downloadFinished) { + try { + System.out.println("还没有下载完成,休眠五秒"); + //休眠5秒 + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("下载完成!"); + } +} diff --git a/group11/1178243325/week03/src/test/java/com/sprint/download/api/ConnectionTest.java b/group11/1178243325/week03/src/test/java/com/sprint/download/api/ConnectionTest.java new file mode 100644 index 0000000000..4322814936 --- /dev/null +++ b/group11/1178243325/week03/src/test/java/com/sprint/download/api/ConnectionTest.java @@ -0,0 +1,21 @@ +package com.sprint.download.api; + +import com.sprint.download.impl.ConnectionManagerImpl; +import org.junit.Assert; +import org.junit.Test; +public class ConnectionTest { + + @Test + public void testGetContentLength() throws Exception { + 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 Exception { + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open("http://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"); + + } +} diff --git a/group11/1178243325/week04/readme.md b/group11/1178243325/week04/readme.md new file mode 100644 index 0000000000..2199199aef --- /dev/null +++ b/group11/1178243325/week04/readme.md @@ -0,0 +1,12 @@ +## 讲课内容: +- 17-03-15:第三次作业讲解 +- 17-03-19:Edison分享的职业发展 + +## 第四周作业(3-13 至 3-19) +无,调整进度 + +## 完成情况: +休养生息 + +## 我的收获: +- 职业发展:从新人到老兵 diff --git a/group11/1178243325/week05/readme.md b/group11/1178243325/week05/readme.md new file mode 100644 index 0000000000..d4388e66d7 --- /dev/null +++ b/group11/1178243325/week05/readme.md @@ -0,0 +1,13 @@ +## 讲课内容: +- 17-03-22 :漫谈操作系统之虚拟内存 +- 17-03-26 :概要性介绍class文件结构和字节码的执行过程 + +## 第五周作业(3-20 至 3-26) +无,调整进度 + +## 完成情况: +修养生息 + +## 我的收获: +- 虚拟内存 +- 进一步理解JVM diff --git a/group11/1178243325/week06/build.gradle b/group11/1178243325/week06/build.gradle new file mode 100644 index 0000000000..128f6fda07 --- /dev/null +++ b/group11/1178243325/week06/build.gradle @@ -0,0 +1,13 @@ +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/week06/readme.md b/group11/1178243325/week06/readme.md new file mode 100644 index 0000000000..d89a5c904e --- /dev/null +++ b/group11/1178243325/week06/readme.md @@ -0,0 +1,16 @@ +## 讲课内容: +- 17-03-27:JVM第一周 +- 17-03-29:JVM之classLoader + +## 第六周作业(3-27 至 04-02) +- 完成对一个.class文件的读取和对.class文件开头四个字节的魔数的判断需要实现ClassLoader.java +- 实现LRU算法 +- 一篇文章 + +## 完成情况: +- ClassLoader.java已完 +- LRU已完 +- [文章](http://www.jianshu.com/p/02a8b4ee4596) + +## 我的收获: +使用开源工具读取文件,并利用工作类进行字符转换.LRU算法(双链表操作),但是更重要的抽象化思想. diff --git a/group11/1178243325/week06/src/main/java/com/sprint/basic/LRUPageFrame.java b/group11/1178243325/week06/src/main/java/com/sprint/basic/LRUPageFrame.java new file mode 100644 index 0000000000..0a2febd715 --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/basic/LRUPageFrame.java @@ -0,0 +1,117 @@ +package com.sprint.basic; + +public class LRUPageFrame { + + /** + * 用双向链表实现LRU算法 + */ + + 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; + } + + /** + * + */ + 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 Node find(int pageNum) { + Node node = first; + while (node != null) { + if (node.pageNum == pageNum) { + return node; + } + node = node.next; + } + return null; + } + + 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 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 void removeLast() { + Node prev = last.prev; + prev.next = null; + last.prev = null; + last = prev; + this.currentSize--; + } + + 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 boolean isEmpty() { + return (first == null) && (last == 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(); + } +} diff --git a/group11/1178243325/week06/src/main/java/com/sprint/jvm/clz/ClassFile.java b/group11/1178243325/week06/src/main/java/com/sprint/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..c40c88b183 --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/jvm/clz/ClassFile.java @@ -0,0 +1,9 @@ +package com.sprint.jvm.clz; + +public class ClassFile { + private final String cafebabe = "cafebabe"; + + public String getCafebabe() { + return cafebabe; + } +} diff --git a/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..445519b3be --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,17 @@ +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 String nextU4ToHexString() { + return Util.byteToHexString(new byte[] {codes[pos++], codes[pos++], codes[pos++], codes[pos++]}); + } + + +} diff --git a/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..1191be47eb --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java @@ -0,0 +1,49 @@ +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 { + List clzPaths = new ArrayList<>(); + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + public void addClassPath(String clzPath) { + if (this.clzPaths.contains(clzPath)) { + return; + } + this.clzPaths.add(clzPath); + } + + private 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) { + File f = new File(clzFileName); + try { + return IOUtils.toByteArray(new FileInputStream(f)); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileParser.java b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..229e7db360 --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/jvm/loader/ClassFileParser.java @@ -0,0 +1,14 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +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; + } + return clzFile; + } +} diff --git a/group11/1178243325/week06/src/main/java/com/sprint/jvm/util/Util.java b/group11/1178243325/week06/src/main/java/com/sprint/jvm/util/Util.java new file mode 100644 index 0000000000..6081635316 --- /dev/null +++ b/group11/1178243325/week06/src/main/java/com/sprint/jvm/util/Util.java @@ -0,0 +1,17 @@ +package com.sprint.jvm.util; + +public class Util { + 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/week06/src/test/java/com/sprint/basic/LRUPageFrameTest.java b/group11/1178243325/week06/src/test/java/com/sprint/basic/LRUPageFrameTest.java new file mode 100644 index 0000000000..ac28668dbe --- /dev/null +++ b/group11/1178243325/week06/src/test/java/com/sprint/basic/LRUPageFrameTest.java @@ -0,0 +1,33 @@ +package com.sprint.basic; +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/1178243325/week06/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java b/group11/1178243325/week06/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java new file mode 100644 index 0000000000..d3d84b414f --- /dev/null +++ b/group11/1178243325/week06/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java @@ -0,0 +1,23 @@ +package com.sprint.jvm.loader; + +import com.sprint.jvm.clz.ClassFile; +import org.junit.Test; +import org.junit.Assert; +public class ClassFileLoaderTest { + + private static final String FULL_QUALTFIED_CLASS_NAME = "com/sprint/jvm/EmployeeV1"; + + static String path1 = "/home/sprint/java/code/coding2017/group11/1178243325/week06/build/classes/test"; + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.sprint.jvm.loader.EmployeeV1"; + clzFile = loader.loadClass(className); + } + + @Test + public void test() { + Assert.assertEquals("cafebabe", clzFile.getCafebabe()); + } +} diff --git a/group11/1178243325/week06/src/test/java/com/sprint/jvm/loader/EmployeeV1.java b/group11/1178243325/week06/src/test/java/com/sprint/jvm/loader/EmployeeV1.java new file mode 100644 index 0000000000..6b8532842b --- /dev/null +++ b/group11/1178243325/week06/src/test/java/com/sprint/jvm/loader/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.loader; + +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", 20); + p.sayHello(); + } +} diff --git a/group11/1178243325/week07/.readme.md.swp b/group11/1178243325/week07/.readme.md.swp new file mode 100644 index 0000000000..3d7e4464a8 Binary files /dev/null and b/group11/1178243325/week07/.readme.md.swp differ diff --git a/group11/1178243325/week07/build.gradle b/group11/1178243325/week07/build.gradle new file mode 100644 index 0000000000..128f6fda07 --- /dev/null +++ b/group11/1178243325/week07/build.gradle @@ -0,0 +1,13 @@ +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/week07/readme.md b/group11/1178243325/week07/readme.md new file mode 100644 index 0000000000..cc9d7c6f3c --- /dev/null +++ b/group11/1178243325/week07/readme.md @@ -0,0 +1,12 @@ +## 讲课内容: +- 17-03-29 :JVM之classLoader + +## 第七周作业(04-03 至 04-09) +- 实现对一个.class文件的常量池读取 +- 实现StackUtil +- [文章](http://www.jianshu.com/p/502c1e5caa97) +## 完成情况: + + +## 我的收获: + diff --git a/group11/1178243325/week07/src/main/java/com/sprint/jvm/clz/AccessFlag.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..e74740aa3e --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/clz/ClassFile.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4e5aad16f9 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/clz/ClassIndex.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..46e7443d90 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/ClassInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..b8da3c656d --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/ConstantInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a8db82689e --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/ConstantPool.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..3a35c22ce0 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..c0eb449085 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..85bb5c4934 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..492fd6e0db --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..f257cea240 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/StringInfo.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..73c58a5e71 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/constant/UTF8Info.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5516999c0e --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..fc5d1b2ac2 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f190f54915 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/loader/ClassFileParser.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..4b77190a04 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/main/java/com/sprint/jvm/util/Util.java b/group11/1178243325/week07/src/main/java/com/sprint/jvm/util/Util.java new file mode 100644 index 0000000000..0f5dc89626 --- /dev/null +++ b/group11/1178243325/week07/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/week07/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java b/group11/1178243325/week07/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java new file mode 100644 index 0000000000..5cbc24577e --- /dev/null +++ b/group11/1178243325/week07/src/test/java/com/sprint/jvm/loader/ClassFileLoaderTest.java @@ -0,0 +1,181 @@ +package com.sprint.jvm.loader; + + +import com.sprint.jvm.clz.ClassFile; +import com.sprint.jvm.clz.ClassIndex; +import com.sprint.jvm.constant.*; +import org.junit.Test; +import org.junit.Assert; +public class ClassFileLoaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/sprint/jvm/loader/EmployeeV1"; + static String path1 = "/home/sprint/java/code/coding2017/group11/1178243325/week07/build/classes/test"; + static String path2 = "/home/sprint/xxx"; + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.sprint.jvm.loader.EmployeeV1"; + clzFile = loader.loadClass(className); + clzFile.print(); + } + + + @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.sprint.jvm.loader.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1050, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.sprint.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", 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.getClassIndex(); + 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/1178243325/week07/src/test/java/com/sprint/jvm/loader/EmployeeV1.java b/group11/1178243325/week07/src/test/java/com/sprint/jvm/loader/EmployeeV1.java new file mode 100644 index 0000000000..6b8532842b --- /dev/null +++ b/group11/1178243325/week07/src/test/java/com/sprint/jvm/loader/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.sprint.jvm.loader; + +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", 20); + p.sayHello(); + } +} diff --git a/group11/1310368322/RemoteSystemsTempFiles/.project b/group11/1310368322/RemoteSystemsTempFiles/.project new file mode 100644 index 0000000000..5447a64fa9 --- /dev/null +++ b/group11/1310368322/RemoteSystemsTempFiles/.project @@ -0,0 +1,12 @@ + + + RemoteSystemsTempFiles + + + + + + + org.eclipse.rse.ui.remoteSystemsTempNature + + diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/AttributeInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..58f2190146 --- /dev/null +++ b/group11/1310368322/src/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/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..e07662a68b --- /dev/null +++ b/group11/1310368322/src/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.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 LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + 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 t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + int attrNameIndex = iter.nextU2toInt(); + int attrLen = iter.nextU2toInt(); + int maxStack = iter.nextU2toInt(); + int max_Locals = iter.nextU2toInt(); + int codeLen = iter.nextU4toInt(); + // code + String code = iter.nextUxToHexString(codeLen); + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, max_Locals, max_Locals, code); + + int exceptionTableLen = iter.nextU2toInt(); + + if(exceptionTableLen > 0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encounted exception table, just ignore it"); + } + + int subAttributesCount = iter.nextU2toInt(); + + for(int i = 0; i < subAttributesCount; i++){ + int subAttrNameIndex = iter.nextU2toInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrNameIndex); + if(CodeAttr.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + int subAttrLen = iter.nextU4toInt();// localVariableTable Ե + LocalVariableTable locVarTable = LocalVariableTable.parse(iter, subAttrNameIndex, subAttrLen); + codeAttr.setLocalVariableTable(locVarTable); + }else if(CodeAttr.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + int subAttrLen = iter.nextU4toInt(); + LineNumberTable lineNumTable = LineNumberTable.parse(iter, subAttrNameIndex, subAttrLen); + codeAttr.setLineNumberTable(lineNumTable); + }else if(CodeAttr.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + int subAttrLen = iter.nextU4toInt(); + StackMapTable stackMapTable = StackMapTable.parse(iter); + codeAttr.setStackMapTable(stackMapTable); + }else{ + throw new RuntimeException("need code to process" + subAttrName); + } + } + + return codeAttr; + } +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LineNumberTable.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..24bcb25572 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,52 @@ +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();// кűкܶġкŶӦ + + // LineNumberTableһṹñ˿ + private static class LineNumberItem{ + int startPC;// ¼ֽк + int lineNum;// ¼JavaԴк + 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 subAttrNameIndex, int subAttrLen){ + LineNumberTable lineNumTable = new LineNumberTable(subAttrNameIndex, subAttrLen); + int lineNumTableLen = iter.nextU2toInt(); + for(int i = 0; i < lineNumTableLen; i ++){ + int startPC = iter.nextU2toInt(); + int lineNum = iter.nextU2toInt(); + LineNumberItem lineNumItem = new LineNumberItem(); + lineNumItem.setStartPC(startPC); + lineNumItem.setLineNum(lineNum); + lineNumTable.addLineNumberItem(lineNumItem); + } + return lineNumTable; + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableItem.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..842e1d0a96 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.attr; + +public class LocalVariableItem { + + private int startPC;// ֲڿʼʱֽƫ + private int length; // ֽij + private int nameIndex; // ֲ + private int descIndex; // ֲ + private int index; // ֲջ֡еľֲе slot λ + + 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/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableTable.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..757f28918b --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,41 @@ +package com.coderising.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.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, int subAttrName, int subAttrLen){ + + LocalVariableTable locVarTable = new LocalVariableTable(subAttrName, subAttrLen); + int localVarTableLen = iter.nextU2toInt(); + for(int i = 0; i < localVarTableLen; i++){ + int startPC = iter.nextU2toInt(); + int length = iter.nextU2toInt(); + int nameIndex = iter.nextU2toInt(); + int descIndex = iter.nextU2toInt(); + int index = iter.nextU2toInt(); + LocalVariableItem locVarItem = new LocalVariableItem(); + locVarItem.setStartPC(startPC); + locVarItem.setLength(length); + locVarItem.setNameIndex(nameIndex); + locVarItem.setDescIndex(descIndex); + locVarItem.setIndex(index); + locVarTable.addLocalVariableItem(locVarItem); + } + + return locVarTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/StackMapTable.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..9df44fb5ca --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +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/1310368322/src/Mini_JVM/com/coderising/jvm/clz/AccessFlag.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..4e26442ed5 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,26 @@ +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; + } + +} 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 new file mode 100644 index 0000000000..4492d2df9e --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/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.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 AccessFlag getAccessFlag(){ + return accessFlag; + } + + public ClassIndex getClzIndex(){ + return clzIndex; + } + + public void setClassIndex(ClassIndex clzIndex){ + this.clzIndex = clzIndex; + } + + public int getMinorVersion(){ + System.out.println(minorVersion); + 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 this.pool; + } + public void setConstantPool(ConstantPool pool){ + this.pool = pool; + } + + public void addField(Field f){ + this.fields.add(f); + } + public List getFields(){ + return this.fields; + } + public void addMethod(Method m){ + this.methods.add(m); + } + public List getMethods() { + return methods; + } + + public void print(){ + if(this.accessFlag.isPublicClass()){ + System.out.println("Access flag : public "); + } + System.out.println("ClassName: " + getClassName()); + System.out.println("SuperClassName: " + getSuperClassName()); + + } + + public void setAccessFlag(AccessFlag accessFlag){ + this.accessFlag = accessFlag; + } + + 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/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassIndex.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..8382ef03f9 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,23 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex; + private int superClassIndex; + + public int getThisClassIndex(){ + System.out.println(thisClassIndex); + 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/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..13fc4101a3 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,33 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo{ + + private int type = ConstantInfo.CLASS_INFO;// ʾóΪ ӿڵķ + private int utf8Index;// CONSTANT_Class_info ͳ ṹе name_index name_index ָһ CONSTANT_Utf8_info ͵ij + + 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/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..e20be200d6 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,34 @@ +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);// õ ConstantInfo ı constantPool е getConstantInfo + // ContantInfo е getConstantInfo ͬ + } + + +} 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 new file mode 100644 index 0000000000..82565b7f59 --- /dev/null +++ b/group11/1310368322/src/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){ + System.out.println("index: " + index); + return ((UTF8Info)this.constantInfos.get(index)).getValue(); + } + + public Object 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 new file mode 100644 index 0000000000..731c35b118 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,62 @@ +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(nameAndTypeIndex); + return typeInfo.getName(); + } + + public String getFieldType(){ + NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(nameAndTypeIndex); + return typeInfo.getTypeInfo(); + } +} + + + + + + + + + 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 new file mode 100644 index 0000000000..49d89083fd --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,52 @@ +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); + } + + @Override + 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 getClassName(){ + ConstantPool pool = this.getConstantPool(); + ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.classInfoIndex); + return clzInfo.getClassName(); + } + + public String getMethodName(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.nameAndTypeIndex); + return typeInfo.getName(); + } + + public String getParamAndReturnType(){ + ConstantPool pool = this.getConstantPool(); + NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.nameAndTypeIndex); + return typeInfo.getTypeInfo(); + } + +} 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 new file mode 100644 index 0000000000..8494e5e76a --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,52 @@ +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; + } + + @Override + public int getType(){ + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1);// õ ֶ Name + return utf8Info1.getValue(); // ֶ Nameֵ + } + + 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/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..f0be39e410 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/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/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..3ff8e9402b --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,30 @@ +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); + } + + + @Override + 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/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..6374764b5f --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,40 @@ +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; + } + + @Override + 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/1310368322/src/Mini_JVM/com/coderising/jvm/field/Field.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..9e110b1867 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/field/Field.java @@ -0,0 +1,43 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class Field { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private ConstantPool pool; + public int getNameIndex(){ + return nameIndex; + } + public int getDescIndex(){ + return descriptorIndex; + } + public String toString(){ + return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex); + } + 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 attrLen = iter.nextU2toInt(); + if(attrLen > 0){ + throw new RuntimeException("Field attributes has not been implemented"); + } + Field field = new Field(accessFlag,nameIndex,descriptorIndex,pool); + + return field; + } + + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..41516cd506 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,61 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + + byte[] codes; + int pos;// άλ + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + } + + public int nextU1toInt(){ + return (codes[pos++] & 0xFF); + } + + public int nextU2toInt(){ + byte [] a = new byte[]{ codes[pos++], codes[pos++]}; + return (a[0]<<8) + a[1]; + } + + public int nextU4toInt(){ + byte [] a = new byte[]{ codes[pos++], codes[pos++], codes[pos++], codes[pos++]}; + return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3]; + } + + public byte[] getByte(int length){ + byte []a = new byte[length]; + for(int i = 0; i < length; i++){ + a[i] = codes[pos++]; + } + return a; + } + public String nextU4ToHexString(){ + StringBuffer buffer = new StringBuffer(); + for(int i = 0; i < 4; i++){ + int a = codes[pos++] & 0xFF; + String strHex = Integer.toHexString(a); + if(strHex.length() < 2){ + strHex = "0" + strHex; + } + buffer.append(strHex); + } + return buffer.toString(); + } + + public String nextUxToHexString(int len) { + + StringBuffer buffer = new StringBuffer(); + for(int i = 0; i < len; i++){ + int a = codes[pos++] & 0xFF; + String strHex = Integer.toHexString(a); + if(strHex.length() < 2){ + strHex = "0" + strHex; + } + buffer.append(strHex); + } + + return buffer.toString(); + + } +} 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 new file mode 100644 index 0000000000..6e479bbce9 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,69 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.runners.Parameterized.Parameters; + +import com.coderising.jvm.clz.ClassFile; + +public class ClassFileLoader { + private List clzPaths = new ArrayList(); + int countForClassPath = 0; + int countForReadBinaryCode = 0; + byte [] a = new byte[10000]; + + /* ָ·ȡļ䱣浽һֽУ + * @Parameters ָ· + * @ֽ + */ + public byte[] readBinaryCode(String className) throws IOException{ + DataInputStream dis = new DataInputStream( + new BufferedInputStream(new FileInputStream(className))); + for(int i = 0; dis.available() != 0; i++){ + a[i] = dis.readByte(); + countForReadBinaryCode++; + } + byte []target = new byte[countForReadBinaryCode]; + System.arraycopy(a, 0, target, 0, countForReadBinaryCode); + dis.close(); + return target; + } + + public void addClassPath(String path){ + clzPaths.add(path); + countForClassPath++; + } + + public String getClassPath(){ + StringBuffer buffer = new StringBuffer(); + for(int i = 0; i < countForClassPath; i++ ){ + if(i==countForClassPath-1){ + buffer.append(clzPaths.get(i)); + }else{ + buffer.append(clzPaths.get(i)+";"); + } + } + return buffer.toString(); + } + + public ClassFile loadClass(String className) throws IOException{ + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + + + + + + + + + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileParser.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..43e3796ef5 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,169 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import javax.management.RuntimeErrorException; + +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; + +/* + * һֽ飬ɶа ClassFile + */ +public class ClassFileParser { + + // غ ClassFile + public ClassFile parse(byte[] codes){ + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicNumber = iter.nextU4ToHexString(); + if(!magicNumber.equals("cafebabe")){ + return null; + } + clzFile.setMinorVersion(iter.nextU2toInt()); + clzFile.setMajorVersion(iter.nextU2toInt()); + + // ȡ + ConstantPool pool = parseConstantPool(iter); + AccessFlag accessFlag = parseAccessFlag(iter); + ClassIndex clzIndex = parseClassIndex(iter); + clzFile.setAccessFlag(accessFlag); + clzFile.setClassIndex(clzIndex); + clzFile.setConstantPool(pool);// м볣 + + parseInterfaces(iter); + parseFields(clzFile,iter); + parseMethods(clzFile,iter); + + + return clzFile; + } + + + + + private AccessFlag parseAccessFlag(ByteCodeIterator iter){ + int accessFlagValue = iter.nextU2toInt(); + AccessFlag accessFlag = new AccessFlag(accessFlagValue); + accessFlag.setFlagValue(accessFlagValue); + 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){ + + int constantPoolCount = iter.nextU2toInt(); + System.out.println("ConstantPool Count : " + constantPoolCount); + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + + // ӳϢ + for(int i = 1; i <= constantPoolCount-1; i++){// JVM 涨Ҫ ȥ 1ȥ 1ij + + int tag = iter.nextU1toInt(); + if(tag == 7){ + // ӿڵķ ClassInfo + int utf8Index = iter.nextU2toInt(); + ClassInfo clzInfo= new ClassInfo(pool);// һ ClassInfo + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + }else if(tag == 1){ + // UTF-8 ַ + int length = iter.nextU2toInt(); + byte data[] = iter.getByte(length); + String value = null; + try { + value = new String(data,"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setLength(length); + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + }else if(tag == 12){ + // NameAndTypeInfo ֶλ򷽷IJַ + int NameIndex = iter.nextU2toInt(); + int TypeIndex = iter.nextU2toInt(); + NameAndTypeInfo nameAndType = new NameAndTypeInfo(pool); + nameAndType.setIndex1(NameIndex); + nameAndType.setIndex2(TypeIndex); + pool.addConstantInfo(nameAndType); + }else if(tag == 9){ + // FieldRefInfo ֶεķ + int classInfoIndex = iter.nextU2toInt(); + int nameAndTypeIndex = iter.nextU2toInt(); + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(classInfoIndex); + fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + pool.addConstantInfo(fieldRefInfo); + }else if(tag == 10){ + // MethodRefInfo зķ + int classInfoIndex = iter.nextU2toInt(); + int nameAndTypeIndex = iter.nextU2toInt(); + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(classInfoIndex); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + pool.addConstantInfo(methodRefInfo); + }else if(tag == 8){ + int stringIndex = iter.nextU2toInt();// ַָ + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(stringIndex); + pool.addConstantInfo(stringInfo); + }else{ + throw new RuntimeException("the constant pool tag" + tag + "has not been implemented yet"); + } + + } + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfacesCount = iter.nextU2toInt(); + System.out.println("interfacesCount: " + interfacesCount); + if(interfacesCount > 0){ + throw new RuntimeException("interfaces has not been implemented"); + } + + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + int fieldsCount = iter.nextU2toInt(); + System.out.println("fieldsCount: " + fieldsCount); + for(int i = 0; i < fieldsCount; i++){ + Field f = Field.parse(clzFile.getConstantPool(), iter); + clzFile.addField(f); + } + + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + int methodsCount = iter.nextU2toInt(); + System.out.println("methodsCount: " + methodsCount); + for(int i = 0; i < methodsCount; i++){ + Method m = Method.parse(clzFile, iter); + clzFile.addMethod(m); + } + + } + +} diff --git a/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/TestJVM.java b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/TestJVM.java new file mode 100644 index 0000000000..735e4d1dc2 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/loader/TestJVM.java @@ -0,0 +1,7 @@ +package com.coderising.jvm.loader; + +public class TestJVM { + public static void main(String[] args) { + System.out.println("Hello"); + } +} 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 new file mode 100644 index 0000000000..572880f729 --- /dev/null +++ b/group11/1310368322/src/Mini_JVM/com/coderising/jvm/method/Method.java @@ -0,0 +1,68 @@ +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.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile 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 ClassFile getClzFile() { + return clzFile; + } + + 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){ + int accessFlag = iter.nextU2toInt(); + int nameIndex = iter.nextU2toInt(); + int descriptor = iter.nextU2toInt(); + int attrCount = iter.nextU2toInt(); + + + Method method = new Method(clzFile,accessFlag,nameIndex,descriptor); + System.out.println("attrCount: " + attrCount); + // methodе + for(int i = 0; i < attrCount; i++){ + int attrNameIndex = iter.nextU2toInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + System.out.println(attrName); + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + CodeAttr attrCode = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(attrCode); + } + + } + return method; + } +} diff --git a/group11/1310368322/src/Download/DownloadThread.java b/group11/1310368322/src/data_structure/BigHomework/Download/DownloadThread.java similarity index 100% rename from group11/1310368322/src/Download/DownloadThread.java rename to group11/1310368322/src/data_structure/BigHomework/Download/DownloadThread.java diff --git a/group11/1310368322/src/Download/FileDownloader.java b/group11/1310368322/src/data_structure/BigHomework/Download/FileDownloader.java similarity index 100% rename from group11/1310368322/src/Download/FileDownloader.java rename to group11/1310368322/src/data_structure/BigHomework/Download/FileDownloader.java diff --git a/group11/1310368322/src/Download/api/Connection.java b/group11/1310368322/src/data_structure/BigHomework/Download/api/Connection.java similarity index 100% rename from group11/1310368322/src/Download/api/Connection.java rename to group11/1310368322/src/data_structure/BigHomework/Download/api/Connection.java diff --git a/group11/1310368322/src/Download/api/ConnectionException.java b/group11/1310368322/src/data_structure/BigHomework/Download/api/ConnectionException.java similarity index 100% rename from group11/1310368322/src/Download/api/ConnectionException.java rename to group11/1310368322/src/data_structure/BigHomework/Download/api/ConnectionException.java diff --git a/group11/1310368322/src/Download/api/ConnectionManager.java b/group11/1310368322/src/data_structure/BigHomework/Download/api/ConnectionManager.java similarity index 100% rename from group11/1310368322/src/Download/api/ConnectionManager.java rename to group11/1310368322/src/data_structure/BigHomework/Download/api/ConnectionManager.java diff --git a/group05/284422826/src/com/coderising/download/api/DownloadListener.java b/group11/1310368322/src/data_structure/BigHomework/Download/api/DownloadListener.java similarity index 100% rename from group05/284422826/src/com/coderising/download/api/DownloadListener.java rename to group11/1310368322/src/data_structure/BigHomework/Download/api/DownloadListener.java diff --git a/group11/1310368322/src/Download/impl/ConnectionImpl.java b/group11/1310368322/src/data_structure/BigHomework/Download/impl/ConnectionImpl.java similarity index 100% rename from group11/1310368322/src/Download/impl/ConnectionImpl.java rename to group11/1310368322/src/data_structure/BigHomework/Download/impl/ConnectionImpl.java diff --git a/group11/1310368322/src/Download/impl/ConnectionManagerImpl.java b/group11/1310368322/src/data_structure/BigHomework/Download/impl/ConnectionManagerImpl.java similarity index 100% rename from group11/1310368322/src/Download/impl/ConnectionManagerImpl.java rename to group11/1310368322/src/data_structure/BigHomework/Download/impl/ConnectionManagerImpl.java diff --git a/group11/1310368322/src/ArrayList.java b/group11/1310368322/src/data_structure/baseDataStructure_1/ArrayList.java similarity index 100% rename from group11/1310368322/src/ArrayList.java rename to group11/1310368322/src/data_structure/baseDataStructure_1/ArrayList.java diff --git a/group11/1310368322/src/LinkedList.java b/group11/1310368322/src/data_structure/baseDataStructure_1/LinkedList.java similarity index 100% rename from group11/1310368322/src/LinkedList.java rename to group11/1310368322/src/data_structure/baseDataStructure_1/LinkedList.java diff --git a/group11/1310368322/src/ArrayUtil.java b/group11/1310368322/src/data_structure/baseDataStructure_2/ArrayUtil.java similarity index 100% rename from group11/1310368322/src/ArrayUtil.java rename to group11/1310368322/src/data_structure/baseDataStructure_2/ArrayUtil.java diff --git a/group11/1310368322/src/data_structure/baseDataStructure_3/LinkedList.java b/group11/1310368322/src/data_structure/baseDataStructure_3/LinkedList.java new file mode 100644 index 0000000000..5ea6a988be --- /dev/null +++ b/group11/1310368322/src/data_structure/baseDataStructure_3/LinkedList.java @@ -0,0 +1,162 @@ +package DataStructure_3; + +import java.util.Stack; + +import DataStructure_1.LinkedList.Node; + +public class LinkedList { + private Node head; + static int size = 0; + public void add(Object o){ + if(null == head){ + head = new Node(); + head.data = o; + head.next = null; + }else{ + Node p = head; + while(null != p.next){ + p = p.next; + } + Node newNode = new Node(); + newNode.data = o; + p.next = newNode; + newNode.next =null; + } + size++; + } + public int size(){ + return size; + } + public void add(int index,Object o){ + if(index < 0){ + throw new RuntimeException("±겻Ϊ"); + } + if(index == 0){ + addFirst(o); + size++; + return; + } + if(index > size){ + throw new RuntimeException(""); + } + int i = 0; + Node p = head; + Node q = null; + + while(i!=index){ + q = p; + p = p.next; + i++; + } + Node r = new Node(); + r.data = o; + r.next =null; + q.next = r; + r.next = p; + size++; + return; + } + + public Object get(int index){ + int i = 0; + Node p = head; + while(i != index){ + p = p.next; + i++; + } + return p.data; + } + public Object remove(int index){ + if(index < 0){ + throw new RuntimeException("±겻Ϊ"); + } + if(index == 1){ + size--; + return head.data; + } + int i = 0; + Node p = head; + Node q = null; + while(i != index){ + q = p; + p = p.next; + i++; + } + q.next = p.next; + size--; + return p.data; + } + public void addFirst(Object o){ + Node p = new Node(); + p.next = head; + p.data = o; + head = p; + size++; + } + public Object removeFirst(){ + head = head.next; + size--; + return null; + } + public static class Node{ + Object data; + Node next; + } + + /** + * Ѹ + * 3->7->10 úΪ 10->7->3 + */ + public void reverse(){ + if(null == head || null == head.next){ + return; + } + Stack s = new Stack(); + Node curNode = head; + while(curNode != null){ + s.push(curNode); + Node nextNode = curNode.next; + curNode.next = null; // Ͽ + curNode = nextNode; + } + + head = s.pop(); + curNode = head; + while(!s.isEmpty()){ + Node nextNode = s.pop(); + curNode.next = nextNode; + curNode = nextNode; + } + + } + + public String toString(){ + StringBuffer buffer = new StringBuffer(); + buffer.append("["); + Node node = head; + while(node != null){ + buffer.append(node.data); + if(node.next != null){ + buffer.append(","); + } + node = node.next; + } + buffer.append("]"); + return buffer.toString(); + } + + + + + + + + + + + + + + + +} diff --git a/group11/1310368322/src/data_structure/baseDataStructure_4_LRU/LRUPageFrame.java b/group11/1310368322/src/data_structure/baseDataStructure_4_LRU/LRUPageFrame.java new file mode 100644 index 0000000000..5e860a31d7 --- /dev/null +++ b/group11/1310368322/src/data_structure/baseDataStructure_4_LRU/LRUPageFrame.java @@ -0,0 +1,143 @@ +package DataStructure_4_LRU; + +import org.junit.runners.Parameterized.Parameters; + +/* + * ˫ʵ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/1310368322/src/data_structure/baseDataStructure_5_Stack/StackUtil.java b/group11/1310368322/src/data_structure/baseDataStructure_5_Stack/StackUtil.java new file mode 100644 index 0000000000..782c7d59a6 --- /dev/null +++ b/group11/1310368322/src/data_structure/baseDataStructure_5_Stack/StackUtil.java @@ -0,0 +1,106 @@ +package DataStructure_5_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; } + int length = s.size(); + Object []temp = new Object[length]; + for(int i = 0; i < length; i++){ + temp[i] = s.pop(); + } + for(int i = 0; i < length; i++){ + s.push(temp[i]); + } + return; + } + + /* + * ɾջָԪأע⣺ֻʹStackĻpush,pop,peek,isEmpty + * + */ + public static void remove(Stack s, Object o){ + int length = s.size(); + Object elementTemp; + System.out.println(length); + int count = 0; + Object []temp = new Object[length]; + if(s.isEmpty()){ return; } + for(int i = 0; i < length;i++){ + elementTemp = s.pop(); + if(!o.equals(elementTemp)){ + temp[count++] = elementTemp; + System.out.println(temp[i]); + } + } + + for(int i = count-1; i >= 0; i--){ + s.push(temp[i]); + } + return; + } + + /* + * ջȡlenԪأԭջеԪرֲ + * @param len + * @return + */ + public static Object[] getTop(Stack s , int len){ + if(s.isEmpty() || len > s.size() || len < 0){ + return null; + } + Object []result = new Object[len]; + for(int i = 0; i < len; i++){ + result[i] = s.pop(); + } + return result; + } + + /* + * ַ s ܰЩַ () [] {}, a, b, c ... x, y, z + * ʹöջַ s еDzdzɶԳֵ + * 磺 s = ([e{d}f]),ַеdzɶԳֵģ÷ true + * s = "([b{x]})",ַеŲdzɶԳֵģ÷ false + * @param s + * @return + */ + public static boolean isValidPairs(String s){ + Stack stack = new Stack(); + System.out.println(stack.isEmpty()); + char elementTemp; + boolean tag = false; + char [] a = s.toCharArray(); + for(int i = 0; i < a.length; i++){ + if((!tag) && (a[i] == '(' || a[i] == ')' || a[i] == '[' || a[i] == ']' || a[i] == '{' || a[i] == '}')){ + stack.push(a[i]); + tag = true; + }else{ + if(a[i] == '(' || a[i] == ')' || a[i] == '[' || a[i] == ']' || a[i] == '{' || a[i] == '}'){ + elementTemp = (char) stack.pop(); + switch(elementTemp){ + case '(': if(a[i]==')'){}else{ stack.push(elementTemp); stack.push(a[i]); }; break; + case '[': if(a[i]==']'){}else{ stack.push(elementTemp); stack.push(a[i]); }; break; + case '{': if(a[i]=='}'){}else{ stack.push(elementTemp); stack.push(a[i]); }; break; + + } + } + } + + } + if(stack.isEmpty()){ + return true; + } + return false; + } +} + + + + + + diff --git a/group11/1310368322/src/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java b/group11/1310368322/src/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java new file mode 100644 index 0000000000..c7285dd9a2 --- /dev/null +++ b/group11/1310368322/src/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java @@ -0,0 +1,106 @@ +package dataStructure_6InfixExpr; + +import java.util.Stack; + +public class InfixExpr { + + String expr = null; + + public InfixExpr(String expr){ + this.expr = expr; + } + + public double evaluate(){ + + Stack operatorStack = new Stack(); + Stack operandStack = new Stack(); + + int tag = -1; + for(int i = 0; i < expr.length(); i++){ + if(operatorStack.isEmpty()){ + tag = -1; + } + char c = expr.charAt(i); + if( tag == 1 && (c == '+' || c == '-' || c == '*' || c == '/')){ + System.out.println("i= " + i); + char down = (char) operatorStack.pop(); + System.out.println("down: " + down); + System.out.println("up: " + c); + if(judgePriority(down,c)){ + double operand = (double) operandStack.pop(); + double operanded = (double) operandStack.pop(); + operandStack.push(operator(down,operanded,operand)); + operatorStack.push(c); + }else{ + operatorStack.push(down); + operatorStack.push(c); + } + }else if(tag == -1 && (c == '+' || c == '-' || c == '*' || c == '/')){ + tag = 1; + operatorStack.push(c); + + }else{ + String number = extractNumber(i,expr); + int length = number.length(); + i += length-1; + double operand = Double.parseDouble(number); + operandStack.push(operand); + } + } + + while(!operatorStack.isEmpty()){ + char operator = (char) operatorStack.pop(); + System.out.println(operator); + double operand = (double) operandStack.pop(); + System.out.println(operand); + double operanded = (double) operandStack.pop(); + System.out.println(operanded); + operandStack.push( operator(operator,operanded,operand)); + } + + return (double) operandStack.pop(); + } + + private String extractNumber(int i, String expr2) { + + StringBuffer buffer = new StringBuffer(); + while( (expr.charAt(i) != '+') && (expr.charAt(i) != '-') && (expr.charAt(i) != '*') && (expr.charAt(i) != '/') ){ + buffer.append(expr.charAt(i)); + if(i >= expr2.length()-1){ + break; + } + i++; + } + return buffer.toString(); + } + + private boolean judgePriority(char down, char up) { + boolean tag = false; + + if((up == '+' || up == '-') && (down == '*' || down == '/')){ + tag = true; + }else if( (up == '*') && (down == '/')){ + tag = true; + }else if( (up == '/') && (down == '*')){ + tag = true; + }else if( (up == '+') && (down == '-') ){ + tag = true; + }else if( (up == '-') && (down == '+') ){ + tag = true; + } + return tag; + } + + private double operator(char operator, double operanded, double operand) { + double result = 0; + + switch(operator){ + case '+': result = operanded + operand; break; + case '-': result = operanded - operand; break; + case '*': System.out.println("˷"); result = operanded * operand; break; + case '/': result = operanded / operand; break; + } + + return result; + } +} diff --git a/group11/1310368322/test/Mini_JVM/EmployeeV1.java b/group11/1310368322/test/Mini_JVM/EmployeeV1.java new file mode 100644 index 0000000000..acbc34c9bb --- /dev/null +++ b/group11/1310368322/test/Mini_JVM/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.loader; + +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(); + } +} diff --git a/group11/1310368322/test/Mini_JVM/TestClassFileLoader.java b/group11/1310368322/test/Mini_JVM/TestClassFileLoader.java new file mode 100644 index 0000000000..d1874a0834 --- /dev/null +++ b/group11/1310368322/test/Mini_JVM/TestClassFileLoader.java @@ -0,0 +1,246 @@ +package com.coderising.jvm.loader; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.List; + +import org.junit.*; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.*; +import com.coderising.jvm.field.Field; +import com.coderising.jvm.method.Method; + +public class TestClassFileLoader { + static String path1 = "D:/ProgramWorld"; + static String path2 = "D:/ProgramWorld/Java"; + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/loader/EmployeeV1"; + static String classPath1 = "D:/ProgramWorld/Java/Practice/LangSi/2017Ⱥ/bin/com/coderising/jvm/loader/EmployeeV1.class"; + static String classPath2 = "D:/TestClass.class"; + static ClassFile clzFile = null; + + + @Test + public void test() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + String clzPath = loader.getClassPath(); + Assert.assertEquals(path1 + ";" + path2, clzPath); + } + @Test + public void testClassFileLength() throws IOException{ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "D:/ProgramWorld/Java/Practice/LangSi/2017Ⱥ/bin/com/coderising/jvm/loader/EmployeeV1.class"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // ע⣺ ֽܺJVM汾йϵԿõൽж + Assert.assertEquals(1058,byteCodes.length); + } + @Test + public void testMagicNumber() throws IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "D:/ProgramWorld/Java/Practice/LangSi/2017Ⱥ/bin/com/coderising/jvm/loader/EmployeeV1.class"; + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{ + byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3] + }; + System.out.println("ddd"); + 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() throws IOException{ + ClassFileLoader loader = new ClassFileLoader(); + clzFile = loader.loadClass(classPath2); + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(51, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool() throws IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + clzFile = loader.loadClass(classPath1); + 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() throws IOException{ + + ClassFileLoader loader = new ClassFileLoader(); + clzFile = loader.loadClass(classPath1); + ClassIndex clzIndex = clzFile.getClzIndex(); + System.out.println("clzIndex="+clzIndex); + ClassInfo thisClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo)clzFile.getConstantPool().getConstantInfo(clzIndex.getSuperClassIndex()); + System.out.println(thisClassInfo.getClassName()); + System.out.println(superClassInfo.getClassName()); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + + // --------------------- JVM + @Test + public void testReadFields() throws IOException{ + ClassFileLoader loader = new ClassFileLoader(); + clzFile = loader.loadClass(classPath1); + 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() throws IOException{ + ClassFileLoader loader = new ClassFileLoader(); + clzFile = loader.loadClass(classPath1); + 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); + } + + +} diff --git a/group11/1310368322/test/FileDownloaderTest.java b/group11/1310368322/test/data_structure/BigHomework/Download/FileDownloaderTest.java similarity index 100% rename from group11/1310368322/test/FileDownloaderTest.java rename to group11/1310368322/test/data_structure/BigHomework/Download/FileDownloaderTest.java diff --git a/group11/1310368322/test/ArrayUtilTest.java b/group11/1310368322/test/data_structure/baseDataStructure_2/ArrayUtilTest.java similarity index 100% rename from group11/1310368322/test/ArrayUtilTest.java rename to group11/1310368322/test/data_structure/baseDataStructure_2/ArrayUtilTest.java diff --git a/group11/1310368322/test/data_structure/baseDataStructure_3/TestLinkedList.java b/group11/1310368322/test/data_structure/baseDataStructure_3/TestLinkedList.java new file mode 100644 index 0000000000..343f9d6f39 --- /dev/null +++ b/group11/1310368322/test/data_structure/baseDataStructure_3/TestLinkedList.java @@ -0,0 +1,25 @@ +package DataStructure_3; + +import static org.junit.Assert.*; +import org.junit.Assert; +import org.junit.Test; + +public class TestLinkedList { + + @Test + public void test() { + 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()); + } + +} diff --git a/group11/1310368322/test/data_structure/baseDataStructure_4_LRU/TestLRUPageFrame.java b/group11/1310368322/test/data_structure/baseDataStructure_4_LRU/TestLRUPageFrame.java new file mode 100644 index 0000000000..227599c187 --- /dev/null +++ b/group11/1310368322/test/data_structure/baseDataStructure_4_LRU/TestLRUPageFrame.java @@ -0,0 +1,31 @@ +package DataStructure_4_LRU; + +import static org.junit.Assert.*; +import org.junit.*; + +import org.junit.Test; + +public class TestLRUPageFrame { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3);// ҳ洢Ϊ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/group11/1310368322/test/data_structure/baseDataStructure_5_Stack/TestStackUtil.java b/group11/1310368322/test/data_structure/baseDataStructure_5_Stack/TestStackUtil.java new file mode 100644 index 0000000000..0b227e9ff6 --- /dev/null +++ b/group11/1310368322/test/data_structure/baseDataStructure_5_Stack/TestStackUtil.java @@ -0,0 +1,77 @@ +package DataStructure_5_Stack; + +import java.util.Stack; + +import org.junit.Assert; + +import org.junit.Test; + +public class TestStackUtil { + + @Test + public void test_reverse_1() { + Stack s = new Stack(); + for(int i = 0; i < 5; i++){ + s.push(i+1); + } + System.out.println(s.toString()); + StackUtil.reverse(s); + System.out.println(s.toString()); + } + + @Test + public void test_reverse_2() { + Stack s = new Stack(); + System.out.println(s.isEmpty()); + System.out.println(s.toString()); + StackUtil.reverse(s); + System.out.println(s.toString()); + } + + @Test + public void testRemove_1(){ + Stack actual = new Stack(); + Stack expected = new Stack(); + for(int i = 0; i < 5; i++){ + actual.push(i+1); + if(i != 2){ expected.push(i+1); } + } + StackUtil.remove(actual, 3); + Assert.assertEquals(expected, actual); + } + @Test + public void testRemove_2(){ + Stack actual = new Stack(); + Stack expected = new Stack(); + StackUtil.remove(actual, 3); + Assert.assertEquals(expected, actual); + } + + @Test + public void testGetTop(){ + Stack s = new Stack(); + for(int i = 0; i < 5; i++){ + s.push(i+1); + } + Object expected[] = {5,4,3}; + Object[] actual = StackUtil.getTop(s, 3); + Assert.assertArrayEquals(expected, actual); + + } + + + @Test + public void testIsValidPairs_1(){ + boolean actual = StackUtil.isValidPairs("([e{d}f])"); + boolean expected = true; + Assert.assertEquals(expected, actual); + } + + @Test + public void testValidPairs_2(){ + boolean actual = StackUtil.isValidPairs("([b{x]})"); + boolean expected = false; + Assert.assertEquals(expected, actual); + } + +} diff --git a/group11/1310368322/test/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java b/group11/1310368322/test/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java new file mode 100644 index 0000000000..c7285dd9a2 --- /dev/null +++ b/group11/1310368322/test/data_structure/baseDataStructure_6InfixExpr/InfixExpr.java @@ -0,0 +1,106 @@ +package dataStructure_6InfixExpr; + +import java.util.Stack; + +public class InfixExpr { + + String expr = null; + + public InfixExpr(String expr){ + this.expr = expr; + } + + public double evaluate(){ + + Stack operatorStack = new Stack(); + Stack operandStack = new Stack(); + + int tag = -1; + for(int i = 0; i < expr.length(); i++){ + if(operatorStack.isEmpty()){ + tag = -1; + } + char c = expr.charAt(i); + if( tag == 1 && (c == '+' || c == '-' || c == '*' || c == '/')){ + System.out.println("i= " + i); + char down = (char) operatorStack.pop(); + System.out.println("down: " + down); + System.out.println("up: " + c); + if(judgePriority(down,c)){ + double operand = (double) operandStack.pop(); + double operanded = (double) operandStack.pop(); + operandStack.push(operator(down,operanded,operand)); + operatorStack.push(c); + }else{ + operatorStack.push(down); + operatorStack.push(c); + } + }else if(tag == -1 && (c == '+' || c == '-' || c == '*' || c == '/')){ + tag = 1; + operatorStack.push(c); + + }else{ + String number = extractNumber(i,expr); + int length = number.length(); + i += length-1; + double operand = Double.parseDouble(number); + operandStack.push(operand); + } + } + + while(!operatorStack.isEmpty()){ + char operator = (char) operatorStack.pop(); + System.out.println(operator); + double operand = (double) operandStack.pop(); + System.out.println(operand); + double operanded = (double) operandStack.pop(); + System.out.println(operanded); + operandStack.push( operator(operator,operanded,operand)); + } + + return (double) operandStack.pop(); + } + + private String extractNumber(int i, String expr2) { + + StringBuffer buffer = new StringBuffer(); + while( (expr.charAt(i) != '+') && (expr.charAt(i) != '-') && (expr.charAt(i) != '*') && (expr.charAt(i) != '/') ){ + buffer.append(expr.charAt(i)); + if(i >= expr2.length()-1){ + break; + } + i++; + } + return buffer.toString(); + } + + private boolean judgePriority(char down, char up) { + boolean tag = false; + + if((up == '+' || up == '-') && (down == '*' || down == '/')){ + tag = true; + }else if( (up == '*') && (down == '/')){ + tag = true; + }else if( (up == '/') && (down == '*')){ + tag = true; + }else if( (up == '+') && (down == '-') ){ + tag = true; + }else if( (up == '-') && (down == '+') ){ + tag = true; + } + return tag; + } + + private double operator(char operator, double operanded, double operand) { + double result = 0; + + switch(operator){ + case '+': result = operanded + operand; break; + case '-': result = operanded - operand; break; + case '*': System.out.println("˷"); result = operanded * operand; break; + case '/': result = operanded / operand; break; + } + + return result; + } +} diff --git a/group11/252308879/README.md b/group11/252308879/README.md new file mode 100644 index 0000000000..99f5dc58e0 --- /dev/null +++ b/group11/252308879/README.md @@ -0,0 +1,29 @@ +Coding2017 项目 +=== + +## 简介 + +* 考虑到目前的项目目录比较凌乱,所以整理一下目录。目前还未整理完成。 + +* 该项目主要是个人的日常作业,包含三大部分(后续会更多): + * 前三周的打基础(计算机系统知识) + * 数据结构 + * mini-jvm + +--- + +## 目录 + +[TOC] + +--- + +## 正文 + +* data-structure 项目中主要包含前三周的作业 + * 基本的数据结构 + * 解析struts.xml + * 多线程下载 +* mini-jvm 项目中主要包含解析jvm的作业 + +* 在目前这两个大模块中,都包含了每周的数据结构练习 diff --git a/group11/252308879/data-structure/pom.xml b/group11/252308879/data-structure/pom.xml new file mode 100644 index 0000000000..42eb53c993 --- /dev/null +++ b/group11/252308879/data-structure/pom.xml @@ -0,0 +1,68 @@ + + 4.0.0 + + + com.pan + 252308879 + 1.0.0-SNAPSHOT + + + data-structure + 1.0.0-SNAPSHOT + jar + + data-structure + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + + + dom4j + dom4j + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + + + org.apache.maven.plugins + maven-source-plugin + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.codehaus.mojo + findbugs-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + diff --git a/group11/252308879/data-structure/src/main/java/com/pan/basic/BinaryTreeNode.java b/group11/252308879/data-structure/src/main/java/com/pan/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..aab398a9b6 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/basic/BinaryTreeNode.java @@ -0,0 +1,32 @@ +package com.pan.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/group11/252308879/data-structure/src/main/java/com/pan/basic/Iterator.java b/group11/252308879/data-structure/src/main/java/com/pan/basic/Iterator.java new file mode 100644 index 0000000000..70735fa34e --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/basic/Iterator.java @@ -0,0 +1,7 @@ +package com.pan.basic; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group11/252308879/data-structure/src/main/java/com/pan/basic/List.java b/group11/252308879/data-structure/src/main/java/com/pan/basic/List.java new file mode 100644 index 0000000000..8ac9cf8e2e --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/basic/List.java @@ -0,0 +1,9 @@ +package com.pan.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/group11/252308879/data-structure/src/main/java/com/pan/basic/Queue.java b/group11/252308879/data-structure/src/main/java/com/pan/basic/Queue.java new file mode 100644 index 0000000000..874d8a5690 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/basic/Queue.java @@ -0,0 +1,19 @@ +package com.pan.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/group11/252308879/data-structure/src/main/java/com/pan/linklist/LRUPageFrame.java b/group11/252308879/data-structure/src/main/java/com/pan/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..5208e5bc76 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/linklist/LRUPageFrame.java @@ -0,0 +1,133 @@ +package com.pan.linklist; + + +/* + * 用双向链表实现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/data-structure/src/main/java/com/pan/stack/StackUtil.java b/group11/252308879/data-structure/src/main/java/com/pan/stack/StackUtil.java new file mode 100644 index 0000000000..74918b1e37 --- /dev/null +++ b/group11/252308879/data-structure/src/main/java/com/pan/stack/StackUtil.java @@ -0,0 +1,141 @@ +package com.pan.stack; + + +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 + 4.0.0 + + + com.pan + 252308879 + 1.0.0-SNAPSHOT + + + mini-jvm + 1.0.0-SNAPSHOT + jar + + mini-jvm + http://maven.apache.org + + + UTF-8 + + + + + com.pan + data-structure + 1.0.0-SNAPSHOT + + + + junit + junit + + + org.apache.commons + commons-lang3 + + + commons-io + commons-io + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + + + org.apache.maven.plugins + maven-source-plugin + + + + org.apache.maven.plugins + maven-jar-plugin + + + + org.codehaus.mojo + findbugs-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + 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 new file mode 100644 index 0000000000..d9455d3807 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/alg/LRUPageFrame.java @@ -0,0 +1,133 @@ +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 new file mode 100644 index 0000000000..01a7f2da52 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/alg/StackUtil.java @@ -0,0 +1,141 @@ +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 clzPaths = new ArrayList(); + int countForClassPath = 0; + int countForReadBinaryCode = 0; + byte [] a = new byte[10000]; + + /* 从指定路径读取二进制文件流,并将其保存到一个字节数组中,并返回 + * @Parameters 指定路径 + * @字节数组 + */ + public byte[] readBinaryCode(String className) throws IOException{ + DataInputStream dis = new DataInputStream( + new BufferedInputStream(new FileInputStream(className))); + for(int i = 0; dis.available() != 0; i++){ + a[i] = dis.readByte(); + countForReadBinaryCode++; + } + byte []target = new byte[countForReadBinaryCode]; + System.arraycopy(a, 0, target, 0, countForReadBinaryCode); + dis.close(); + return target; + } + + public void addClassPath(String path){ + clzPaths.add(path); + countForClassPath++; + } + + public String getClassPath(){ + StringBuffer buffer = new StringBuffer(); + for(int i = 0; i < countForClassPath; i++ ){ + if(i==countForClassPath-1){ + buffer.append(clzPaths.get(i)); + }else{ + buffer.append(clzPaths.get(i)+";"); + } + } + return buffer.toString(); + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/EmployeeV1.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/EmployeeV1.java new file mode 100644 index 0000000000..71f9ff54a4 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/EmployeeV1.java @@ -0,0 +1,30 @@ +package com.pan.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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/AttributeInfo.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..1a81e8b473 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.pan.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/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/CodeAttr.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..80a05a9ac0 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/CodeAttr.java @@ -0,0 +1,94 @@ +package com.pan.jvm.attr; + +import com.pan.jvm.clz.ClassFile; +import com.pan.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-code: "+code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionTableLen = iter.nextU2ToInt(); + + if (exceptionTableLen > 0){ + String exTable = iter.nextUxToHexString(exceptionTableLen); + System.out.println("Encountered exception table, just ignore!"); + } + + // 处理子属性 + int subAttrCount = iter.nextU2ToInt(); + for (int i = 1; i <= subAttrCount; i++) { + int suAttrIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(suAttrIndex); + + iter.back(2);// 便于在子属性中获取 attrNameIndex + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)){ + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lineNumberTable); + }else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)){ + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(localVariableTable); + }else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)){ + StackMapTable stackMapTable = StackMapTable.parse(iter); + codeAttr.setStackMapTable(stackMapTable); + }else { + throw new RuntimeException("Need code to process :" + subAttrName); + } + + } + return codeAttr; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LineNumberTable.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..563e8b19d5 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LineNumberTable.java @@ -0,0 +1,53 @@ +package com.pan.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.pan.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 lineNumberTable = new LineNumberTable(attrNameIndex, attrLen); + + int attrItemSize = iter.nextU2ToInt(); + for (int i = 1; i <= attrItemSize; i++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.nextU2ToInt()); + lineNumberItem.setLineNum(iter.nextU2ToInt()); + + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; + } + + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableItem.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..7e202a3931 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.pan.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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableTable.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..74c73baac6 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/LocalVariableTable.java @@ -0,0 +1,42 @@ +package com.pan.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.pan.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){ + + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + + LocalVariableTable localVariableTable = new LocalVariableTable(attrNameIndex, attrLen); + + int attrItemSize = iter.nextU2ToInt(); + for (int i = 1; i <= attrItemSize; 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; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/StackMapTable.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..8d7c32b4bd --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.pan.jvm.attr; + + +import com.pan.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/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/AccessFlag.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..045741bd1e --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.pan.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/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassFile.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..e632888d89 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassFile.java @@ -0,0 +1,88 @@ +package com.pan.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.pan.jvm.constant.ClassInfo; +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.field.Field; +import com.pan.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(); + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassIndex.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e09d6f0076 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..b842755586 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ClassInfo.java @@ -0,0 +1,28 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..464e44a79d --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantInfo.java @@ -0,0 +1,31 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..c2da2637c5 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/ConstantPool.java @@ -0,0 +1,32 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..2aaced31d3 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/FieldRefInfo.java @@ -0,0 +1,58 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..a3e6f969b0 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/MethodRefInfo.java @@ -0,0 +1,58 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..30be83ef3a --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,49 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..cc6989bef7 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package com.pan.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + +} 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 new file mode 100644 index 0000000000..ad3f397949 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/StringInfo.java @@ -0,0 +1,28 @@ +package com.pan.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/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 new file mode 100644 index 0000000000..502adae968 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/constant/UTF8Info.java @@ -0,0 +1,38 @@ +package com.pan.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/252308879/mini-jvm/src/main/java/com/pan/jvm/field/Field.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/field/Field.java new file mode 100644 index 0000000000..22775d0de7 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/field/Field.java @@ -0,0 +1,47 @@ +package com.pan.jvm.field; + + +import com.pan.jvm.constant.ConstantPool; +import com.pan.jvm.constant.UTF8Info; +import com.pan.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; + } + + @Override + 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 accessFlags = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attrCount = iter.nextU2ToInt(); + System.out.println("Field Attributes Count: " + attrCount); + Field field = new Field(accessFlags, nameIndex, descriptorIndex, pool); + if (attrCount > 0){ + throw new RuntimeException("Attributes Count > 0"); + } + return field; + } + +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ByteCodeIterator.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..24f00ccc5d --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,52 @@ +package com.pan.jvm.loader; + +import java.util.Arrays; + +import com.pan.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/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileLoader.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..fa25990691 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileLoader.java @@ -0,0 +1,104 @@ +package com.pan.jvm.loader; + +import com.pan.jvm.clz.ClassFile; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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; + + +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/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 new file mode 100644 index 0000000000..b2bddb85c2 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/loader/ClassFileParser.java @@ -0,0 +1,172 @@ +package com.pan.jvm.loader; + +import com.pan.jvm.clz.AccessFlag; +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.clz.ClassIndex; +import com.pan.jvm.constant.*; +import com.pan.jvm.field.Field; +import com.pan.jvm.method.Method; + +import java.io.UnsupportedEncodingException; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + String magicNumber = iterator.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) {// 验证是否为Java的.class文件 + return null; + } + ClassFile classFile = new ClassFile(); + classFile.setMinorVersion(iterator.nextU2ToInt()); + classFile.setMajorVersion(iterator.nextU2ToInt()); + + ConstantPool constantPool = parseConstantPool(iterator); + classFile.setConstPool(constantPool); + + AccessFlag flag = parseAccessFlag(iterator); + classFile.setAccessFlag(flag); + + // this clz 和 supper clz + ClassIndex clzIndex = parseClassIndex(iterator); + classFile.setClassIndex(clzIndex); + + // interface + parseInterfaces(iterator); + + // field + parseFields(classFile, iterator); + + // method + parseMethods(classFile, iterator); + + return classFile; + } + + private void parseMethods(ClassFile classFile, ByteCodeIterator iterator) { + int methodsCount = iterator.nextU2ToInt(); + System.out.println("Methods Count: " + methodsCount); + + for (int i = 1; i <= methodsCount; i++) { + Method method = Method.parse(classFile, iterator); + classFile.addMethod(method); + } + } + + + private void parseFields(ClassFile clzFile, ByteCodeIterator iterator) { + int fieldsCount = iterator.nextU2ToInt(); + System.out.println("Field count:" + fieldsCount); + for (int i = 1; i <= fieldsCount; i++) {// 从第一个开始,因为不包含本身 + Field field = Field.parse(clzFile.getConstantPool(), iterator); + clzFile.addField(field); + } + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + + int thisClassIndex = iter.nextU2ToInt(); + int supperClassIndex = iter.nextU2ToInt(); + + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(thisClassIndex); + classIndex.setSuperClassIndex(supperClassIndex); + return classIndex; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + /** + * 解析常量池 + * + * @param iter + * @return + */ + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int constPoolCount = iter.nextU2ToInt(); + + System.out.println("Constant Pool Count :" + constPoolCount); + ConstantPool pool = new ConstantPool(); + // 因为常量池中的信息是从 1 开始的,但是数组或者List 下标是从0开始,所以设置第一个为空的常量 + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= constPoolCount - 1; i++) { + + // 获取标识符信息 + int tag = iter.nextU1toInt(); + + switch (tag) { + + case 7: //CONSTANT_Class + int utf8Index = iter.nextU2ToInt(); + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(utf8Index); + + pool.addConstantInfo(classInfo); + break; + case 9: // CONSTANT_Fieldref + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + + pool.addConstantInfo(fieldRefInfo); + break; + case 10: // CONSTANT_Methodref + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + + pool.addConstantInfo(methodRefInfo); + break; + case 8: + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(info); + break; + case 12: // CONSTANT_NameAndType + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); + + pool.addConstantInfo(nameAndTypeInfo); + break; + case 1: // CONSTANT_Utf8 + 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 utf8Str = new UTF8Info(pool); + utf8Str.setLength(length); + utf8Str.setValue(value); + + pool.addConstantInfo(utf8Str); + break; + default: + 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/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 new file mode 100644 index 0000000000..0fbb0f0946 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/method/Method.java @@ -0,0 +1,71 @@ +package com.pan.jvm.method; + + +import com.pan.jvm.attr.AttributeInfo; +import com.pan.jvm.attr.CodeAttr; +import com.pan.jvm.clz.ClassFile; +import com.pan.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){ + int accessFlags = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attrCount = iter.nextU2ToInt(); + + System.out.println("Method Attributes Count: " + attrCount); + Method method = new Method(clzFile, accessFlags, nameIndex, descriptorIndex); + if (attrCount > 0){ + for (int i = 1; i <= attrCount; i++) { + int attrNameIndex = iter.nextU2ToInt(); + String attrName = clzFile.getConstantPool().getUTF8String(attrNameIndex); + iter.back(2); // 回退两个,便于Code 中读取属性 + if (AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + }else { + throw new RuntimeException("Current Has CODE. Not Support Other"); + } + } + } + return method; + + } +} diff --git a/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/util/Util.java b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/util/Util.java new file mode 100644 index 0000000000..ae130b4183 --- /dev/null +++ b/group11/252308879/mini-jvm/src/main/java/com/pan/jvm/util/Util.java @@ -0,0 +1,23 @@ +package com.pan.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/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java b/group11/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java new file mode 100644 index 0000000000..8f6803c11f --- /dev/null +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/alg/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +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 new file mode 100644 index 0000000000..71671c9b47 --- /dev/null +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/alg/StackUtilTest.java @@ -0,0 +1,76 @@ +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 new file mode 100644 index 0000000000..d341553c70 --- /dev/null +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/ClassFileLoaderTest.java @@ -0,0 +1,258 @@ +package com.pan.jvm; + +import java.util.List; + +import com.pan.jvm.clz.ClassFile; +import com.pan.jvm.clz.ClassIndex; +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.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); + } + + + /** + * ---------------------------------------------------------------------- + */ + + + @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); + } + + +} diff --git a/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/TestReadCFBB.java b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/TestReadCFBB.java new file mode 100644 index 0000000000..8590e78c09 --- /dev/null +++ b/group11/252308879/mini-jvm/src/test/java/com/pan/jvm/TestReadCFBB.java @@ -0,0 +1,41 @@ +package com.pan.jvm; + +import com.pan.jvm.loader.ClassFileLoader; +import org.junit.Test; + +import java.io.IOException; + +/** + * 用于测试第一次JVM作业,读取.class作业 和 魔幻数字 + */ +public class TestReadCFBB { + + @Test + public void testClassPath(){ + ClassFileLoader classFileLoader = new ClassFileLoader(); + String path = ClassFileLoader.class.getClassLoader().getResource("").getPath(); + path = path.replace("test-classes", "classes"); + classFileLoader.addClassPath(path); + classFileLoader.addClassPath("d://tmp"); + + String clzPath = classFileLoader.getClassPath(); + System.out.println(clzPath); + } + + + + @Test + public void testReadCFBB() throws IOException { + + ClassFileLoader classFileLoader = new ClassFileLoader(); + String path = ClassFileLoader.class.getClassLoader().getResource("").getPath(); + path = path.replace("test-classes", "classes"); + classFileLoader.addClassPath(path); + byte[] bytes = classFileLoader.readBinaryCode("com.pan.jvm.loader.ClassFileLoader"); + for (byte b : bytes) { + String toHexString = Integer.toHexString(b & 0xFF).toUpperCase(); + System.out.print(toHexString + " "); + } + } + +} diff --git a/group11/252308879/pom.xml b/group11/252308879/pom.xml new file mode 100644 index 0000000000..642387b95a --- /dev/null +++ b/group11/252308879/pom.xml @@ -0,0 +1,140 @@ + + + + + + data-structure + mini-jvm + + + com.pan + 252308879 + pom + 1.0.0-SNAPSHOT + + 4.0.0 + + + UTF-8 + 1.8 + 1.8 + 3.3 + 2.4 + 2.5 + 2.5 + 2.8.2 + 2.3.1 + 2.5 + 2.12.2 + + + + + + junit + junit + 4.12 + test + + + dom4j + dom4j + 1.6.1 + + + org.apache.commons + commons-lang3 + 3.4 + + + commons-io + commons-io + 2.4 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven_compiler_plugin_version} + + ${java_source_version} + ${java_target_version} + ${project.build.sourceEncoding} + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + ${maven_surefire_report_plugin} + + false + + + + + + org.apache.maven.plugins + maven-source-plugin + ${maven_source_plugin_version} + + + attach-sources + + jar-no-fork + + + + + true + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven_jar_plugin_version} + + + true + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven_war_plugin_version} + + + true + + + + + + org.codehaus.mojo + findbugs-maven-plugin + ${findbugs_maven_plugin_version} + + true + target/site + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven_checkstyle_plugin_version} + + + + \ No newline at end of file diff --git a/group11/283091182/mini-jvm-week1-bk/loader/ClassFileLoader.java b/group11/283091182/mini-jvm-week1-bk/loader/ClassFileLoader.java new file mode 100644 index 0000000000..527e2f14d8 --- /dev/null +++ b/group11/283091182/mini-jvm-week1-bk/loader/ClassFileLoader.java @@ -0,0 +1,93 @@ +package com.coderising.jvm.loader; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + + File classFile = getClassFileFromPath(className); + + byte[] buffer = new byte[1024]; + try { + FileInputStream fis = new FileInputStream(classFile); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + int readLen; + while((readLen = fis.read(buffer))>-1){ + baos.write(buffer, 0, readLen); + } + + return baos.toByteArray(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + + public void addClassPath(String path) { + File clzPath = new File(path); + if(clzPath.exists() && clzPath.isDirectory()){ + this.clzPaths.add(path); + }else{ + System.out.println("Invalid path:"+ path); + } + } + + + + public String getClassPath(){ + StringBuilder sb = new StringBuilder(); + Iterator it = this.clzPaths.iterator(); + while(it.hasNext()){ + if(sb.length()>0){ + sb.append(";"); + } + sb.append(it.next()); + } + return sb.toString(); + } + + public File getClassFileFromPath(String className) { + Iterator it = this.clzPaths.iterator(); + + //replace "." with "\\" in windows + String fullclassPath = className.replaceAll("\\.", (File.separatorChar=='\\')?"\\\\":"/")+".class"; + + while(it.hasNext()){ + File clzFile; + String path = (String)it.next(); + if(path.endsWith(String.valueOf(File.separatorChar))){ + clzFile = new File(path+fullclassPath); + }else{ + clzFile = new File(path+File.separatorChar+fullclassPath); + } + + //Check file before further proceed + if(clzFile.exists()&&clzFile.isFile()){ + return clzFile; + } + } + + throw new RuntimeException("Class not found:"+className); + } + + + +} diff --git a/group11/283091182/mini-jvm-week1-bk/test/ClassFileloaderTest.java b/group11/283091182/mini-jvm-week1-bk/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..21d7e97074 --- /dev/null +++ b/group11/283091182/mini-jvm-week1-bk/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 = "C:\\Users\\Administrator\\mygit\\coding2017\\liuxin\\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 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/com/coderising/jvm/constant/FieldRefInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/constant/MethodRefInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/constant/NameAndTypeInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/constant/NullConstantInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/constant/StringInfo.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/constant/UTF8Info.java b/group11/283091182/mini-jvm/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group11/283091182/mini-jvm/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/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/283091182/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..514d85e08f --- /dev/null +++ b/group11/283091182/mini-jvm/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", 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/src/com/coderising/array/ArrayList.java b/group11/283091182/src/com/coderising/array/ArrayList.java new file mode 100644 index 0000000000..18b0dcca6f --- /dev/null +++ b/group11/283091182/src/com/coderising/array/ArrayList.java @@ -0,0 +1,116 @@ +package com.coderising.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 GROW_BY_SIZE = 10; + + private Object[] elementData = new Object[GROW_BY_SIZE]; + + public void add(Object o){ + if(size == elementData.length){ + grow(); + } + elementData[size]=o; + size++; + } + public void add(int index, Object o){ + validate(index); + if(size == elementData.length){ + grow(); + } + for(int i=size;i>index+1;i--){ + elementData[i]=elementData[i-1]; + } + elementData[index]=o; + size++; + } + + public Object get(int index){ + validate(index); + return elementData[index]; + } + + public Object remove(int index){ + validate(index); + Object result = elementData[index]; + for(int i =index;i=size)throw new IndexOutOfBoundsException("Invalid Index:"+pos); + Object result = elementData[pos]; + pos++; + return result; + } + + + } + + private void grow(){ + elementData = Arrays.copyOf(elementData, elementData.length+GROW_BY_SIZE); + } + private void validate(int index){ + if(index<0||index>=size)throw new IndexOutOfBoundsException("Invalid Index:"+index); + } + + @Override + public String toString(){ + StringBuilder sb = new StringBuilder("["); + for(int i=0;i1)sb.append(","); + sb.append(elementData[i]); + } + sb.append("]size=").append(this.size()); + return sb.toString(); + } + + public static void main(String[] args){ + ArrayList l = new ArrayList(); + for(int i=0;i<12;i++){ + l.add(i+""); + } + System.out.println(l); + l.add("aaa"); + System.out.println("After adding aaa:"+l); + l.add(2,"bbb"); + System.out.println("After adding bbb:"+l); + System.out.println(l.get(2)); + System.out.println("After getting:"+l); + System.out.println(l.remove(2)); + System.out.println("After removing:"+l); + Iterator it = l.iterator(); + while(it.hasNext()){ + System.out.println(it.next()); + } + } + +} diff --git a/group11/283091182/src/com/coderising/array/ArrayListTest.java b/group11/283091182/src/com/coderising/array/ArrayListTest.java new file mode 100644 index 0000000000..8bdc0515d1 --- /dev/null +++ b/group11/283091182/src/com/coderising/array/ArrayListTest.java @@ -0,0 +1,142 @@ +/** + * + */ +package com.coderising.array; + +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; + +/** + * @author Administrator + * + */ +public class ArrayListTest { + + private ArrayList al; + /** + * @throws java.lang.Exception + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + System.out.println("SetUp"); + al= new ArrayList(); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + System.out.println("TearDown"); + al = null; + } + + /** + * Test method for {@link com.coderising.array.ArrayList#add(java.lang.Object)}. + */ + @Test + public final void testAddObject() { + al.add("aaa"); + al.add("bbb"); + al.add("ccc"); + assertEquals("aaa",al.get(0)); + assertEquals("bbb",al.get(1)); + assertEquals("ccc",al.get(2)); + assertEquals(3,al.size()); + } + + /** + * Test method for {@link com.coderising.array.ArrayList#add(int, java.lang.Object)}. + */ + @Test + public final void testAddIntObject() { + al.add("aaa"); + al.add(0,"bbb"); + al.add(1,"ccc"); + assertEquals("bbb",al.get(0)); + assertEquals("ccc",al.get(1)); + assertEquals("aaa",al.get(2)); + assertEquals(3,al.size()); + } + /** + * Test method for {@link com.coderising.array.ArrayList#add(int, java.lang.Object)}. + */ + @Test(expected=IndexOutOfBoundsException.class) + public final void testAddIntObjectWithException1() { + al.add(-1, "aaa"); + } + /** + * Test method for {@link com.coderising.array.ArrayList#add(int, java.lang.Object)}. + */ + @Test(expected=IndexOutOfBoundsException.class) + public final void testAddIntObjectWithException2() { + al.add("aaa"); + al.add(1,"bbb"); + } + + /** + * Test method for {@link com.coderising.array.ArrayList#get(int)}. + */ + @Test + public final void testGet() { + fail("Not yet implemented"); // TODO + } + /** + * Test method for {@link com.coderising.array.ArrayList#get(int)}. + */ + @Test + public final void testGetWithException1() { + fail("Not yet implemented"); // TODO + } + /** + * Test method for {@link com.coderising.array.ArrayList#get(int)}. + */ + @Test + public final void testGetWithException2() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link com.coderising.array.ArrayList#remove(int)}. + */ + @Test + public final void testRemove() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link com.coderising.array.ArrayList#size()}. + */ + @Test + public final void testSize() { + fail("Not yet implemented"); // TODO + } + + /** + * Test method for {@link com.coderising.array.ArrayList#iterator()}. + */ + @Test + public final void testIterator() { + fail("Not yet implemented"); // TODO + } + +} diff --git a/group11/283091182/src/com/coding/basic/ArrayList.java b/group11/283091182/src/com/coding/basic/ArrayList.java deleted file mode 100644 index 402d05c019..0000000000 --- a/group11/283091182/src/com/coding/basic/ArrayList.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.coding.basic; - -import java.util.Arrays; - -public class ArrayList implements List { - - private int size = 0; - - private static final int GROW_BY_SIZE = 10; - - private Object[] elementData = new Object[GROW_BY_SIZE]; - - public void add(Object o){ - if(size == elementData.length){ - grow(); - } - elementData[size]=o; - size++; - } - public void add(int index, Object o){ - validate(index); - if(size == elementData.length){ - grow(); - } - for(int i=size;i>index+1;i--){ - elementData[i]=elementData[i-1]; - } - elementData[index]=o; - size++; - } - - public Object get(int index){ - validate(index); - return elementData[index]; - } - - public Object remove(int index){ - validate(index); - Object result = elementData[index]; - for(int i =index;i=size)throw new IndexOutOfBoundsException("Invalid Index:"+pos); - Object result = elementData[pos]; - pos++; - return result; - } - - - } - - private void grow(){ - elementData = Arrays.copyOf(elementData, elementData.length+GROW_BY_SIZE); - } - private void validate(int index){ - if(index<0||index>=size)throw new IndexOutOfBoundsException("Invalid Index:"+index); - } - - @Override - public String toString(){ - StringBuilder sb = new StringBuilder("["); - for(int i=0;i1)sb.append(","); - sb.append(elementData[i]); - } - sb.append("]size=").append(this.size()); - return sb.toString(); - } - - public static void main(String[] args){ - ArrayList l = new ArrayList(); - for(int i=0;i<12;i++){ - l.add(i+""); - } - System.out.println(l); - l.add("aaa"); - System.out.println("After adding aaa:"+l); - l.add(2,"bbb"); - System.out.println("After adding bbb:"+l); - System.out.println(l.get(2)); - System.out.println("After getting:"+l); - System.out.println(l.remove(2)); - System.out.println("After removing:"+l); - Iterator it = l.iterator(); - while(it.hasNext()){ - System.out.println(it.next()); - } - } - -} diff --git a/group11/283091182/src/com/coding/basic/ArrayListTest.java b/group11/283091182/src/com/coding/basic/ArrayListTest.java deleted file mode 100644 index 7807fa831e..0000000000 --- a/group11/283091182/src/com/coding/basic/ArrayListTest.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * - */ -package com.coding.basic; - -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; - -/** - * @author Administrator - * - */ -public class ArrayListTest { - - private ArrayList al; - /** - * @throws java.lang.Exception - */ - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - /** - * @throws java.lang.Exception - */ - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - /** - * @throws java.lang.Exception - */ - @Before - public void setUp() throws Exception { - System.out.println("SetUp"); - al= new ArrayList(); - } - - /** - * @throws java.lang.Exception - */ - @After - public void tearDown() throws Exception { - System.out.println("TearDown"); - al = null; - } - - /** - * Test method for {@link com.coding.basic.ArrayList#add(java.lang.Object)}. - */ - @Test - public final void testAddObject() { - al.add("aaa"); - al.add("bbb"); - al.add("ccc"); - assertEquals("aaa",al.get(0)); - assertEquals("bbb",al.get(1)); - assertEquals("ccc",al.get(2)); - assertEquals(3,al.size()); - } - - /** - * Test method for {@link com.coding.basic.ArrayList#add(int, java.lang.Object)}. - */ - @Test - public final void testAddIntObject() { - al.add("aaa"); - al.add(0,"bbb"); - al.add(1,"ccc"); - assertEquals("bbb",al.get(0)); - assertEquals("ccc",al.get(1)); - assertEquals("aaa",al.get(2)); - assertEquals(3,al.size()); - } - /** - * Test method for {@link com.coding.basic.ArrayList#add(int, java.lang.Object)}. - */ - @Test(expected=IndexOutOfBoundsException.class) - public final void testAddIntObjectWithException1() { - al.add(-1, "aaa"); - } - /** - * Test method for {@link com.coding.basic.ArrayList#add(int, java.lang.Object)}. - */ - @Test(expected=IndexOutOfBoundsException.class) - public final void testAddIntObjectWithException2() { - al.add("aaa"); - al.add(1,"bbb"); - } - - /** - * Test method for {@link com.coding.basic.ArrayList#get(int)}. - */ - @Test - public final void testGet() { - fail("Not yet implemented"); // TODO - } - /** - * Test method for {@link com.coding.basic.ArrayList#get(int)}. - */ - @Test - public final void testGetWithException1() { - fail("Not yet implemented"); // TODO - } - /** - * Test method for {@link com.coding.basic.ArrayList#get(int)}. - */ - @Test - public final void testGetWithException2() { - fail("Not yet implemented"); // TODO - } - - /** - * Test method for {@link com.coding.basic.ArrayList#remove(int)}. - */ - @Test - public final void testRemove() { - fail("Not yet implemented"); // TODO - } - - /** - * Test method for {@link com.coding.basic.ArrayList#size()}. - */ - @Test - public final void testSize() { - fail("Not yet implemented"); // TODO - } - - /** - * Test method for {@link com.coding.basic.ArrayList#iterator()}. - */ - @Test - public final void testIterator() { - fail("Not yet implemented"); // TODO - } - -} diff --git a/group11/283091182/src/com/coding/basic/LinkedList.java b/group11/283091182/src/com/coding/basic/LinkedList.java deleted file mode 100644 index 233c243130..0000000000 --- a/group11/283091182/src/com/coding/basic/LinkedList.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.coding.basic; - -public class LinkedList implements List { - - private Node head = null; - private int size = 0; - - public void add(Object o){ - if(head==null){ - head = new Node(o); - }else{ - Node temp = head; - while(temp.hasNext()){ - temp = temp.next; - } - temp.next = new Node(o); - } - size++; - - } - public void add(int index , Object o){ - validate(index); - if(index==0){ - Node newNode = new Node(o,head); - head = newNode; - }else{ - Node temp = head; - for(int i=0;i=size)throw new IndexOutOfBoundsException("Invalid Index:"+index); - } - - 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; - } - public Node(Object data){ - this.data = data; - this.next = null; - } - } - @Override - public String toString(){ - StringBuilder sb = new StringBuilder("["); - Node temp = head; - while(temp!=null){ - if(sb.length()>1)sb.append(","); - sb.append(temp.data); - temp = temp.next; - } - sb.append("]size=").append(this.size()); - return sb.toString(); - } - public static void main(String[] args){ - LinkedList l = new LinkedList(); - for(int i=0;i<12;i++){ - l.add(i+""); - } - System.out.println(l); - l.add("aaa"); - System.out.println("After adding aaa:"+l); - l.add(2,"bbb"); - System.out.println("After adding bbb:"+l); - System.out.println(l.get(2)); - System.out.println("After getting:"+l); - System.out.println(l.remove(2)); - System.out.println("After removing:"+l); - l.addFirst("first"); - System.out.println("After add First:"+l); - l.addLast("last"); - System.out.println("After add Last:"+l); - System.out.println(l.removeFirst()); - System.out.println("After remove First:"+l); - System.out.println(l.removeLast()); - System.out.println("After remove Last:"+l); - Iterator it = l.iterator(); - while(it.hasNext()){ - System.out.println(it.next()); - } - //it.next(); - } -} diff --git a/group11/283091182/src/com/coding/basic/Queue.java b/group11/283091182/src/com/coding/basic/Queue.java index 45fea2a118..0f1f068e19 100644 --- a/group11/283091182/src/com/coding/basic/Queue.java +++ b/group11/283091182/src/com/coding/basic/Queue.java @@ -1,5 +1,7 @@ package com.coding.basic; +import com.coding.basic.linklist.LinkedList; + public class Queue { private LinkedList list = new LinkedList(); diff --git a/group11/283091182/src/com/coding/basic/Stack.java b/group11/283091182/src/com/coding/basic/Stack.java index 915d173b1b..5ff5ce5279 100644 --- a/group11/283091182/src/com/coding/basic/Stack.java +++ b/group11/283091182/src/com/coding/basic/Stack.java @@ -1,5 +1,7 @@ package com.coding.basic; +import com.coderising.array.ArrayList; + public class Stack { private ArrayList elementData = new ArrayList(); diff --git a/group11/283091182/src/com/coding/basic/linklist/LRUPageFrame.java b/group11/283091182/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..9f6edbcb66 --- /dev/null +++ b/group11/283091182/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,141 @@ +package com.coding.basic.linklist; + +/** + * 用双向链表实现LRU算法 + * @author liuxin + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + + Node(int pageNum, Node prev, Node next){ + this.pageNum = pageNum; + this.next = next; + this.prev = prev; + } + } + + private int capacity; + + private int size; + + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + System.out.println("CurrentList= "+this.toString()+"; accessing - "+pageNum); + Node target = find(pageNum); + if(target==null){ + createNewNodeAsHead(pageNum); + }else{ + moveExistingNodeToHead(target); + } + + } + + private void removeLast(){ + Node secToLast = last.prev; + last = null; + secToLast.next = null; + last = secToLast; + size--; + } + + private void moveExistingNodeToHead(Node node){ + + Node prev = node.prev; + Node next = node.next; + + if(prev==null){ + //already in the head,do nothing; + return; + } + + if(next==null){ + //currently in the tail + last = prev; + } + + //in the middle + prev.next = next; + if(next!=null){ + next.prev = prev; + } + node.prev = null; + node.next = first; + first = node; + } + + private void createNewNodeAsHead(int value){ + Node node = new Node(value,null,null); + //first node + if(size==0){ + this.first = node; + this.last = node; + this.size ++; + }else{ + //linklist already exists + this.first.prev = node; + node.next = this.first; + this.first = node; + this.size++; + + if(size>capacity){ + removeLast(); + } + } + + } + + private Node find(int value){ + if(size==0){ + return null; + } + Node temp = first; + while(temp!=null){ + if(temp.pageNum==value){ + return temp; + }else{ + temp = temp.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(","); + } + } + return buffer.toString(); + } + +} diff --git a/group11/283091182/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group11/283091182/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..4070f1f2b3 --- /dev/null +++ b/group11/283091182/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/group11/283091182/src/com/coding/basic/linklist/LinkedList.java b/group11/283091182/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..2c5959890a --- /dev/null +++ b/group11/283091182/src/com/coding/basic/linklist/LinkedList.java @@ -0,0 +1,181 @@ +package com.coding.basic.linklist; + +import com.coding.basic.Iterator; +import com.coding.basic.List; + +public class LinkedList implements List { + + private Node head = null; + private int size = 0; + + public void add(Object o){ + if(head==null){ + head = new Node(o); + }else{ + Node temp = head; + while(temp.hasNext()){ + temp = temp.next; + } + temp.next = new Node(o); + } + size++; + + } + public void add(int index , Object o){ + validate(index); + if(index==0){ + Node newNode = new Node(o,head); + head = newNode; + }else{ + Node temp = head; + for(int i=0;i=size)throw new IndexOutOfBoundsException("Invalid Index:"+index); + } + + 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; + } + public Node(Object data){ + this.data = data; + this.next = null; + } + } + @Override + public String toString(){ + StringBuilder sb = new StringBuilder("["); + Node temp = head; + while(temp!=null){ + if(sb.length()>1)sb.append(","); + sb.append(temp.data); + temp = temp.next; + } + sb.append("]size=").append(this.size()); + return sb.toString(); + } + public static void main(String[] args){ + LinkedList l = new LinkedList(); + for(int i=0;i<12;i++){ + l.add(i+""); + } + System.out.println(l); + l.add("aaa"); + System.out.println("After adding aaa:"+l); + l.add(2,"bbb"); + System.out.println("After adding bbb:"+l); + System.out.println(l.get(2)); + System.out.println("After getting:"+l); + System.out.println(l.remove(2)); + System.out.println("After removing:"+l); + l.addFirst("first"); + System.out.println("After add First:"+l); + l.addLast("last"); + System.out.println("After add Last:"+l); + System.out.println(l.removeFirst()); + System.out.println("After remove First:"+l); + System.out.println(l.removeLast()); + System.out.println("After remove Last:"+l); + Iterator it = l.iterator(); + while(it.hasNext()){ + System.out.println(it.next()); + } + //it.next(); + } +} diff --git a/group11/283091182/src/com/coding/basic/stack/Stack.java b/group11/283091182/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..c59be3c1e4 --- /dev/null +++ b/group11/283091182/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,50 @@ +package com.coding.basic.stack; + +import com.coderising.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + if(elementData.size()==0)throw new RuntimeException("Stack is empty."); + return elementData.remove(elementData.size()-1); + } + + public Object peek(){ + if(elementData.size()==0)throw new RuntimeException("Stack is empty."); + return elementData.get(elementData.size()-1); + } + public boolean isEmpty(){ + return (elementData.size()==0); + } + public int size(){ + return elementData.size(); + } + + @Override + public String toString(){ + return elementData.toString(); + } + + public static void main(String[] args){ + Stack s = new Stack(); + s.push("aaa"); + s.push("bbb"); + s.push("ccc"); + System.out.println(s); + System.out.println(s.isEmpty()); + System.out.println(s.size()); + System.out.println(s.peek()); + System.out.println(s.pop()); + System.out.println(s.pop()); + System.out.println(s.pop()); + System.out.println(s); + System.out.println(s.isEmpty()); + System.out.println(s.size()); + //System.out.println(s.pop()); + } +} diff --git a/group11/283091182/src/com/coding/basic/stack/StackUtil.java b/group11/283091182/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..cd5aa08d06 --- /dev/null +++ b/group11/283091182/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,140 @@ +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 temp = new Stack(); + int counter = s.size(); + while(counter>1){ + //Get the peek one + Object o = s.pop(); + for(int i=0;is.size()){ + throw new RuntimeException("Index Out of Bound:"+ len); + } + Object[] objArr = new Object[len]; + Stack tmpStk = new Stack(); + for(int i=0;i totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + + return baos.toByteArray(); + } @Override diff --git a/group11/542194147/myDataStructure/src/com/coderising/jvm/loader/ClassFileLoader.java b/group11/542194147/myDataStructure/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..f6b93bfb41 --- /dev/null +++ b/group11/542194147/myDataStructure/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,89 @@ +package com.coderising.jvm.loader; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + private static final int BUFFER_SIZE=1024; + + public byte[] readBinaryCode(String className) { + className=className.replace(".","\\")+".class"; + String absolutePath=null; + for(int i=0;ifile.length()){ + return Arrays.copyOf(baos.toByteArray(), (int) file.length()); + } + } catch (IOException e) { + e.printStackTrace(); + }finally{ + try { + fis.close(); + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return baos.toByteArray(); + } + + + public void addClassPath(String path) { + if(this.clzPaths.contains(path)){ + return; + } + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuffer sb=new StringBuffer(); + for(int i=0;i=capacity){//缓存已满删除最后的数据 + removeLastNode(); + } + addNewNodeTOHead(newNode);//把新数据加到缓存头部 + } + } + + private void addNewNodeTOHead(Node node) { + if(first==null&&last==null){ + first=node; + last=node; + node.next=null; + node.prev=null; + }else{ + first.prev=node; + node.prev=null; + node.next=first; + first=node; + } + currentSize++; + } + + private void removeLastNode() { + Node node=last.prev; + node.next=null; + last.prev=null; + last=node; + currentSize--; + } + + private void moveExistingNodeToHead(Node node) { + if(node==first){ + return; + }else if(node==last){ + Node prevNode=node.prev; + last=prevNode; + prevNode.next=null; + }else{ + node.prev.next=node.next; + node.next.prev=node.prev; + } + node.prev=null; + node.next=first; + first.prev=node; + first=node; + } + + + private Node findNode(int data) { + Node node=first; + while(node!=null){ + if(node.pageNum==data){ + return node; + } + node=node.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(","); + } + } + return buffer.toString(); + } + +} diff --git a/group11/542194147/myDataStructure/src/com/coding/basic/LRUPageFrameTest.java b/group11/542194147/myDataStructure/src/com/coding/basic/LRUPageFrameTest.java new file mode 100644 index 0000000000..53db234945 --- /dev/null +++ b/group11/542194147/myDataStructure/src/com/coding/basic/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +package com.coding.basic; + +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/group11/996108220/src/com/coderising/jvm/clz/AccessFlag.java b/group11/996108220/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java b/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..8575f5641a --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,74 @@ +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/996108220/src/com/coderising/jvm/clz/ClassIndex.java b/group11/996108220/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..f42e45d48f --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coderising.jvm.clz; + +public class ClassIndex { + private int thisClassIndex;//u2 + private int superClassIndex;//u2 + + 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/996108220/src/com/coderising/jvm/constant/ClassInfo.java b/group11/996108220/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..d673cae1bd --- /dev/null +++ b/group11/996108220/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 ;//u2 + 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/996108220/src/com/coderising/jvm/constant/ConstantInfo.java b/group11/996108220/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java b/group11/996108220/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coderising/jvm/constant/FieldRefInfo.java b/group11/996108220/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..07133aa3a1 --- /dev/null +++ b/group11/996108220/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;//u2 + private int nameAndTypeIndex;//u2 + + 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/996108220/src/com/coderising/jvm/constant/MethodRefInfo.java b/group11/996108220/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..ad3723ad0c --- /dev/null +++ b/group11/996108220/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; //u2 + private int nameAndTypeIndex;//u2 + + 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/996108220/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group11/996108220/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..ee05963d21 --- /dev/null +++ b/group11/996108220/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;//u2 + private int index2;//u2 + + 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/996108220/src/com/coderising/jvm/constant/NullConstantInfo.java b/group11/996108220/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coderising/jvm/constant/StringInfo.java b/group11/996108220/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..1f0539dda4 --- /dev/null +++ b/group11/996108220/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;//u2 + 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/996108220/src/com/coderising/jvm/constant/UTF8Info.java b/group11/996108220/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..c2c4408421 --- /dev/null +++ b/group11/996108220/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 ;//2 + private String value;//length + 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/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..a151decad8 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.loader; + +import java.util.Arrays; +import com.coderising.jvm.util.Util; + + + +public class ByteCodeIterator { + byte[] codes; + int cursor=0; + public ByteCodeIterator(byte[] codes) { + this.codes=codes; + } + public ByteCodeIterator(byte[] codes,int cursor) { + this.codes=codes; + this.cursor=cursor; + } + public boolean hasNext() { + return cursor != codes.length; + } + + + public int next() { + + int i = cursor; + if (i >= codes.length) + throw new ArrayIndexOutOfBoundsException(); + cursor = i + 1; + return codes[i]&0xFF; + } + public int nextU2ToInt() { + + return Util.byteToInt(new byte[]{codes[cursor++],codes[cursor++]}); + } + public int nextU4ToInt() { + + return Util.byteToInt(new byte[]{codes[cursor++],codes[cursor++], + codes[cursor++],codes[cursor++]}); + } + public String nextU4ToHexString() { + return Util.byteToHexString(new byte[]{codes[cursor++],codes[cursor++], + codes[cursor++],codes[cursor++]}); + + } + public byte[] getByte(int length) { + int i=cursor; + cursor=cursor+length; + return Arrays.copyOfRange(codes,i, cursor); + } + +} diff --git a/group11/996108220/src/com/coderising/jvm/loader/ClassFileLoader.java b/group11/996108220/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..eccf6dc7b0 --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,88 @@ +package com.coderising.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 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 fileName) { + ArrayList list=new ArrayList(); + try { + InputStream in=new FileInputStream(fileName.toString()); + int length=-1; + byte[] buffer=new byte[1024]; + while ((length=in.read(buffer))!=-1) { + int size=list.size(); + for (int i = size; i < size+length; i++) { + list.add(buffer[i-size]); + } + } + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + byte[] byteCodes=new byte[list.size()]; + for (int i = 0; i < byteCodes.length; i++) { + byteCodes[i]=list.get(i); + } + + return byteCodes; + } + + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + public void addClassPath(String path) { + clzPaths.add(path); + + } + + + + public String getClassPath(){ + String string=""; + for (int i = 0; i < clzPaths.size(); i++) { + string=i==0?string+clzPaths.get(i):string+";"+clzPaths.get(i); + } + return string; + } + + + + + +} diff --git a/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java b/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..ac55f25e0e --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,111 @@ +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.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.util.Util; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ByteCodeIterator iter=new ByteCodeIterator(codes); + String magicNumber=iter.nextU4ToHexString(); + if (!magicNumber.equals("cafebabe")) { + return null; + } + ClassFile classFile=new ClassFile(); + classFile.setMinorVersion(iter.nextU2ToInt()); + classFile.setMajorVersion(iter.nextU2ToInt()); + classFile.setConstPool(parseConstantPool(iter)); + classFile.setAccessFlag(parseAccessFlag(iter)); + classFile.setClassIndex(parseClassInfex(iter)); + return classFile; + } + + 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 constPoolCount=iter.nextU2ToInt(); + + ConstantPool pool=new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i <= constPoolCount-1; i++) { + int tag=iter.next(); + if (tag==1) { + //UTF8Info + UTF8Info utf8Info=new UTF8Info(pool); + int length=iter.nextU2ToInt(); + utf8Info.setLength(length); + String value=Util.byteToString(iter.getByte(length)); + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + } + else if (tag==7) { + //ClassInfo + ClassInfo classInfo=new ClassInfo(pool); + int utf8Index=iter.nextU2ToInt(); + classInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(classInfo); + } + else if (tag==8) { + //StringInfo + StringInfo stringInfo=new StringInfo(pool); + int index=iter.nextU2ToInt(); + stringInfo.setIndex(index); + pool.addConstantInfo(stringInfo); + } + else if (tag==9) { + //FieldRefInfo + 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 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 nameAndTypeInfo=new NameAndTypeInfo(pool); + int index1=iter.nextU2ToInt(); + int index2=iter.nextU2ToInt(); + nameAndTypeInfo.setIndex1(index1); + nameAndTypeInfo.setIndex2(index2); + pool.addConstantInfo(nameAndTypeInfo); + } + else { + new RuntimeException("缺少tag为"+tag+"的常量"); + } + } + + return pool; + } + + +} diff --git a/group11/996108220/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group11/996108220/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..44d000a19a --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,201 @@ +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.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.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; +import com.coderising.jvm.loader.ClassFileLoader; + + + + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "F:\\mycoding2017\\group11\\996108220\\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); + } + + + + 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/group11/996108220/src/com/coderising/jvm/test/EmployeeV1.java b/group11/996108220/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..9a36573dd3 --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coderising/jvm/util/Util.java b/group11/996108220/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..c9808b1c1c --- /dev/null +++ b/group11/996108220/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,33 @@ +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;ielementData.length)this.grow(elementData); - else elementData[size++]=o; + else{ + elementData[size]=o; + size++; + } + } /** * 在index处添加元素,index+1到size-1元素向后移动 diff --git a/group11/996108220/src/com/coding/basic/Stack.java b/group11/996108220/src/com/coding/basic/Stack.java deleted file mode 100644 index ea41c87d1b..0000000000 --- a/group11/996108220/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.coding.basic; - -public class Stack { - //用动态数组实现栈 - private ArrayList elementData = new ArrayList(); - - public void push(Object o){ - elementData.add(elementData.size()); - } - - public Object pop(){ - return elementData.remove(elementData.size()-1); - } - - public Object peek(){ - return elementData.get(elementData.size()-1); - } - public boolean isEmpty(){ - return elementData.size()==0?true:false; - } - public int size(){ - return elementData.size(); - } -} diff --git a/group11/996108220/src/com/coding/basic/linklist/LRUPageFrame.java b/group11/996108220/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..f9ee1e68fa --- /dev/null +++ b/group11/996108220/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,139 @@ +package com.coding.basic.linklist; + + +/** + * 用双向链表实现LRU算法 + * @author 996108220 + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + + public Node(int pageNum2) { + this.pageNum=pageNum2; + this.next=null; + this.prev=null; + } + + } + + private int capacity; + private int size; + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + this.size=0; + + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + Node node=remove(pageNum); + if (node==null) { + node=new Node(pageNum); + push(node); + } + else { + addTail(node); + } + + + } + + + private void push(Node node) { + if (this.size()==capacity) { + removeFirst(); + } + addTail(node); + } + + private void addTail(Node node) { + if (size==0) { + first=node; + last=node; + } + else { + node.prev=last; + last.next=node; + last=node; + + } + size++; + + } + + private void removeFirst() { + + Node node=this.first; + first=first.next; + node.next=null; + first.prev=null; + size--; + } + + private int size() { + + return size; + } + + private Node remove(int pageNum) { + Node node=first; + while(node!=null){ + if (node.pageNum==pageNum) { + if (node==first) { + first=node.next; + node.next=null; + first.prev=null; + } + else if (node==last) { + last=node.prev; + last.next=null; + node.prev=null; + } + else { + node.prev.next=node.next; + node.next.prev=node.prev; + node.next=null; + node.prev=null; + } + size--; + break; + } + node=node.next; + } + return node; + } + + public String toString(){ + StringBuilder buffer = new StringBuilder(); + Node node = last; + while(node != null){ + buffer.append(node.pageNum); + + node = node.prev; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } + +} diff --git a/group11/996108220/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group11/996108220/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..67cf36067b --- /dev/null +++ b/group11/996108220/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/group11/996108220/src/com/coding/basic/stack/Stack.java b/group11/996108220/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..05f380a304 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,40 @@ +package com.coding.basic.stack; + +import com.coding.basic.ArrayList; + +public class Stack { + //用动态数组实现栈 + private ArrayList elementData = new ArrayList(); + + public void push(Object o){ + elementData.add(o); + } + + public Object pop(){ + return elementData.remove(elementData.size()-1); + } + + public Object peek(){ + return elementData.get(elementData.size()-1); + } + public boolean isEmpty(){ + return elementData.size()==0?true:false; + } + public int size(){ + return elementData.size(); + } + public String toString() { + + StringBuffer buffer=new StringBuffer("["); + for (int i = elementData.size()-1; i >=0; i--) { + if (i==0) { + buffer.append(elementData.get(i).toString()+"]"); + } + else { + buffer.append(elementData.get(i).toString()+","); + } + } + return buffer.toString(); + } + +} diff --git a/group11/996108220/src/com/coding/basic/stack/StackUtil.java b/group11/996108220/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..2499f144ea --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,131 @@ +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) { + + reverse(s,s.size()); + } + + private static void reverse(Stack s, int length) { + if (length==1) { + return ; + } + Stack s1=new Stack(); + Object o=s.pop(); + for (int i = 1; i < length; i++) { + s1.push(s.pop()); + } + s.push(o); + for (int i = 1; i < length; i++) { + s.push(s1.pop()); + } + reverse(s, length-1); + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + if (s.size()==0) { + return; + } + Stack s1=new Stack(); + while(s.size()!=0) { + if (!s.peek().equals(o)) { + s1.push(s.pop()); + + } + else { + s.pop(); + break; + } + } + while(s1.size()!=0) { + s.push(s1.pop()); + } + + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (len>s.size()||len<=0) { + return null; + } + Stack s1=new Stack(); + Object[] array=new Object[len]; + for (int i = 0; i < len; i++) { + Object object=s.pop(); + array[i]=object; + s1.push(object); + } + while(s1.size()!=0) { + s.push(s1.pop()); + } + 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){ + Stack stack=new Stack(); + for (int i = 0; i < s.length(); i++) { + switch (s.charAt(i)) { + case '(': + stack.push(s.charAt(i)); + break; + case '[': + stack.push(s.charAt(i)); + break; + case '{': + stack.push(s.charAt(i)); + break; + case ')': + if (stack.size()==0||(!stack.pop().equals('('))) { + return false; + } + break; + case ']': + if (stack.size()==0||(!stack.pop().equals('['))) { + return false; + } + break; + case '}': + if (stack.size()==0||(!stack.pop().equals('{'))) { + return false; + } + break; + default: + break; + } + } + if (stack.size()!=0) { + return false; + } + else { + return true; + } + + } + + +} diff --git a/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java b/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..91e3211683 --- /dev/null +++ b/group11/996108220/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,82 @@ +package com.coding.basic.stack; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class StackUtilTest { + Stack s; + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + } + @Test + public void testToString() { + s=new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + s.push(6); + + Assert.assertEquals("[6,5,4,3,2,1]", s.toString()); + } + + @Test + public void testReverse() { + s=new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + s.push(6); + StackUtil.reverse(s); + //System.out.println(s.size()); + Assert.assertEquals("[1,2,3,4,5,6]", s.toString()); + } + @Test + public void testRemove() { + s=new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + s.push(6); + StackUtil.remove(s, 6); + //System.out.println(s.toString()); + Assert.assertEquals("[5,4,3,2,1]", s.toString()); + } + @Test + public void testGetTop() { + s=new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + s.push(6); + Object[] s1=StackUtil.getTop(s, s.size()); + for (int i = 0; i < s1.length; i++) { + System.out.println(s1[i]); + } + //Assert.assertEquals("[5,6]", s1.toString()); + } + @Test + public void testIsValidPairs() { + String s="([e{df])" ; + Assert.assertEquals(false, StackUtil.isValidPairs(s)); + } + +} diff --git a/group11/group11.md b/group11/group11.md deleted file mode 100644 index 8b13789179..0000000000 --- a/group11/group11.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/group12/247565311/structure/week1/ArrayList.java b/group12/247565311/structure/week1/ArrayList.java new file mode 100644 index 0000000000..a16c32e05c --- /dev/null +++ b/group12/247565311/structure/week1/ArrayList.java @@ -0,0 +1,204 @@ +package structure.week1; + +import java.util.Collection; + +import structure.week1.List; + +public class ArrayList{ + private int size=0,offset=10; + private Object[] data = null; + public ArrayList(){ + data = new Object[offset]; + } + public ArrayList(int arg0){ + if(arg0<0) arg0=0; + size = arg0; + data = new Object[size]; + } + + public void add(Object arg0) { + size += 1; + int leng = data.length; + if(size>leng){ + Object[] newdata = new Object[size + offset]; + for(int i=0;isize || 0leng){ + Object[] newdata = new Object[size + offset]; + for(int i=0;i arg0) { + if (arg0 == null) return false; + int leng = data.length,newobjnum = arg0.size(),lastsize=size; + size += newobjnum; + if(size>leng){ + Object[] newdata = new Object[size + offset]; + for(int i=0;i arg1) { + int newobjnum = arg1.size(),lastsize = size; + if(arg1 == null || arg0>size+1 || 0>arg0 || newobjnum==0) return false; + size += newobjnum; + int leng = data.length; + if(size>leng){ + Object[] newdata = new Object[size + offset]; + for(int i=0;i arg0) { + for(Object o:arg0){ + if(!this.contains(o)) return false; + } + return true; + } + + public E get(int arg0) { + if(arg0 >-1 && arg0-1;i--){ + if(this.data[i].equals(arg0)) return i; + } + return -1; + } + + public Iterator iterator() { + + return null; + } + + public boolean remove(Object arg0) { + for(int i=0;ithis.size-1) return null; + E res = (E)data[arg0]; + for(int i=arg0;i arg0) { + int toberemovednums = arg0.size(); + if(!this.containsAll(arg0)) return false; + int index=0; + for(int i=0;ithis.size-1) return null; + this.data[arg0] = arg1; + return arg1; + } + + public int size() { + return this.size; + } +////////////////////////////////////////////// + public Object[] toArray() { + if(this.size == 0) return null; + Object[] res = new Object[this.size]; + for(int i=0;i T[] toArray(T[] arg0) { + T[] res = (T[])(new Object[this.size]); + for(int i=0;i{ + public boolean hasNext(); + public E next(); +} diff --git a/group12/247565311/structure/week1/LinkedList.java b/group12/247565311/structure/week1/LinkedList.java new file mode 100644 index 0000000000..362959879b --- /dev/null +++ b/group12/247565311/structure/week1/LinkedList.java @@ -0,0 +1,237 @@ +package structure.week1; + +import java.util.Collection; + +public class LinkedList { + private Node head = null; + private Node tail = null; + private int size = 0; + + public LinkedList(){ + head = new Node(null); + tail = new Node(null); + head.next = tail; + tail.ahead = head; + size = 0; + } + public LinkedList(int arg0){ + head = new Node(null); + tail = new Node(null); + head.next = tail; + tail.ahead = head; + size = 0; + } + public Object clone(){ + LinkedList clone = null; + try { + clone = (LinkedList)(super.clone()); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + clone.head = new Node(null); + clone.tail = new Node(null); + clone.size = 0; + for(Node x = head.next;x!=null;x = x.next){ + clone.add(x.val); + } + return clone; + } + public void add(Object val) { + Node n = new Node(val); + n.next = tail; + n.ahead = tail.ahead; + tail.ahead.next = n; + tail.ahead = n; + size += 1; + } + + public void add(int arg0, E arg1) { + if(arg0<0 || arg0>size) arg0=0; + Node n=new Node(arg1),p=head; + for(int i=0;i arg0) { + for(E o:arg0){ + this.add(o); + } + return true; + } + + public boolean addAll(int arg0, Collection arg1) { + for(E e:arg1){ + this.add(arg0,e); + arg0+=1; + } + return true; + } + + public void clear() { + head = new Node(null); + tail = new Node(null); + head.next = tail; + tail.ahead = head; + size = 0; + } + + public boolean contains(Object arg0) { + boolean flag = arg0==null; + Node n = head; + for(int i=0;i arg0) { + for(Object e:arg0){ + if(!this.contains(e)) return false; + } + return true; + } + + public E get(int arg0) { + E res = null; + if(arg0>-1 && arg0 < size){ + Node n = head; + for(int i=0;i iterator() { + + return null; + } + + public int lastIndexOf(Object arg0) { + boolean flag = arg0==null; + Node n = tail; + for(int i=size-1;i>-1;i--){ + n = n.ahead; + if(flag){ + if(n.val == null) return i; + }else{ + if(arg0.equals(n.val)) return i; + } + } + return -1; + } + + public boolean remove(Object arg0) { + Node n = head; + int index = this.indexOf(arg0); + if(index == -1) return false; + for(int i=0;isize-1) return null; + for(int i=0;i arg0) { + for(Object o:arg0){ + if(!this.remove(o)) return false; + } + return true; + } + + public boolean retainAll(Collection arg0) { + // ? + return false; + } + + public E set(int arg0, E arg1) { + if(arg0<0 || arg0>size-1) return null; + Node n=head; + for(int i=0;i T[] toArray(T[] arg0) { + T[]res = (T[]) new Object[size]; + Node n = head; + for(int i=0;i extends Iterator{ + public void add(Object o); + public E get(int index); + public E remove(int index); + public int size(); + void add(int arg0, E arg1); +} diff --git a/group12/247565311/structure/week1/Queue.java b/group12/247565311/structure/week1/Queue.java new file mode 100644 index 0000000000..ec96650332 --- /dev/null +++ b/group12/247565311/structure/week1/Queue.java @@ -0,0 +1,18 @@ +package structure.week1; +public class Queue { + private LinkedList data = new LinkedList(); + public void enQueue(E arg0){ + data.add(data.size(),arg0); + } + public E deQueue(){ + E res = data.get(0); + data.remove(0); + return res; + } + public int size(){ + return data.size(); + } + public boolean isEmpty(){ + return data.isEmpty(); + } +} diff --git a/group12/247565311/structure/week1/Stack.java b/group12/247565311/structure/week1/Stack.java new file mode 100644 index 0000000000..582f5d0eac --- /dev/null +++ b/group12/247565311/structure/week1/Stack.java @@ -0,0 +1,28 @@ +package structure.week1; + +import structure.week1.List; + +public class Stack { + private ArrayList data = new ArrayList(); + public boolean isEmpty(){ + return data.isEmpty(); + } + public int size(){ + return data.size(); + } + public boolean push(E arg0){ + data.add(arg0); + return true; + } + public E pop(){ + if(this.isEmpty()) return null; + E res = data.get(data.size()-1); + data.remove(data.size()-1); + return res; + } + public E peek(){ + if(this.isEmpty()) return null; + E res = data.get(data.size()-1); + return res; + } +} diff --git a/group12/247565311/structure/week2/ArrayUtil.java b/group12/247565311/structure/week2/ArrayUtil.java new file mode 100644 index 0000000000..4c29f58e7e --- /dev/null +++ b/group12/247565311/structure/week2/ArrayUtil.java @@ -0,0 +1,206 @@ +package structure.week2; +import structure.week1.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){ // time :O(n) + int leno = origin.length; + for(int i=0;i=len1){ + temparray[temp] = array2[p2]; + p2 += 1; + continue; + } + if(p2>=len2){ + temparray[temp] = array1[p1]; + p1 += 1; + continue; + } + if(array1[p1] > array2[p2]){ + temparray[temp] = array2[p2]; + p2 += 1; + }else{ + temparray[temp] = array1[p1]; + p1 += 1; + } + } + temp = 0; + for(int i=1;i data = new ArrayList(); + data.add(llast); + data.add(last); + while(last+llast li = new ArrayList(); + int cur = 2; + while(cur li = null,resli = new ArrayList(); + for(int i=6;i getAllElem(int arg0){ + ArrayList res = new ArrayList(); + for(int i=1;i size || index<0) throw new IndexOutOfBoundsException("Index:"+index+", Size:"+size); + } + private void checkGetIndex(int index){ + if(index >= size || index<0) throw new IndexOutOfBoundsException("Index:"+index+", Size:"+size); + } + public void add(Object o){ + Node newNode = new Node(o),p = head; + while(p.next!=null) + p = p.next; + p.next = newNode; + size += 1; + } + /** + * + * */ + public void add(int index , Object o){ + checkAddIndex(index); + Node p = head; + for(int i=0;i7->10 , úΪ 10->7->3 + */ + public void reverse(){ + Node rhead = new Node(),p=head; + for(int i=0;i5->7->8 , ɾԺֵΪ 7->8 + * list = 2->5->7->8->10 ,ɾԺֵΪ7,8,10 + + */ + public void removeFirstHalf(){ + int numToRemove = 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 []res = new int[list.size()]; + Node p = head.next,q = list.head.next; + int lenl = list.size(),index=0; + for(int i=0;imax) return; // Ŀ (min,max) + Node p = head; + while(p.next != null && ((Integer)p.next.data).intValue()<=min) // ɵԪ + p = p.next; + while(p.next != null && ((Integer)p.next.data).intValue() lib = new HashSet(); + class Node{ + int val; + Node next; + public Node(int _val){ + val = _val; + next = null; + } + } + public LRUPageFrame(int _size){ + if(_size>0) { + this.size = _size; + } + } + public int[] getAll(){ + int length = lib.size(),index = 0; + int []res = new int[length]; + Node p = head.next; + while(p!=null){ + res[index] = p.val; + index += 1; + p = p.next; + } + return res; + } + public void add(int e){ + int index = 0; + if(lib.contains(e)){ + Node p = head; + while(p.next!= null){ + if(p.next.val == e){ + Node newn = p.next; + p.next = newn.next; + newn.next = head.next; + head.next = newn; + break; + } + p = p.next; + } + }else{ + if(lib.size() == size){ + lib.add(e); + Node newn = new Node(e); + newn.next = head.next; + head.next = newn; + Node p = head; + while(p.next.next != null) + p = p.next; + Node deln = p.next; + lib.remove(deln.val); + p.next = null; + }else{ + Node newn = new Node(e); + newn.next = head.next; + head.next = newn; + lib.add(e); + } + } + } +} diff --git a/group12/247565311/structure/week5/LRUPageFrameTest.java b/group12/247565311/structure/week5/LRUPageFrameTest.java new file mode 100644 index 0000000000..cb795054d5 --- /dev/null +++ b/group12/247565311/structure/week5/LRUPageFrameTest.java @@ -0,0 +1,36 @@ +package structure. week5; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LRUPageFrameTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testAdd() { + LRUPageFrame lru = new LRUPageFrame(5); + lru.add(3); + lru.add(7); + lru.add(5); + lru.add(8); + lru.add(10); + Assert.assertArrayEquals(new int[]{10,8,5,7,3}, lru.getAll()); + lru.add(5); + lru.add(3); + Assert.assertArrayEquals(new int[]{3,5,10,8,7}, lru.getAll()); + lru.add(8); + lru.add(11); + Assert.assertArrayEquals(new int[]{11,8,3,5,10}, lru.getAll()); + } +} diff --git a/group12/247565311/structure/week6/StackUtil.java b/group12/247565311/structure/week6/StackUtil.java new file mode 100644 index 0000000000..9895f02f30 --- /dev/null +++ b/group12/247565311/structure/week6/StackUtil.java @@ -0,0 +1,133 @@ +package structure.week6; +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 + * 濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,pop,peek,isEmpty閿涳拷閸欘垯浜掓担璺ㄦ暏閸欙箑顦绘稉锟介嚋閺嶅牊娼垫潏鍛И + */ + public static void reverse(Stack s){ + if(s == null || s.isEmpty()) return; + int size = 0; + Stack s1 = new Stack(); + while(!s.isEmpty()){ + s1.push(s.pop()); + size += 1; + } + while(!s1.isEmpty()) + s.push(s1.pop()); + for(int i=0;ii) + s1.push(s.pop()); + s.push(integer); + while(s1.size()>0) + s.push(s1.pop()); + } + } + // 閫氳繃閫掑綊鍙互涓嶄娇鐢ㄥ爢鏍堝畬鎴愯繖涓�姛鑳� + public static void reverse2(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); + } + } + /** + * 閸掔娀娅庨弽鍫滆厬閻ㄥ嫭鐓囨稉顏勫帗缁憋拷濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,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()); + } + } + + /** + * 娴犲孩鐖ゆい璺哄絿瀵版en娑擃亜鍘撶槐锟�閸樼喐娼甸惃鍕垽娑擃厼鍘撶槐鐘辩箽閹镐椒绗夐崣锟� * 濞夈劍鍓伴敍姘涧閼虫垝濞囬悽鈯縯ack閻ㄥ嫬鐔�張顒佹惙娴f粣绱濋崡纭僽sh,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})")); + } + +} \ No newline at end of file diff --git a/group12/247565311/structure/week7/InfixExpr.java b/group12/247565311/structure/week7/InfixExpr.java new file mode 100644 index 0000000000..4fc4d13fbe --- /dev/null +++ b/group12/247565311/structure/week7/InfixExpr.java @@ -0,0 +1,99 @@ +package structure.week7; +// 姹傝В琛ㄨ揪寮忓瓧绗︿覆锛岄鍏堝皢琛ㄨ揪寮忓垱寤烘垚涓�5琛ㄨ揪寮忔爲锛岄渶瑕佹牴鎹繍绠楃鐨勪紭鍏堢骇鏉ュ垱寤� +public class InfixExpr { + String expr = null; + Element getElem = null; + public InfixExpr(String expr) { + this.expr = expr; + getElem = new Element(expr); + } + public float evaluate() throws Exception{ + Node node = new Node('\0',getElem.getNextNum()); + Node root = createNode(node); + return (float) getValue(root); + } + class Element{ + private int index; + private String str; + public Element(String _str){ + index = 0; + str = _str; + } + public double getNextNum(){ + double resl = 0,resr=0; + int fbits = 0; + char ch = str.charAt(index); + boolean hasp = false; + while(ch=='.' || (ch<='9' && '0'<=ch)){ + index += 1; + if(ch == '.') hasp = true; + else{ + if(hasp){ + fbits -= 1; + resr += (double)(ch-'0') * Math.pow(10,fbits); + }else{ + resl *= 10; + resl += (ch-'0'); + } + } + if(hasNext()) ch = str.charAt(index); + else break; + } + return resl+resr; + } + public char getNextOper(){ + if(hasNext()){ + char ch = str.charAt(index); + if((ch>='0' && '9'>=ch) || ch=='.') return '\0'; + else{ + index += 1; + return ch; + } + }else{ + return '\0'; + } + } + public boolean hasNext(){ + return index implements List { - private int size=0,offset=10; - private Object[] data = null; - public ArrayList(){ - data = new Object[offset]; - } - public ArrayList(int arg0){ - if(arg0<0) arg0=0; - size = arg0; - data = new Object[size]; - } - @Override - public void add(Object arg0) { - size += 1; - int leng = data.length; - if(size>leng){ - Object[] newdata = new Object[size + offset]; - for(int i=0;isize || 0leng){ - Object[] newdata = new Object[size + offset]; - for(int i=0;i arg0) { - if (arg0 == null) return false; - int leng = data.length,newobjnum = arg0.size(),lastsize=size; - size += newobjnum; - if(size>leng){ - Object[] newdata = new Object[size + offset]; - for(int i=0;i arg1) { - int newobjnum = arg1.size(),lastsize = size; - if(arg1 == null || arg0>size+1 || 0>arg0 || newobjnum==0) return false; - size += newobjnum; - int leng = data.length; - if(size>leng){ - Object[] newdata = new Object[size + offset]; - for(int i=0;i arg0) { - for(Object o:arg0){ - if(!this.contains(o)) return false; - } - return true; - } - - @Override - public E get(int arg0) { - if(arg0 >-1 && arg0-1;i--){ - if(this.data[i].equals(arg0)) return i; - } - return -1; - } - - public Iterator iterator() { - - return null; - } - - public boolean remove(Object arg0) { - for(int i=0;ithis.size-1) return null; - E res = (E)data[arg0]; - for(int i=arg0;i arg0) { - int toberemovednums = arg0.size(); - if(!this.containsAll(arg0)) return false; - int index=0; - for(int i=0;ithis.size-1) return null; - this.data[arg0] = arg1; - return arg1; - } - - @Override - public int size() { - return this.size; - } - - public List subList(int arg0, int arg1) { - if(arg0>=arg1 || arg0<0 || arg1>this.size-1) return null; - List res = new ArrayList(); - for(int i=arg0;i T[] toArray(T[] arg0) { - T[] res = (T[])(new Object[this.size]); - for(int i=0;i{ - public boolean hasNext(); - public E next(); -} diff --git a/group12/247565311/week1/LinkedList.java b/group12/247565311/week1/LinkedList.java deleted file mode 100644 index 0b74925cbe..0000000000 --- a/group12/247565311/week1/LinkedList.java +++ /dev/null @@ -1,242 +0,0 @@ -package week1; - -import java.util.Collection; - -public class LinkedList implements List { - private Node head = null; - private Node tail = null; - private int size = 0; - - public LinkedList(){ - head = new Node(null); - tail = new Node(null); - head.next = tail; - tail.ahead = head; - size = 0; - } - public LinkedList(int arg0){ - head = new Node(null); - tail = new Node(null); - head.next = tail; - tail.ahead = head; - size = 0; - } - public Object clone(){ - LinkedList clone = null; - try { - clone = (LinkedList)(super.clone()); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - clone.head = new Node(null); - clone.tail = new Node(null); - clone.size = 0; - for(Node x = head.next;x!=null;x = x.next){ - clone.add(x.val); - } - return clone; - } - @Override - public void add(Object val) { - Node n = new Node(val); - n.next = tail; - n.ahead = tail.ahead; - tail.ahead.next = n; - tail.ahead = n; - size += 1; - } - - @Override - public void add(int arg0, E arg1) { - if(arg0<0 || arg0>size) arg0=0; - Node n=new Node(arg1),p=head; - for(int i=0;i arg0) { - for(E o:arg0){ - this.add(o); - } - return true; - } - - public boolean addAll(int arg0, Collection arg1) { - for(E e:arg1){ - this.add(arg0,e); - arg0+=1; - } - return true; - } - - public void clear() { - head = new Node(null); - tail = new Node(null); - head.next = tail; - tail.ahead = head; - size = 0; - } - - public boolean contains(Object arg0) { - boolean flag = arg0==null; - Node n = head; - for(int i=0;i arg0) { - for(Object e:arg0){ - if(!this.contains(e)) return false; - } - return true; - } - - @Override - public E get(int arg0) { - E res = null; - if(arg0>-1 && arg0 < size){ - Node n = head; - for(int i=0;i iterator() { - - return null; - } - - public int lastIndexOf(Object arg0) { - boolean flag = arg0==null; - Node n = tail; - for(int i=size-1;i>-1;i--){ - n = n.ahead; - if(flag){ - if(n.val == null) return i; - }else{ - if(arg0.equals(n.val)) return i; - } - } - return -1; - } - - public boolean remove(Object arg0) { - Node n = head; - int index = this.indexOf(arg0); - if(index == -1) return false; - for(int i=0;isize-1) return null; - for(int i=0;i arg0) { - for(Object o:arg0){ - if(!this.remove(o)) return false; - } - return true; - } - - public boolean retainAll(Collection arg0) { - // ? - return false; - } - - public E set(int arg0, E arg1) { - if(arg0<0 || arg0>size-1) return null; - Node n=head; - for(int i=0;i T[] toArray(T[] arg0) { - T[]res = (T[]) new Object[size]; - Node n = head; - for(int i=0;i extends Iterator{ - public void add(Object o); - public void add(int index, E o); - public E get(int index); - public E remove(int index); - public int size(); -} diff --git a/group12/247565311/week1/Queue.java b/group12/247565311/week1/Queue.java deleted file mode 100644 index 78f25cb826..0000000000 --- a/group12/247565311/week1/Queue.java +++ /dev/null @@ -1,18 +0,0 @@ -package week1; -public class Queue { - private LinkedList data = new LinkedList(); - public void enQueue(E arg0){ - data.add(data.size(),arg0); - } - public E deQueue(){ - E res = data.get(0); - data.remove(0); - return res; - } - public int size(){ - return data.size(); - } - public boolean isEmpty(){ - return data.isEmpty(); - } -} diff --git a/group12/247565311/week1/Stack.java b/group12/247565311/week1/Stack.java deleted file mode 100644 index 5dcccc5fca..0000000000 --- a/group12/247565311/week1/Stack.java +++ /dev/null @@ -1,28 +0,0 @@ -package week1; - -import week1.List; - -public class Stack { - private ArrayList data = new ArrayList(); - public boolean isEmpty(){ - return data.isEmpty(); - } - public int size(){ - return data.size(); - } - public boolean push(E arg0){ - data.add(arg0); - return true; - } - public E pop(){ - if(this.isEmpty()) return null; - E res = data.get(data.size()-1); - data.remove(data.size()-1); - return res; - } - public E peek(){ - if(this.isEmpty()) return null; - E res = data.get(data.size()-1); - return res; - } -} diff --git a/group12/247565311/week2/ArrayUtil.java b/group12/247565311/week2/ArrayUtil.java deleted file mode 100644 index 00bab36625..0000000000 --- a/group12/247565311/week2/ArrayUtil.java +++ /dev/null @@ -1,206 +0,0 @@ -package week2; -import week1.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){ // time :O(n) - int leno = origin.length; - for(int i=0;i=len1){ - temparray[temp] = array2[p2]; - p2 += 1; - continue; - } - if(p2>=len2){ - temparray[temp] = array1[p1]; - p1 += 1; - continue; - } - if(array1[p1] > array2[p2]){ - temparray[temp] = array2[p2]; - p2 += 1; - }else{ - temparray[temp] = array1[p1]; - p1 += 1; - } - } - temp = 0; - for(int i=1;i data = new ArrayList(); - data.add(llast); - data.add(last); - while(last+llast li = new ArrayList(); - int cur = 2; - while(cur li = null,resli = new ArrayList(); - for(int i=6;i getAllElem(int arg0){ - ArrayList res = new ArrayList(); - for(int i=1;iparameters){ - if(actionName == null || parameters == null) return null; - List actions = null; - try { - File xmlfile = new File(System.getProperty("user.dir")+"\\bin\\week2\\struts.xml"); - Document doc = new SAXReader().read(xmlfile); - Element root = doc.getRootElement(); - actions = root.elements(); - } catch (DocumentException e) { - e.printStackTrace(); - } - - String className=""; - Element curActNode = null; - for(int i=0;i attrs = actions.get(i).attributes(); - for(int j=0;j class1 = null; - try { - class1 = Class.forName(className); - class1Instance = class1.newInstance(); - } catch (Exception e) { - e.printStackTrace(); - } - for(String key : parameters.keySet()){ - String methodName = "set"+(new StringBuilder()).append(Character.toUpperCase(key.charAt(0))).append(key.substring(1)).toString(); - Object methodPara=parameters.get(key); - try { - Method method =class1.getMethod(methodName, String.class); - method.invoke(class1Instance, methodPara); - } catch (Exception e) { - e.printStackTrace(); - } - } - Object exeResult = null; - try { - Method method =class1.getMethod("execute"); - exeResult = method.invoke(class1Instance); - } catch (Exception e) { - e.printStackTrace(); - } - - String jsp = null; - List results = curActNode.elements(); - for(int i=0;i attrs = results.get(i).attributes(); - for(int j=0;j para = new HashMap(); - view.setParameters(para); - - Field [] fields = class1.getDeclaredFields(); - for(int i=0;i 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"); //ԤIJһ - - 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/group12/247565311/week2/View.java b/group12/247565311/week2/View.java deleted file mode 100644 index 4f88ad3b84..0000000000 --- a/group12/247565311/week2/View.java +++ /dev/null @@ -1,24 +0,0 @@ -package week2; -import java.util.Map; -public class View { - private String jsp; - @SuppressWarnings("rawtypes") - private Map parameters; - - public String getJsp(){ - return jsp; - } - public View setJsp(String jsp){ - this.jsp = jsp; - return this; - } - @SuppressWarnings("rawtypes") - public Map getParameters(){ - return parameters; - } - @SuppressWarnings("rawtypes") - public View setParameters(Map parameters){ - this.parameters = parameters; - return this; - } -} diff --git a/group12/247565311/week2/struts.xml b/group12/247565311/week2/struts.xml deleted file mode 100644 index 234232d0b6..0000000000 --- a/group12/247565311/week2/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group12/247565311/week2_miniStruts/LoginAction.java b/group12/247565311/week2_miniStruts/LoginAction.java new file mode 100644 index 0000000000..f696180eeb --- /dev/null +++ b/group12/247565311/week2_miniStruts/LoginAction.java @@ -0,0 +1,30 @@ +package week2_miniStruts; + +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/group12/247565311/week2_miniStruts/Struts.java b/group12/247565311/week2_miniStruts/Struts.java new file mode 100644 index 0000000000..5ccadb610f --- /dev/null +++ b/group12/247565311/week2_miniStruts/Struts.java @@ -0,0 +1,101 @@ +package week2_miniStruts; +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +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 { + @SuppressWarnings("unchecked") + public static View runAction(String actionName,Mapparameters){ + if(actionName == null || parameters == null) return null; + List actions = null; + try { + File xmlfile = new File(System.getProperty("user.dir")+"\\bin\\week2\\struts.xml"); + Document doc = new SAXReader().read(xmlfile); + Element root = doc.getRootElement(); + actions = root.elements(); + } catch (DocumentException e) { + e.printStackTrace(); + } + + String className=""; + Element curActNode = null; + for(int i=0;i attrs = actions.get(i).attributes(); + for(int j=0;j class1 = null; + try { + class1 = Class.forName(className); + class1Instance = class1.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + } + for(String key : parameters.keySet()){ + String methodName = "set"+(new StringBuilder()).append(Character.toUpperCase(key.charAt(0))).append(key.substring(1)).toString(); + Object methodPara=parameters.get(key); + try { + Method method =class1.getMethod(methodName, String.class); + method.invoke(class1Instance, methodPara); + } catch (Exception e) { + e.printStackTrace(); + } + } + Object exeResult = null; + try { + Method method =class1.getMethod("execute"); + exeResult = method.invoke(class1Instance); + } catch (Exception e) { + e.printStackTrace(); + } + + String jsp = null; + List results = curActNode.elements(); + for(int i=0;i attrs = results.get(i).attributes(); + for(int j=0;j para = new HashMap(); + view.setParameters(para); + + Field [] fields = class1.getDeclaredFields(); + for(int i=0;i 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"); //ԤIJһ + + 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/group12/247565311/week2_miniStruts/View.java b/group12/247565311/week2_miniStruts/View.java new file mode 100644 index 0000000000..3d69a03600 --- /dev/null +++ b/group12/247565311/week2_miniStruts/View.java @@ -0,0 +1,24 @@ +package week2_miniStruts; +import java.util.Map; +public class View { + private String jsp; + @SuppressWarnings("rawtypes") + private Map parameters; + + public String getJsp(){ + return jsp; + } + public View setJsp(String jsp){ + this.jsp = jsp; + return this; + } + @SuppressWarnings("rawtypes") + public Map getParameters(){ + return parameters; + } + @SuppressWarnings("rawtypes") + public View setParameters(Map parameters){ + this.parameters = parameters; + return this; + } +} diff --git a/group12/247565311/week3/DownloadThread.java b/group12/247565311/week3/DownloadThread.java deleted file mode 100644 index 2670bef00b..0000000000 --- a/group12/247565311/week3/DownloadThread.java +++ /dev/null @@ -1,61 +0,0 @@ -package week3; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; - -import week3.api.Connection; - -public class DownloadThread extends Thread{ - Connection conn; - CyclicBarrier barrier; - int startPos; - int endPos; - String path = ""; - int step = 1024*200; // ÿ200kдһļ - public DownloadThread(CyclicBarrier _barrier, Connection conn, int startPos, int endPos,String filepath){ - this.conn = conn; - this.startPos = startPos; - this.endPos = endPos; - this.path = filepath; - this.barrier = _barrier; - } - public void run(){ - // ȡصֽ飬дļעһ̳߳ - // ֻдһֵļ - - // connectȡֽ飬ûֽˣͱʾⲿ - // filepathдļ - if(conn == null) return; - int curEndPos = startPos; - while(curEndPos endPos) - curEndPos = endPos; - try { - byte[] data = conn.read(startPos, curEndPos); - RandomAccessFile files = new RandomAccessFile(path,"rw"); - files.seek(startPos); - files.write(data); - files.close(); - System.out.println("startPos"+startPos + ", length:"+data.length); - } catch (IOException e) { - e.printStackTrace(); - } - } - conn.close(); - try { - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - e.printStackTrace(); - } - } -} diff --git a/group12/247565311/week3/FileDownloader.java b/group12/247565311/week3/FileDownloader.java deleted file mode 100644 index 1a426c3682..0000000000 --- a/group12/247565311/week3/FileDownloader.java +++ /dev/null @@ -1,77 +0,0 @@ -package week3; -import java.util.concurrent.CyclicBarrier; -import java.io.IOException; -import java.io.RandomAccessFile; - -import week3.api.Connection; -import week3.api.ConnectionException; -import week3.api.ConnectionManager; -import week3.api.DownloadListener; -import week3.impl.ConnectionManagerImpl; - -public class FileDownloader { - private int MaxThreadNum = 4; - private String url = null,path=null; - DownloadListener listener = null; - private ConnectionManager cm = new ConnectionManagerImpl(); - - public FileDownloader(String weburl,String localpath) { - this.url = weburl; - this.path = localpath; - } - - public void execute() throws InterruptedException{ - // 在这里实现你的代码, 注意: 需要用多线程实现下载 - // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 - // (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; - CyclicBarrier barr= new CyclicBarrier(MaxThreadNum,new Runnable(){ - public void run(){ - listener.notifyFinished(); - } - }); - try { - conn = cm.open(this.url); - int length = conn.getContentLength(); - // 在这里创建出一个同样大小的空文件, 路径是path - RandomAccessFile tarfile = new RandomAccessFile(path,"rw"); - tarfile.setLength(length); - tarfile.close(); - Thread[] threads = new Thread[4]; - threads[0] = new DownloadThread(barr,cm.open(this.url),0,length/4,path); - threads[1] = new DownloadThread(barr,cm.open(this.url),length/4,length/2,path); - threads[2] = new DownloadThread(barr,cm.open(this.url),length/2,3*length/4,path); - threads[3] = new DownloadThread(barr,cm.open(this.url),3*length/4,length,path); - for(int i=0;i<4;i++) - threads[i].start(); - } catch (ConnectionException | 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; - } - public double getDownPercent(){ - return 0.0; - } -} diff --git a/group12/247565311/week3/FileDownloaderTest.java b/group12/247565311/week3/FileDownloaderTest.java deleted file mode 100644 index 3c729218d3..0000000000 --- a/group12/247565311/week3/FileDownloaderTest.java +++ /dev/null @@ -1,50 +0,0 @@ -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://music.163.com/api/pc/download/latest"; - String path = "D:\\hellp.exe"; - FileDownloader downloader = new FileDownloader(url,path); - ConnectionManager cm = new ConnectionManagerImpl(); - downloader.setConnectionManager(cm); - downloader.setListener(new DownloadListener() { - @Override - public void notifyFinished() { - downloadFinished = true; - } - }); - double time = 0; - try { - downloader.execute(); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - while (!downloadFinished) { - try { - Thread.sleep(100);//休眠0.1秒 - - time += 1; - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!耗时:"+time/10.0+" 秒。"); - } -} diff --git a/group12/247565311/week3/LinkedList.java b/group12/247565311/week3/LinkedList.java deleted file mode 100644 index dbf9465386..0000000000 --- a/group12/247565311/week3/LinkedList.java +++ /dev/null @@ -1,252 +0,0 @@ -package week3; - - -import java.util.NoSuchElementException; - -import week1.Iterator; -import week1.List; - -public class LinkedList implements List { - private Node head = new Node(); - private int size = 0; - private void checkAddIndex(int index){ - if(index > size || index<0) throw new IndexOutOfBoundsException("Index:"+index+", Size:"+size); - } - private void checkGetIndex(int index){ - if(index >= size || index<0) throw new IndexOutOfBoundsException("Index:"+index+", Size:"+size); - } - public void add(Object o){ - Node newNode = new Node(o),p = head; - while(p.next!=null) - p = p.next; - p.next = newNode; - size += 1; - } - /** - * - * */ - public void add(int index , Object o){ - checkAddIndex(index); - Node p = head; - for(int i=0;i7->10 , úΪ 10->7->3 - */ - public void reverse(){ - Node rhead = new Node(),p=head; - for(int i=0;i5->7->8 , ɾԺֵΪ 7->8 - * list = 2->5->7->8->10 ,ɾԺֵΪ7,8,10 - - */ - public void removeFirstHalf(){ - int numToRemove = 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 []res = new int[list.size()]; - Node p = head.next,q = list.head.next; - int lenl = list.size(),index=0; - for(int i=0;imax) return; // Ŀ (min,max) - Node p = head; - while(p.next != null && ((Integer)p.next.data).intValue()<=min) // ɵԪ - p = p.next; - while(p.next != null && ((Integer)p.next.data).intValue()0)output.write(res,0,len); - else break; - } - return Arrays.copyOf(output.toByteArray(), endPos-startPos); - } - } catch (IOException e) { - e.printStackTrace(); - } - if(conn!=null) conn.disconnect(); - return res; - } - - @Override - public int getContentLength() { - try{ - URLConnection con = url.openConnection(); - return con.getContentLength(); - }catch(Exception e){ - e.printStackTrace(); - } - return -1; - } - - @Override - public void close() { - } -} diff --git a/group12/247565311/week3/impl/ConnectionManagerImpl.java b/group12/247565311/week3/impl/ConnectionManagerImpl.java deleted file mode 100644 index b4a7cf381f..0000000000 --- a/group12/247565311/week3/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package week3.impl; - -import java.io.IOException; -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 { - URL urllink = null; - ConnectionImpl conImpl = null; - @Override - public Connection open(String url) throws ConnectionException { - return new ConnectionImpl(url); - } -} diff --git a/group12/247565311/week3_fileDownloader/DownloadThread.java b/group12/247565311/week3_fileDownloader/DownloadThread.java new file mode 100644 index 0000000000..11d228b652 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/DownloadThread.java @@ -0,0 +1,55 @@ +package week3_fileDownloader; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +import week3_fileDownloader.api.Connection; + +public class DownloadThread extends Thread{ + Connection conn; + CyclicBarrier barrier; + int startPos; + int endPos; + String path = ""; + int step = 1024*200; // ÿ200kдһļ + public DownloadThread(CyclicBarrier _barrier, Connection conn, int startPos, int endPos,String filepath){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.path = filepath; + this.barrier = _barrier; + } + public void run(){ + // ȡصֽ飬дļעһ̳߳ + // ֻдһֵļ + + // connectȡֽ飬ûֽˣͱʾⲿ + // filepathдļ + if(conn == null) return; + int curEndPos = startPos; + while(curEndPos endPos) + curEndPos = endPos; + try { + byte[] data = conn.read(startPos, curEndPos); + RandomAccessFile files = new RandomAccessFile(path,"rw"); + files.seek(startPos); + files.write(data); + files.close(); + System.out.println("startPos"+startPos + ", length:"+data.length); + } catch (IOException e) { + e.printStackTrace(); + } + } + conn.close(); + try { + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + e.printStackTrace(); + } + } +} diff --git a/group12/247565311/week3_fileDownloader/FileDownloader.java b/group12/247565311/week3_fileDownloader/FileDownloader.java new file mode 100644 index 0000000000..2c23ac39c0 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/FileDownloader.java @@ -0,0 +1,78 @@ +package week3_fileDownloader; + +import java.util.concurrent.CyclicBarrier; +import java.io.IOException; +import java.io.RandomAccessFile; + +import week3_fileDownloader.api.Connection; +import week3_fileDownloader.api.ConnectionException; +import week3_fileDownloader.api.ConnectionManager; +import week3_fileDownloader.api.DownloadListener; +import week3_fileDownloader.impl.ConnectionManagerImpl; + +public class FileDownloader { + private int MaxThreadNum = 4; + private String url = null,path=null; + DownloadListener listener = null; + private ConnectionManager cm = new ConnectionManagerImpl(); + + public FileDownloader(String weburl,String localpath) { + this.url = weburl; + this.path = localpath; + } + + public void execute() throws InterruptedException{ + // 鍦ㄨ繖閲屽疄鐜颁綘鐨勪唬鐮侊紝 娉ㄦ剰锛�闇�鐢ㄥ绾跨▼瀹炵幇涓嬭浇 + // 杩欎釜绫讳緷璧栦簬鍏朵粬鍑犱釜鎺ュ彛, 浣犻渶瑕佸啓杩欏嚑涓帴鍙g殑瀹炵幇浠g爜 + // (1) ConnectionManager , 鍙互鎵撳紑涓�釜杩炴帴锛岄�杩嘋onnection鍙互璇诲彇鍏朵腑鐨勪竴娈碉紙鐢╯tartPos, endPos鏉ユ寚瀹氾級 + // (2) DownloadListener, 鐢变簬鏄绾跨▼涓嬭浇锛�璋冪敤杩欎釜绫荤殑瀹㈡埛绔笉鐭ラ亾浠�箞鏃跺�缁撴潫锛屾墍浠ヤ綘闇�瀹炵幇褰撴墍鏈� + // 绾跨▼閮芥墽琛屽畬浠ュ悗锛�璋冪敤listener鐨刵otifiedFinished鏂规硶锛�杩欐牱瀹㈡埛绔氨鑳芥敹鍒伴�鐭ャ� + // 鍏蜂綋鐨勫疄鐜版�璺細 + // 1. 闇�璋冪敤ConnectionManager鐨刼pen鏂规硶鎵撳紑杩炴帴锛�鐒跺悗閫氳繃Connection.getContentLength鏂规硶鑾峰緱鏂囦欢鐨勯暱搴� + // 2. 鑷冲皯鍚姩3涓嚎绋嬩笅杞斤紝 娉ㄦ剰姣忎釜绾跨▼闇�鍏堣皟鐢–onnectionManager鐨刼pen鏂规硶 + // 鐒跺悗璋冪敤read鏂规硶锛�read鏂规硶涓湁璇诲彇鏂囦欢鐨勫紑濮嬩綅缃拰缁撴潫浣嶇疆鐨勫弬鏁帮紝 杩斿洖鍊兼槸byte[]鏁扮粍 + // 3. 鎶奲yte鏁扮粍鍐欏叆鍒版枃浠朵腑 + // 4. 鎵�湁鐨勭嚎绋嬮兘涓嬭浇瀹屾垚浠ュ悗锛�闇�璋冪敤listener鐨刵otifiedFinished鏂规硶 + + // 涓嬮潰鐨勪唬鐮佹槸绀轰緥浠g爜锛�涔熷氨鏄鍙湁涓�釜绾跨▼锛�浣犻渶瑕佹敼閫犳垚澶氱嚎绋嬬殑銆� + Connection conn = null; + CyclicBarrier barr= new CyclicBarrier(MaxThreadNum,new Runnable(){ + public void run(){ + listener.notifyFinished(); + } + }); + try { + conn = cm.open(this.url); + int length = conn.getContentLength(); + // 鍦ㄨ繖閲屽垱寤哄嚭涓�釜鍚屾牱澶у皬鐨勭┖鏂囦欢锛�璺緞鏄痯ath + RandomAccessFile tarfile = new RandomAccessFile(path,"rw"); + tarfile.setLength(length); + tarfile.close(); + Thread[] threads = new Thread[4]; + threads[0] = new DownloadThread(barr,cm.open(this.url),0,length/4,path); + threads[1] = new DownloadThread(barr,cm.open(this.url),length/4,length/2,path); + threads[2] = new DownloadThread(barr,cm.open(this.url),length/2,3*length/4,path); + threads[3] = new DownloadThread(barr,cm.open(this.url),3*length/4,length,path); + for(int i=0;i<4;i++) + threads[i].start(); + } catch (ConnectionException | 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; + } + public double getDownPercent(){ + return 0.0; + } +} diff --git a/group12/247565311/week3_fileDownloader/FileDownloaderTest.java b/group12/247565311/week3_fileDownloader/FileDownloaderTest.java new file mode 100644 index 0000000000..3488fd5245 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/FileDownloaderTest.java @@ -0,0 +1,50 @@ +package week3_fileDownloader; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import week3_fileDownloader.api.ConnectionManager; +import week3_fileDownloader.api.DownloadListener; +import week3_fileDownloader.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://music.163.com/api/pc/download/latest"; + String path = "D:\\hellp.exe"; + FileDownloader downloader = new FileDownloader(url,path); + ConnectionManager cm = new ConnectionManagerImpl(); + downloader.setConnectionManager(cm); + downloader.setListener(new DownloadListener() { + @Override + public void notifyFinished() { + downloadFinished = true; + } + }); + double time = 0; + try { + downloader.execute(); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + while (!downloadFinished) { + try { + Thread.sleep(100);//浼戠湢0.1绉� + + time += 1; + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + System.out.println("涓嬭浇瀹屾垚锛佽�鏃讹細"+time/10.0+" 绉掋�"); + } +} diff --git a/group12/247565311/week3_fileDownloader/api/Connection.java b/group12/247565311/week3_fileDownloader/api/Connection.java new file mode 100644 index 0000000000..5100870e1f --- /dev/null +++ b/group12/247565311/week3_fileDownloader/api/Connection.java @@ -0,0 +1,23 @@ +package week3_fileDownloader.api; + +import java.io.IOException; +import java.net.HttpURLConnection; + +public interface Connection{ + /** + * 缁欏畾寮�鍜岀粨鏉熶綅缃紝 璇诲彇鏁版嵁锛�杩斿洖鍊兼槸瀛楄妭鏁扮粍 + * @param startPos 寮�浣嶇疆锛�浠�寮� + * @param endPos 缁撴潫浣嶇疆 + * @return + */ + public byte[] read(int startPos,int endPos) throws IOException; + /** + * 寰楀埌鏁版嵁鍐呭鐨勯暱搴� * @return + */ + public int getContentLength(); + + /** + * 鍏抽棴杩炴帴 + */ + public void close(); +} diff --git a/group12/247565311/week3_fileDownloader/api/ConnectionException.java b/group12/247565311/week3_fileDownloader/api/ConnectionException.java new file mode 100644 index 0000000000..4a9cfd8aa6 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/api/ConnectionException.java @@ -0,0 +1,5 @@ +package week3_fileDownloader.api; + +public class ConnectionException extends Exception { + private String exceptionstr = ""; +} diff --git a/group12/247565311/week3_fileDownloader/api/ConnectionManager.java b/group12/247565311/week3_fileDownloader/api/ConnectionManager.java new file mode 100644 index 0000000000..f917cde2e9 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package week3_fileDownloader.api; + +public interface ConnectionManager { + /** + * 缁欏畾涓�釜url , 鎵撳紑涓�釜杩炴帴 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group12/247565311/week3_fileDownloader/api/DownloadListener.java b/group12/247565311/week3_fileDownloader/api/DownloadListener.java new file mode 100644 index 0000000000..27fc35452f --- /dev/null +++ b/group12/247565311/week3_fileDownloader/api/DownloadListener.java @@ -0,0 +1,5 @@ +package week3_fileDownloader.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group12/247565311/week3_fileDownloader/impl/ConnectionImpl.java b/group12/247565311/week3_fileDownloader/impl/ConnectionImpl.java new file mode 100644 index 0000000000..78f393e07e --- /dev/null +++ b/group12/247565311/week3_fileDownloader/impl/ConnectionImpl.java @@ -0,0 +1,65 @@ +package week3_fileDownloader.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 week3_fileDownloader.api.Connection; + +public class ConnectionImpl implements Connection{ + URL url = null; + public ConnectionImpl(String str){ + try { + url = new URL(str); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + // Ҫִأȡֽ + // ฺ򿪡ر + @Override + public byte[] read(int startPos, int endPos) { + HttpURLConnection conn = null; + byte[]res = null; + try { + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("Range","bytes="+startPos+"-"+endPos); + int responcode = conn.getResponseCode(); + if(200 < responcode && responcode < 300){ + InputStream input = conn.getInputStream(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + res = new byte[2048]; + while(output.size()0)output.write(res,0,len); + else break; + } + return Arrays.copyOf(output.toByteArray(), endPos-startPos); + } + } catch (IOException e) { + e.printStackTrace(); + } + if(conn!=null) conn.disconnect(); + return res; + } + + @Override + public int getContentLength() { + try{ + URLConnection con = url.openConnection(); + return con.getContentLength(); + }catch(Exception e){ + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + } +} diff --git a/group12/247565311/week3_fileDownloader/impl/ConnectionManagerImpl.java b/group12/247565311/week3_fileDownloader/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..7aab7eb651 --- /dev/null +++ b/group12/247565311/week3_fileDownloader/impl/ConnectionManagerImpl.java @@ -0,0 +1,18 @@ +package week3_fileDownloader.impl; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +import week3_fileDownloader.api.Connection; +import week3_fileDownloader.api.ConnectionException; +import week3_fileDownloader.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + URL urllink = null; + ConnectionImpl conImpl = null; + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } +} diff --git a/group12/247565311/week5/ClassFileLoader.java b/group12/247565311/week5/ClassFileLoader.java deleted file mode 100644 index fc5e920f19..0000000000 --- a/group12/247565311/week5/ClassFileLoader.java +++ /dev/null @@ -1,63 +0,0 @@ -package week5; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -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) throws Exception { - for(String s:clzPaths){ - String filename = s+className+".class"; - File file = new File(filename); - if(file.exists())return loadClassFile(filename); - } - return null; - } - - private byte[] loadClassFile(String clzFileName) throws Exception { - File file = new File(clzFileName); - long filelength = file.length(); - byte[]res = null; - if(filelength>Integer.MAX_VALUE)throw new IOException("ļ"); - try { - FileInputStream fileinput = new FileInputStream(file); - res = new byte[(int) filelength]; - int offset=0,length=0; - while(offset-1)) - offset += length; - fileinput.close(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - return res; - } - - public void addClassPath(String path) { - clzPaths.add(path); - } - - public String getClassPath_V1(){ - String res = ""; - int size = clzPaths.size(); - for(int i=0;i lib = new HashSet(); - class Node{ - int val; - Node next; - public Node(int _val){ - val = _val; - next = null; - } - } - public LRU(int _size){ - if(_size>0) { - this.size = _size; - } - } - public int[] getAll(){ - int length = lib.size(),index = 0; - int []res = new int[length]; - Node p = head.next; - while(p!=null){ - res[index] = p.val; - index += 1; - p = p.next; - } - return res; - } - public void add(int e){ - int index = 0; - if(lib.contains(e)){ - Node p = head; - while(p.next!= null){ - if(p.next.val == e){ - Node newn = p.next; - p.next = newn.next; - newn.next = head.next; - head.next = newn; - break; - } - p = p.next; - } - }else{ - if(lib.size() == size){ - lib.add(e); - Node newn = new Node(e); - newn.next = head.next; - head.next = newn; - Node p = head; - while(p.next.next != null) - p = p.next; - Node deln = p.next; - lib.remove(deln.val); - p.next = null; - }else{ - Node newn = new Node(e); - newn.next = head.next; - head.next = newn; - lib.add(e); - } - } - } -} diff --git a/group12/247565311/week5/LRUTest.java b/group12/247565311/week5/LRUTest.java deleted file mode 100644 index 0ee0d95309..0000000000 --- a/group12/247565311/week5/LRUTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package week5; - -import static org.junit.Assert.*; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class LRUTest { - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testAdd() { - LRU lru = new LRU(5); - lru.add(3); - lru.add(7); - lru.add(5); - lru.add(8); - lru.add(10); - Assert.assertArrayEquals(new int[]{10,8,5,7,3}, lru.getAll()); - lru.add(5); - lru.add(3); - Assert.assertArrayEquals(new int[]{3,5,10,8,7}, lru.getAll()); - lru.add(8); - lru.add(11); - Assert.assertArrayEquals(new int[]{11,8,3,5,10}, lru.getAll()); - } -} diff --git a/group12/247565311/week567_miniJVM/attr/AttributeInfo.java b/group12/247565311/week567_miniJVM/attr/AttributeInfo.java new file mode 100644 index 0000000000..e97ebe0065 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/AttributeInfo.java @@ -0,0 +1,24 @@ +package week567_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/group12/247565311/week567_miniJVM/attr/CodeAttr.java b/group12/247565311/week567_miniJVM/attr/CodeAttr.java new file mode 100644 index 0000000000..b32d6aada9 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/CodeAttr.java @@ -0,0 +1,63 @@ + + + +package week567_miniJVM.attr; + +import week567_miniJVM.clz.ClassFile; +import week567_miniJVM.constant.ConstantPool; +import week567_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){ + + + return null; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} + + + + diff --git a/group12/247565311/week567_miniJVM/attr/LineNumberTable.java b/group12/247565311/week567_miniJVM/attr/LineNumberTable.java new file mode 100644 index 0000000000..1160f1b274 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/LineNumberTable.java @@ -0,0 +1,51 @@ + +package week567_miniJVM.attr; + +import java.util.ArrayList; +import java.util.List; + +import week567_miniJVM.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/group12/247565311/week567_miniJVM/attr/LocalVariableItem.java b/group12/247565311/week567_miniJVM/attr/LocalVariableItem.java new file mode 100644 index 0000000000..5ce8ad8810 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/LocalVariableItem.java @@ -0,0 +1,47 @@ + +package week567_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/group12/247565311/week567_miniJVM/attr/LocalVariableTable.java b/group12/247565311/week567_miniJVM/attr/LocalVariableTable.java new file mode 100644 index 0000000000..c8dbf11b70 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/LocalVariableTable.java @@ -0,0 +1,37 @@ + + +package week567_miniJVM.attr; + + +import java.util.ArrayList; +import java.util.List; + +import week567_miniJVM.constant.ConstantPool; + +import week567_miniJVM.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/group12/247565311/week567_miniJVM/attr/StackMapTable.java b/group12/247565311/week567_miniJVM/attr/StackMapTable.java new file mode 100644 index 0000000000..c6b72f2655 --- /dev/null +++ b/group12/247565311/week567_miniJVM/attr/StackMapTable.java @@ -0,0 +1,44 @@ + +package week567_miniJVM.attr; + + +import week567_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); + + //鍚庨潰鐨凷tackMapTable澶繃澶嶆潅锛�涓嶅啀澶勭悊锛�鍙妸鍘熷鐨勪唬鐮佽杩涙潵淇濆瓨 + String code = iter.nextUxToHexString(len); + t.setOriginalCode(code); + + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} + + + + + + + + + + + + + diff --git a/group12/247565311/week567_miniJVM/clz/AccessFlag.java b/group12/247565311/week567_miniJVM/clz/AccessFlag.java new file mode 100644 index 0000000000..cb28fbe259 --- /dev/null +++ b/group12/247565311/week567_miniJVM/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package week567_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/group12/247565311/week567_miniJVM/clz/ClassFile.java b/group12/247565311/week567_miniJVM/clz/ClassFile.java new file mode 100644 index 0000000000..91226364b8 --- /dev/null +++ b/group12/247565311/week567_miniJVM/clz/ClassFile.java @@ -0,0 +1,84 @@ +package week567_miniJVM.clz; + +import week567_miniJVM.constant.ClassInfo; +import week567_miniJVM.constant.ConstantPool; +import week567_miniJVM.field.Field; +import week567_miniJVM.method.Method; +import structure.week1.ArrayList; + +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(); + } + public ArrayList getMethods() { + return null; + } + public ArrayList getFields() { + return null; + } +} diff --git a/group12/247565311/week567_miniJVM/clz/ClassIndex.java b/group12/247565311/week567_miniJVM/clz/ClassIndex.java new file mode 100644 index 0000000000..77118cafa6 --- /dev/null +++ b/group12/247565311/week567_miniJVM/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package week567_miniJVM.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/group12/247565311/week567_miniJVM/constant/ClassInfo.java b/group12/247565311/week567_miniJVM/constant/ClassInfo.java new file mode 100644 index 0000000000..77aa730b16 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package week567_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(); + } +} diff --git a/group12/247565311/week567_miniJVM/constant/ConstantInfo.java b/group12/247565311/week567_miniJVM/constant/ConstantInfo.java new file mode 100644 index 0000000000..7277bd18c4 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package week567_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); + } + +} diff --git a/group12/247565311/week567_miniJVM/constant/ConstantPool.java b/group12/247565311/week567_miniJVM/constant/ConstantPool.java new file mode 100644 index 0000000000..fb35f6c253 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package week567_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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group12/247565311/week567_miniJVM/constant/FieldRefInfo.java b/group12/247565311/week567_miniJVM/constant/FieldRefInfo.java new file mode 100644 index 0000000000..20e7d91e67 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package week567_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(); + } +} diff --git a/group12/247565311/week567_miniJVM/constant/MethodRefInfo.java b/group12/247565311/week567_miniJVM/constant/MethodRefInfo.java new file mode 100644 index 0000000000..82b29c7446 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package week567_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(); + } + + + +} diff --git a/group12/247565311/week567_miniJVM/constant/NameAndTypeInfo.java b/group12/247565311/week567_miniJVM/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..3a87554806 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package week567_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()+")"; + } +} diff --git a/group12/247565311/week567_miniJVM/constant/NullConstantInfo.java b/group12/247565311/week567_miniJVM/constant/NullConstantInfo.java new file mode 100644 index 0000000000..1b9ed25aba --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package week567_miniJVM.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group12/247565311/week567_miniJVM/constant/StringInfo.java b/group12/247565311/week567_miniJVM/constant/StringInfo.java new file mode 100644 index 0000000000..7a8e8da135 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/StringInfo.java @@ -0,0 +1,26 @@ +package week567_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); + } + +} diff --git a/group12/247565311/week567_miniJVM/constant/UTF8Info.java b/group12/247565311/week567_miniJVM/constant/UTF8Info.java new file mode 100644 index 0000000000..ac2341bda9 --- /dev/null +++ b/group12/247565311/week567_miniJVM/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package week567_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; + } + + + +} diff --git a/group12/247565311/week567_miniJVM/field/Field.java b/group12/247565311/week567_miniJVM/field/Field.java new file mode 100644 index 0000000000..47eac5a308 --- /dev/null +++ b/group12/247565311/week567_miniJVM/field/Field.java @@ -0,0 +1,33 @@ +package week567_miniJVM.field; + +import week567_miniJVM.constant.ConstantPool; +import week567_miniJVM.constant.UTF8Info; +import week567_miniJVM.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/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java b/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..d38345b3fe --- /dev/null +++ b/group12/247565311/week567_miniJVM/loader/ByteCodeIterator.java @@ -0,0 +1,20 @@ +package week567_miniJVM.loader; + +public class ByteCodeIterator { + + public int nextU2ToInt() { + // TODO Զɵķ + return 0; + } + + public int nextU4ToInt() { + // TODO Զɵķ + return 0; + } + + public String nextUxToHexString(int len) { + // TODO Զɵķ + return null; + } + +} diff --git a/group12/247565311/week567_miniJVM/loader/ClassFileLoader.java b/group12/247565311/week567_miniJVM/loader/ClassFileLoader.java new file mode 100644 index 0000000000..89c66a8197 --- /dev/null +++ b/group12/247565311/week567_miniJVM/loader/ClassFileLoader.java @@ -0,0 +1,59 @@ +package week567_miniJVM.loader; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import week567_miniJVM.clz.ClassFile; + +public class ClassFileLoader { + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) throws Exception { + for(String s:clzPaths){ + String filename = s+className+".class"; + File file = new File(filename); + if(file.exists())return loadClassFile(filename); + } + return null; + } + public ClassFile loadClass(String className){ + return null; + } + private byte[] loadClassFile(String clzFileName) throws Exception { + File file = new File(clzFileName); + long filelength = file.length(); + byte[]res = null; + if(filelength>Integer.MAX_VALUE)throw new IOException("ļ"); + try { + FileInputStream fileinput = new FileInputStream(file); + res = new byte[(int) filelength]; + int offset=0,length=0; + while(offset-1)) + offset += length; + fileinput.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return res; + } + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + public String getClassPath(){ + String res = ""; + int size = clzPaths.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()); + } + /** + * miniJVM第三次作业测试用例 + */ + @Test + public void testReadFields(){ + ArrayList 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(){ + ArrayList 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/group12/247565311/week567_miniJVM/test/EmployeeV1.java b/group12/247565311/week567_miniJVM/test/EmployeeV1.java new file mode 100644 index 0000000000..b9855461ae --- /dev/null +++ b/group12/247565311/week567_miniJVM/test/EmployeeV1.java @@ -0,0 +1,5 @@ +package week567_miniJVM.test; + +public class EmployeeV1 { + +} diff --git a/group12/247565311/week567_miniJVM/util/Util.java b/group12/247565311/week567_miniJVM/util/Util.java new file mode 100644 index 0000000000..c10eaee6f2 --- /dev/null +++ b/group12/247565311/week567_miniJVM/util/Util.java @@ -0,0 +1,24 @@ +package week567_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 - - - - - - - - + + + + + + + + diff --git a/group12/382266293/coding/basic/collection/concrete/ArrayList.java b/group12/382266293/coding/basic/collection/concrete/ArrayList.java index 3eeca56fee..71accca366 100644 --- a/group12/382266293/coding/basic/collection/concrete/ArrayList.java +++ b/group12/382266293/coding/basic/collection/concrete/ArrayList.java @@ -70,6 +70,7 @@ public void addLast(E e) { } public E removeLast() { + checkIndex(size); return elements[--size]; } diff --git a/group12/382266293/coding/basic/linklist/LRUPageFrame.java b/group12/382266293/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..31b22dc26b --- /dev/null +++ b/group12/382266293/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,163 @@ +package linklist; + +/** + * 用双向链表实现LRU算法 + * + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node(int pageNum) { + this.pageNum = pageNum; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + pageNum; + return result; + } + + @Override + public String toString() { + return "Node [pageNum=" + pageNum + "]"; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Node other = (Node) obj; + if (pageNum != other.pageNum) + return false; + return true; + } + + } + + private int capacity; + + private Node first;// 链表头 + private Node last;// 链表尾 + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + private int size; + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + if (size < this.capacity) { + addNode(pageNum); + return; + } + + Node p = findNode(pageNum); + if (null == p) { + p = new Node(pageNum); + p.next = first; + first.prev = p; + first = p; + moveLastPoint(); + return; + } + + if (p == first) { + return; + } + + if (p == last) { + p.next = first; + first.prev = p; + first = p; + moveLastPoint(); + return; + } + + movePtoFirst(p); + + } + + private void moveLastPoint() { + last = last.prev; + last.next = null; + } + + private void movePtoFirst(Node p) { + p.prev.next = p.next; + p.next.prev = p.prev; + first.prev = p; + p.next = first; + first = p; + } + + private void addNode(int pageNum) { + Node node = new Node(pageNum); + if (null == first) { + first = node; + size++; + return; + } + + node.next = first; + first.prev = node; + first = node; + size++; + + if (null == last) { + last = node.next; + return; + } + + } + + private Node findNode(int pageNum) { + Node node = first; + while (null != node) { + if (node.pageNum != pageNum) { + node = node.next; + } else { + return node; + } + } + return null; + } + + public static void main(String[] args) { + + } + + 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/group12/382266293/coding/basic/linklist/LRUPageFrameTest.java b/group12/382266293/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7745d31569 --- /dev/null +++ b/group12/382266293/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,32 @@ +package linklist; + +import org.junit.Assert; + +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(4); + frame.access(7); + frame.access(0); + frame.access(1); + frame.access(9); + Assert.assertEquals("9,1,0,7", frame.toString()); + frame.access(2); + Assert.assertEquals("2,9,1,0", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,9,1", frame.toString()); + frame.access(0); + Assert.assertEquals("0,2,9,1", frame.toString()); + frame.access(3); + Assert.assertEquals("3,0,2,9", frame.toString()); + frame.access(0); + Assert.assertEquals("0,3,2,9", frame.toString()); + frame.access(4); + Assert.assertEquals("4,0,3,2", frame.toString()); + } + +} diff --git a/group12/382266293/coding/basic/stack/StackUtil.java b/group12/382266293/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..706bcd7033 --- /dev/null +++ b/group12/382266293/coding/basic/stack/StackUtil.java @@ -0,0 +1,140 @@ +package stack; + +import static org.junit.Assert.assertEquals; + +import java.util.Objects; +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 stack) { + if (stack.isEmpty()) { + return; + } + int i = getAndRemoveLastElement(stack); + reverse(stack); + stack.push(i); + } + + public static int getAndRemoveLastElement(Stack stack) { + int result = stack.pop(); + if (stack.isEmpty()) { + return result; + } else { + int last = getAndRemoveLastElement(stack); + stack.push(result); + return last; + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + if (s.isEmpty()) { + return; + } + Stack s2 = new Stack(); + while (s.peek() != null) { + if (!Objects.equals(o, s.peek())) { + s2.push(s.pop()); + } else { + s.pop(); + break; + } + } + while (!s2.isEmpty()) { + s.push(s2.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]; + } + + int len1 = (s.size() < len) ? s.size() : len; + + Object[] result = new Object[len1]; + Stack s2 = new Stack(); + Object o = null; + for (int i = 0; i < len1; i++) { + o = s.pop(); + result[i] = o; + s2.push(o); + } + while (!s2.isEmpty()) { + s.push(s2.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 s2 = new Stack(); + for (int i = 0; i < s.length(); i++) { + char c1 = s.charAt(i); + if (c1 != ')' && c1 != ']' && c1 != '}') { + s2.push(c1); + } else { + char c2 = getOpChar(s2); + if (!isPair(c1, c2)) { + return false; + } + } + } + + return true; + } + + private static boolean isPair(char c1, char c2) { + if (c1 == ')' && c2 == '(') { + return true; + } + + if (c1 == ']' && c2 == '[') { + return true; + } + + if (c1 == '}' && c2 == '{') { + return true; + } + + return false; + } + + private static char getOpChar(Stack s2) { + char c2 = s2.pop(); + while (c2 != ')' && c2 != ']' && c2 != '}' && + c2 != '(' && c2 != '[' && c2 != '{' && !s2.isEmpty()) { + c2 = s2.pop(); + } + return c2; + } + +} diff --git a/group12/382266293/coding/basic/stack/StackUtilTest.java b/group12/382266293/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..9180c4816e --- /dev/null +++ b/group12/382266293/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,85 @@ +package stack; + +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.Stack; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class StackUtilTest { + + Stack s; + @Before + public void setUp() throws Exception { + s = new Stack(); + } + + @After + public void tearDown() throws Exception { + s = null; + } + + @Test + public void testReverse() { + for(int i = 5; i >= 1; i--) { + s.push(i); + } + + StackUtil.reverse(s); + assertEquals(s.toString(),"[1, 2, 3, 4, 5]"); + + } + + @Test + public void testRemove() { + for(int i = 5; i >= 1; i--) { + s.push(i); + } + + StackUtil.remove(s,2); + assertEquals(s.toString(),"[5, 4, 3, 1]"); + + StackUtil.remove(s,5); + assertEquals(s.toString(),"[4, 3, 1]"); + + StackUtil.remove(s,1); + assertEquals(s.toString(),"[4, 3]"); + + s = new Stack(); + assertEquals(s.toString(),"[]"); + } + + @Test + public void testGetTop() { + for(int i = 5; i >= 1; i--) { + s.push(i); + } + + Object[] o = StackUtil.getTop(s,2); + + assertEquals(s.toString(),"[5, 4, 3, 2, 1]"); + assertEquals(Arrays.toString(o),"[1, 2]"); + + o = StackUtil.getTop(s,6); + assertEquals(Arrays.toString(o),"[1, 2, 3, 4, 5]"); + + o = StackUtil.getTop(s,0); + assertEquals(Arrays.toString(o),"[]"); + } + + @Test + public void testIsValidPairs() { + + String s1 = "([e{d}f])"; + assertEquals(true,StackUtil.isValidPairs(s1)); + + s1 = "([b{x]y})"; + assertEquals(false,StackUtil.isValidPairs(s1)); + + } + +} diff --git a/group12/382266293/coding/basic/stack/expr/InfixExpr.java b/group12/382266293/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..eade1dc743 --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,18 @@ +package stack.expr; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + return 0.0f; + } + + + + +} diff --git a/group12/382266293/coding/basic/stack/expr/InfixExprTest.java b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..bb047629bd --- /dev/null +++ b/group12/382266293/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package 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/group12/382266293/src/array/ArrayUtil.java b/group12/382266293/src/array/ArrayUtil.java index 8412a68f48..ea847fd386 100644 --- a/group12/382266293/src/array/ArrayUtil.java +++ b/group12/382266293/src/array/ArrayUtil.java @@ -6,40 +6,37 @@ import collection.Iterator; import collection.concrete.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] + * 给定一个整形数组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){ - + public void reverseArray(int[] origin) { + int temp; int index = origin.length - 1; - int numbersToReverse = origin.length/2; - for (int i = 0; i < numbersToReverse ; i++) { + int numbersToReverse = origin.length / 2; + for (int i = 0; i < numbersToReverse; i++) { temp = origin[i]; origin[i] = origin[index - i]; origin[index - 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} + * 现在有如下的一个数组: 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){ - + public int[] removeZero(int[] oldArray) { + BitSet check = new BitSet(oldArray.length); boolean isZero; for (int i = 0; i < oldArray.length; i++) { @@ -47,32 +44,32 @@ public int[] removeZero(int[] oldArray){ check.set(i, isZero); } - int newSize = oldArray.length-check.cardinality(); + int newSize = oldArray.length - check.cardinality(); int[] newArr = new int[newSize]; - + int nextIndex = check.nextClearBit(0); - for(int i = 0 ; i < newSize ; i++) { + for (int i = 0; i < newSize; i++) { newArr[i] = oldArray[nextIndex]; - nextIndex = check.nextClearBit(nextIndex+1); + nextIndex = check.nextClearBit(nextIndex + 1); } return newArr; } - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 - * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + * 给定两个已经排序好的整形数组, 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){ - + + public int[] merge(int[] array1, int[] array2) { + int len1 = array1.length; int len2 = array2.length; - int len3 = array1[len1-1] < array2[len2-1] ? array2[len2-1] + 1: array1[len1-1] + 1; + int len3 = array1[len1 - 1] < array2[len2 - 1] ? array2[len2 - 1] + 1 : array1[len1 - 1] + 1; int[] newArr = new int[len3]; initialArray(newArr, -1); for (int i = 0; i < len1; i++) { @@ -88,24 +85,24 @@ public int[] merge(int[] array1, int[] array2){ } return Arrays.copyOf(newArr, mergedLength); } - + public static void initialArray(int[] arr, int j) { for (int i = 0; i < arr.length; i++) { arr[i] = j; } } - + /** * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * 注意,老数组的元素在新数组中需要保持 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 * [2,3,6,0,0,0] + * * @param oldArray * @param size * @return */ - public int[] grow(int [] oldArray, int size){ - + public int[] grow(int[] oldArray, int size) { + int[] newArr = new int[oldArray.length + size]; for (int i = 0; i < oldArray.length; i++) { newArr[i] = oldArray[i]; @@ -113,39 +110,38 @@ public int[] grow(int [] oldArray, int size){ return newArr; } - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] + * 斐波那契数列为: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){ + public int[] fibonacci(int max) { if (max == 1) return new int[0]; int[] result = new int[max]; result[0] = result[1] = 1; int count = 0; - for (int i = 2, j = 0; j < max ; i++) { - result[i] = result[i-1] + result[i-2]; + for (int i = 2, j = 0; j < max; i++) { + result[i] = result[i - 1] + result[i - 2]; j = result[i]; count++; } return Arrays.copyOf(result, ++count); } - + /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * * @param max * @return */ - public int[] getPrimes(int max){ - + public int[] getPrimes(int max) { + String temp = ""; - for(int i = 0; i < max; i++) { - if(isPrime(i)) { + for (int i = 0; i < max; i++) { + if (isPrime(i)) { temp += i + " "; } } @@ -154,82 +150,77 @@ public int[] getPrimes(int max){ for (int i = 0; i < result.length; i++) { result[i] = Integer.parseInt(tempArr[i]); } - + return result; } - + public static boolean isPrime(int num) { - + if (num <= 1) return false; - + if (num == 2) return true; - - for(int i = 2; i <= Math.sqrt(num) + 1; i++) { + + for (int i = 2; i <= Math.sqrt(num) + 1; i++) { if (num % i == 0) return false; } - + return true; } - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * * @param max * @return */ - public int[] getPerfectNumbers(int max){ - + public int[] getPerfectNumbers(int max) { + int count = 0; ArrayList myList = new ArrayList(); - for(int i = 1; i < max; i++) { - if(isPerfectNum(i)) { + for (int i = 1; i < max; i++) { + if (isPerfectNum(i)) { count++; myList.add(i); } } - int[] result = new int[count]; + int[] result = new int[count]; Iterator iterator = myList.iterator(); for (int i = 0; i < count; i++) { result[i] = iterator.next(); } return result; } - - + public static boolean isPerfectNum(int num) { - + int sum = 0; - for (int i = 1; i <= num/2; i++) { + for (int i = 1; i <= num / 2; i++) { if (num % i == 0) sum += i; } - + return (num == sum) ? true : false; } - /** - * 用seperator 把数组 array给连接起来 - * 例如array= [3,8,9], seperator = "-" - * 则返回值为"3-8-9" + * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * * @param array * @param s * @return */ - public String join(int[] array, String seperator){ + public String join(int[] array, String seperator) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < array.length; i++) { sb.append(array[i]); - if (i < array.length-1) + if (i < array.length - 1) sb.append(seperator); } return sb.toString(); } - } \ No newline at end of file diff --git a/group12/382266293/src/array/ArrayUtilTest.java b/group12/382266293/src/array/ArrayUtilTest.java index 42085c1e25..031ef6c09b 100644 --- a/group12/382266293/src/array/ArrayUtilTest.java +++ b/group12/382266293/src/array/ArrayUtilTest.java @@ -9,14 +9,11 @@ import org.junit.Before; import org.junit.Test; - - - public class ArrayUtilTest { private int[] actual; ArrayUtil au = new ArrayUtil(); - + @Before public void setUp() throws Exception { @@ -27,34 +24,33 @@ public void tearDown() throws Exception { actual = null; } - @Test public void testReverseArray() { - + int size = getRandomNumber(); int[] expected = getRandomIntArray(size); actual = Arrays.copyOf(expected, size); - + au.reverseArray(actual); - + for (int i = 0; i < size; i++) { - assertEquals(expected[i], actual[size-1-i]); + assertEquals(expected[i], actual[size - 1 - i]); } - + } @Test public void testRemoveZero() { - + int size = getRandomNumber(10000); int[] expected = getRandomIntArray(size); - int zeros = getRandomNumber(size-1); + int zeros = getRandomNumber(size - 1); TreeSet t = new TreeSet(); while (t.size() != zeros) { t.add(getRandomNumber(size)); } - + for (Integer i : t) { expected[i] = 0; } @@ -62,17 +58,17 @@ public void testRemoveZero() { int expectedSize = size - zeros; actual = au.removeZero(expected); assertEquals(expectedSize, actual.length); - + for (int i = 0, j = 0; i < size; i++) { if (expected[i] != 0) assertEquals(expected[i], actual[j++]); } - + } @Test public void testMerge() { - int[] arr1 = getRandomIntArray(getRandomNumber()); + int[] arr1 = getRandomIntArray(getRandomNumber()); int[] arr2 = getRandomIntArray(getRandomNumber()); Arrays.sort(arr1); Arrays.sort(arr2); @@ -85,12 +81,12 @@ public void testMerge() { } int[] actual = new int[arr1.length + arr2.length]; actual = au.merge(arr1, arr2); - + assertEquals(t.size(), actual.length); - + Iterator it = t.iterator(); - for(int i = 0; it.hasNext(); i++) { - assertEquals((int)it.next(), actual[i]); + for (int i = 0; it.hasNext(); i++) { + assertEquals((int) it.next(), actual[i]); } } @@ -100,43 +96,43 @@ public void testGrow() { int[] expected = getRandomIntArray(getRandomNumber()); int growSize = getRandomNumber(); int[] actual = au.grow(expected, growSize); - + assertEquals(expected.length + growSize, actual.length); - + for (int i = 0; i < actual.length; i++) { if (i < expected.length) { assertEquals(expected[i], actual[i]); } else { assertEquals(0, actual[i]); - } + } } } @Test public void testFibonacci() { - int[] expected = new int[] {1, 1, 2, 3, 5, 8, 13}; + int[] expected = new int[] { 1, 1, 2, 3, 5, 8, 13 }; int[] acutal = new int[expected.length]; actual = au.fibonacci(15); - assertArrayEquals(expected,actual); + assertArrayEquals(expected, actual); } @Test public void testGetPrimes() { - - int[] expected = new int[] {2,3,5,7,11,13,17,19}; + + int[] expected = new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }; int[] acutal = new int[expected.length]; actual = au.getPrimes(23); - assertArrayEquals(expected,actual); + assertArrayEquals(expected, actual); } @Test public void testGetPerfectNumbers() { - - int[] expected = new int[] {6, 28, 496, 8128}; + + int[] expected = new int[] { 6, 28, 496, 8128 }; int[] acutal = new int[expected.length]; actual = au.getPerfectNumbers(10000); - assertArrayEquals(expected,actual); + assertArrayEquals(expected, actual); } @Test @@ -145,9 +141,9 @@ public void testJoin() { int[] expected = getRandomIntArray(getRandomNumber()); String seperator = "-"; String joinedString = au.join(expected, seperator); - + String[] actual = joinedString.split(seperator); - + assertEquals(expected.length, actual.length); for (int i = 0; i < expected.length; i++) { assertEquals(expected[i], Integer.parseInt(actual[i])); diff --git a/group12/382266293/src/com/coderising/download/DownloadThread.java b/group12/382266293/src/com/coderising/download/DownloadThread.java index d1e1f04c47..38f92f6677 100644 --- a/group12/382266293/src/com/coderising/download/DownloadThread.java +++ b/group12/382266293/src/com/coderising/download/DownloadThread.java @@ -7,8 +7,7 @@ import com.coderising.download.api.Connection; - -public class DownloadThread extends Thread{ +public class DownloadThread extends Thread { Connection conn; int startPos; @@ -16,15 +15,16 @@ public class DownloadThread extends Thread{ private String dest; private FileDownloader fileDownloader; - public DownloadThread( Connection conn, int startPos, int endPos){ - - this.conn = conn; + public DownloadThread(Connection conn, int startPos, int endPos) { + + this.conn = conn; this.startPos = startPos; this.endPos = endPos; } + @Override - public void run(){ - System.out.println(this.getName()+" is running"); + public void run() { + System.out.println(this.getName() + " is running"); RandomAccessFile raf = null; try { byte[] buffer = conn.read(startPos, endPos); @@ -36,7 +36,7 @@ public void run(){ e.printStackTrace(); } finally { conn.close(); - System.out.println(this.getName()+" finished"); + System.out.println(this.getName() + " finished"); try { if (raf != null) @@ -48,7 +48,7 @@ public void run(){ } } } - + public void setFileDownloader(FileDownloader fileDownloader) { this.fileDownloader = fileDownloader; } @@ -56,15 +56,14 @@ public void setFileDownloader(FileDownloader fileDownloader) { public void notifyFinished() { fileDownloader.setThreadFinished(); } - + public void setDest(String dest) { this.dest = dest; } - + public void close() { this.conn.close(); - + } - } diff --git a/group12/382266293/src/com/coderising/download/DownloadUtil.java b/group12/382266293/src/com/coderising/download/DownloadUtil.java index b01200c51d..c169214476 100644 --- a/group12/382266293/src/com/coderising/download/DownloadUtil.java +++ b/group12/382266293/src/com/coderising/download/DownloadUtil.java @@ -66,8 +66,8 @@ public static boolean rename(String from, String to) { public static void printDownloadReport(int length, long start, long end) { int time = (int) ((end - start) / 1000); - float speed = (float)length / 1024 / 1024 / time; - System.out.println("共耗时:" + time + "s,下载速度: " + (float)(Math.round(speed*100))/100 + "Mb/s"); + float speed = (float) length / 1024 / 1024 / time; + System.out.println("共耗时:" + time + "s,下载速度: " + (float) (Math.round(speed * 100)) / 100 + "Mb/s"); } } \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/download/FileDownloader.java b/group12/382266293/src/com/coderising/download/FileDownloader.java index c756248bb1..671ff7243c 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloader.java +++ b/group12/382266293/src/com/coderising/download/FileDownloader.java @@ -45,7 +45,6 @@ public void execute() { Connection conn = cm.open(this.url); int length = conn.getContentLength(); - System.out.println("file length:" + length); setLocation("C:\\"); @@ -53,7 +52,7 @@ public void execute() { setFileName(name); setTempName(name); checkLength(length, conn); - + DownloadUtil.createTempFile(tempName, length); int connNumbers = DownloadUtil.calculateConnects(length); @@ -153,7 +152,6 @@ private void setAndStartThreadPool(Connection conn, DownloadThread[] threadPool, } threadPool[i] = new DownloadThread(con, beginPos, endPos); setAndStartThread(threadPool[i], tempName); - } } diff --git a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java index ae24faa19f..88a5dba40e 100644 --- a/group12/382266293/src/com/coderising/download/FileDownloaderTest.java +++ b/group12/382266293/src/com/coderising/download/FileDownloaderTest.java @@ -22,7 +22,6 @@ public void tearDown() throws Exception { public static String qq = "http://sw.bos.baidu.com/sw-search-sp/software/89179b0b248b1/QQ_8.9.20026.0_setup.exe"; public static String picture = "http://image.beekka.com/blog/201304/bg2013042401.jpg"; public static String foxmail = "http://sw.bos.baidu.com/sw-search-sp/software/6c7bb8b6674d0/fm728chb379_7.2.8.379_setup.exe"; - @Test public void testDownload() { diff --git a/group12/382266293/src/com/coderising/download/api/Connection.java b/group12/382266293/src/com/coderising/download/api/Connection.java index 63d9fc7b19..11a0eab3d8 100644 --- a/group12/382266293/src/com/coderising/download/api/Connection.java +++ b/group12/382266293/src/com/coderising/download/api/Connection.java @@ -5,23 +5,31 @@ public interface Connection { /** * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * @param startPos 开始位置, 从0开始 - * @param endPos 结束位置 + * + * @param startPos + * 开始位置, 从0开始 + * @param endPos + * 结束位置 * @return */ - public byte[] read(int startPos,int endPos) throws IOException; + public byte[] read(int startPos, int endPos) throws IOException; + /** * 得到数据内容的长度 + * * @return */ public int getContentLength(); - + /** * 关闭连接 */ public void close(); + public String getFileName(); + public void setFinished(); + public boolean isFinished(); } diff --git a/group12/382266293/src/com/coderising/download/api/ConnectionManager.java b/group12/382266293/src/com/coderising/download/api/ConnectionManager.java index 17f1e544b1..c305248608 100644 --- a/group12/382266293/src/com/coderising/download/api/ConnectionManager.java +++ b/group12/382266293/src/com/coderising/download/api/ConnectionManager.java @@ -3,11 +3,12 @@ public interface ConnectionManager { /** * 给定一个url , 打开一个连接 + * * @param url * @return */ - + final int MAX_CONNECTION_SIZE = 100; - + public Connection open(String url) throws ConnectionException; } diff --git a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java index 61ed430106..a4fa5c15ad 100644 --- a/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java +++ b/group12/382266293/src/com/coderising/download/impl/ConnectionImpl.java @@ -10,14 +10,14 @@ import sun.net.www.protocol.http.HttpURLConnection; -public class ConnectionImpl implements Connection{ +public class ConnectionImpl implements Connection { private ConnectionManager cm; private static int buffer_size = 1024; private HttpURLConnection httpConn; private URL url; private boolean finished = false; - + public ConnectionImpl(ConnectionManager cm, String _url) { this.cm = cm; try { @@ -35,28 +35,28 @@ public byte[] read(int startPos, int endPos) throws IOException { try { httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - in = httpConn.getInputStream(); + in = httpConn.getInputStream(); out = new ByteArrayOutputStream(); in = httpConn.getInputStream(); - //in.skip(startPos); - + // in.skip(startPos); + int len = 0; byte[] b = new byte[1024]; - while((len = in.read(b)) != -1) { + while ((len = in.read(b)) != -1) { out.write(b, 0, len); } int totalLen = endPos - startPos + 1; - - if (out.size() > totalLen) { + + if (out.size() > totalLen) { byte[] data = out.toByteArray(); return data; } - + return out.toByteArray(); - + } catch (IOException e) { e.printStackTrace(); - } + } return null; } @@ -65,18 +65,18 @@ public int getContentLength() { int len = httpConn.getContentLength(); return len; - + } @Override public void close() { - httpConn.disconnect(); + httpConn.disconnect(); } @Override public String getFileName() { String fileName = httpConn.getURL().getFile(); - fileName = fileName.substring(fileName.lastIndexOf('/')+1); + fileName = fileName.substring(fileName.lastIndexOf('/') + 1); return fileName; } @@ -90,5 +90,4 @@ public boolean isFinished() { return finished; } - } diff --git a/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java index 4d44301b0d..122073e37b 100644 --- a/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java +++ b/group12/382266293/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -11,7 +11,7 @@ public class ConnectionManagerImpl implements ConnectionManager { private int connections = 0; private String url; - + public ConnectionManagerImpl() { this.connections = 0; } @@ -24,12 +24,12 @@ public Connection open(String url) throws ConnectionException { Connection conn = null; try { address = new URL(url); - conn = new ConnectionImpl(this,url); + conn = new ConnectionImpl(this, url); connections++; return conn; } catch (IOException e) { e.printStackTrace(); - } + } return null; } @@ -43,4 +43,3 @@ private void checkConnectionSize() { } } - diff --git a/group12/382266293/src/com/coderising/download/impl/NoFreeSourceException.java b/group12/382266293/src/com/coderising/download/impl/NoFreeSourceException.java index f2f68c3aa0..909a17a29b 100644 --- a/group12/382266293/src/com/coderising/download/impl/NoFreeSourceException.java +++ b/group12/382266293/src/com/coderising/download/impl/NoFreeSourceException.java @@ -2,7 +2,6 @@ public class NoFreeSourceException extends Exception { - public NoFreeSourceException(String string) { super(string); } diff --git a/group12/382266293/src/com/coderising/jvm/attr/AttributeInfo.java b/group12/382266293/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..89fb53394e --- /dev/null +++ b/group12/382266293/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/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..68a628ec61 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,118 @@ +package com.coderising.jvm.attr; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.Field; +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(); + + System.out.println("attrIndex " + attrNameIndex); + + int attrLen = iter.nextU4ToInt(); + + int maxStack = iter.nextU2ToInt(); + + int maxLocals = iter.nextU2ToInt(); + + int codeLen = iter.nextU4ToInt(); + + System.out.println("codeLen " + codeLen); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, "Code"); + + String code = iter.nextUxToHexString(codeLen); + + System.out.println("Code is " + code); + + int exceptionTableLen = iter.nextU2ToInt(); + + if (exceptionTableLen > 0) { + + String exTable = iter.nextUxToHexString(exceptionTableLen); + + System.out.println("exception encounted " + exTable); + } + + int sub_attrNum = iter.nextU2ToInt(); + + for (int i = 0; i < sub_attrNum; i++) { + + int subAttrNameIndex = iter.nextU2ToInt(); + String subAttrName = clzFile.getConstantPool().getUTF8String(subAttrNameIndex); + System.out.println("subAttrNameIndex is " + subAttrName); + iter.back(2); + + if (AttributeInfo.LINE_NUM_TABLE.equalsIgnoreCase(subAttrName)) { + + LineNumberTable lnt = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lnt); + + } else if (AttributeInfo.LOCAL_VAR_TABLE.equalsIgnoreCase(subAttrName)) { + + LocalVariableTable lvt = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(lvt); + + } else if (AttributeInfo.STACK_MAP_TABLE.equalsIgnoreCase(subAttrName)) { + + StackMapTable smt = StackMapTable.parse(iter); + codeAttr.setStackMapTable(smt); + + } else { + throw new RuntimeException(subAttrName + "not implemented yet"); + } + + } + + return codeAttr; + } + + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java rename to group12/382266293/src/com/coderising/jvm/attr/LineNumberTable.java diff --git a/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..3eb2654e36 --- /dev/null +++ b/group12/382266293/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/liuxin/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java rename to group12/382266293/src/com/coderising/jvm/attr/LocalVariableTable.java diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java similarity index 100% rename from liuxin/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java rename to group12/382266293/src/com/coderising/jvm/attr/StackMapTable.java diff --git a/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java b/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..17dd61f8b6 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,32 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.loader.ByteCodeIterator; + +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; + } + + public static AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } +} \ No newline at end of file diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..6e37d03643 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,118 @@ +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 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 List getFields() { + + return fields; + } + + public void setFields(List fields) { + + this.fields = fields; + + } + + public void addField(Field field) { + + this.fields.add(field); + + } + + public List getMethods() { + + return methods; + } + + public void setMethods(List methods) { + + this.methods = methods; + + } + + public void addMethod(Method method) { + + this.methods.add(method); + + } +} diff --git a/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java b/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..0212bc9fb3 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +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/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..4b593e7347 --- /dev/null +++ b/group12/382266293/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(); + } +} diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..96845046b3 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,32 @@ +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; + pool.addConstantInfo(this); + } + + public abstract int getType(); + + public ConstantPool getConstantPool() { + return constantPool; + } + + public ConstantInfo getConstantInfo(int index) { + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..95c44dde8f --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,32 @@ +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) { + //System.out.println(this.constantInfos.get(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/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..e9f34e550c --- /dev/null +++ b/group12/382266293/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(); + } +} diff --git a/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..d58de16f72 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,57 @@ +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/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..a792e2dc13 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,48 @@ +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/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java b/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..7d1abf7699 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..0ea1f6bdac --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,27 @@ +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/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java b/group12/382266293/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..a7e88969a4 --- /dev/null +++ b/group12/382266293/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; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/field/Field.java b/group12/382266293/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..2b0c549685 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/field/Field.java @@ -0,0 +1,48 @@ +package com.coderising.jvm.field; + +import com.coderising.jvm.clz.AccessFlag; +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; + } + + + + + @Override + public String toString() { + return pool.getUTF8String(nameIndex) + ":" + pool.getUTF8String(descriptorIndex) ; + } + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + int access_flags = iter.nextU2ToInt(); + int name_index = iter.nextU2ToInt(); + int descriptor_index = iter.nextU2ToInt(); + int attrbutes_count = iter.nextU2ToInt(); + + if (attrbutes_count != 0) { + throw new RuntimeException("field attrbutes_count is " + attrbutes_count); + } + + Field field = new Field(access_flags,name_index,descriptor_index,pool); + + return field; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..4b554a434a --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,69 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + + private byte[] codes = null; + private int currPos = 0; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public String nextU4ToHexString() { + byte[] u4 = new byte[] { codes[currPos++], codes[currPos++], codes[currPos++], codes[currPos++] }; + return Util.byteToHexString(u4); + } + + public int nextU1ToInt() { + byte[] u1 = new byte[] { codes[currPos++] }; + return Util.byteToInt(u1); + + } + + public int nextU2ToInt() { + byte[] u2 = new byte[] { codes[currPos++], codes[currPos++] }; + return Util.byteToInt(u2); + } + + public int nextU4ToInt() { + byte[] u4 = new byte[] { codes[currPos++], codes[currPos++], codes[currPos++], codes[currPos++] }; + return Util.byteToInt(u4); + } + + + public byte[] nextNbytesToHexString(int length) { + byte[] bytes = new byte[length]; + int len = currPos + length; + for(int j = 0; currPos < len; j++) { + bytes[j] = codes[currPos++]; + } + + return bytes; + } + + public String nextUxToHexString(int length) { + byte[] codes = nextNbytesToHexString(length); + return byteToHexString(codes); + } + + public 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(); + } + + public void back(int i) { + currPos = currPos - 2; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java index 9ba4ff935b..71a8b6fefa 100644 --- a/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -4,9 +4,12 @@ import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; +import com.coderising.jvm.clz.ClassFile; + public class ClassFileLoader { private List clzPaths = new ArrayList(); @@ -17,6 +20,14 @@ public byte[] readBinaryCode(String className) { return loadClassFile(clzFileName); } + public ClassFile loadClass(String className) throws UnsupportedEncodingException { + + ClassFileParser clzParser = new ClassFileParser(); + byte[] codes = readBinaryCode(className); + ClassFile clzFile = clzParser.parse(codes); + return clzFile; + } + @SuppressWarnings("resource") private byte[] loadClassFile(String clzFileName) { File classFile = getClassFile(clzFileName); diff --git a/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..e1c997d3d0 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,191 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; + +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; +import com.coderising.jvm.util.Util; + +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) == false) { + throw new RuntimeException("invalide class file!" + magicNumber); + } + + int minorVersion = iter.nextU2ToInt(); + System.out.println("minorVersion is " + minorVersion); + clzFile.setMinorVersion(minorVersion); + + int majorVersion = iter.nextU2ToInt(); + System.out.println("majorVersion is " + majorVersion); + clzFile.setMajorVersion(majorVersion); + + + ConstantPool pool = parseConstantPool(iter); + clzFile.setConstPool(pool); + + + AccessFlag accessFlag = parseAccessFlag(iter); + clzFile.setAccessFlag(accessFlag); + + ClassIndex classIndex = parseClassIndex(iter); + clzFile.setClassIndex(classIndex); + + parseInterfaces(iter); + + parseFields(clzFile, iter); + + parseMethods(clzFile, iter); + + return clzFile; + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + + int methodNum = iter.nextU2ToInt(); + + ConstantPool pool = clzFile.getConstantPool(); + for (int i = 0; i < methodNum; i++) { + Method method = Method.parse(clzFile,iter); + clzFile.addMethod(method); + } + + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + + int fieldNum = iter.nextU2ToInt(); + + ConstantPool pool = clzFile.getConstantPool(); + for (int i = 0; i < fieldNum; i++) { + Field field = Field.parse(pool,iter); + clzFile.addField(field); + } + + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceNum = iter.nextU2ToInt(); + + if (0 != interfaceNum) { + throw new RuntimeException("interface parser not finsihed yet, pls check!"); + } + + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + return AccessFlag.parseAccessFlag(iter); + } + + 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) { + + int constantsNum = iter.nextU2ToInt(); + System.out.println("constantsNum is " + constantsNum); + + ConstantPool pool = new ConstantPool(); + + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i < constantsNum; i++) { + + int tag = iter.nextU1ToInt(); + + if (tag == 7) { + // Class info + ClassInfo classInfo = new ClassInfo(pool); + int utf8Index = iter.nextU2ToInt(); + classInfo.setUtf8Index(utf8Index); + + + } else if (tag == 1) { + + // utf8-info + UTF8Info utf8Info = new UTF8Info(pool); + int length = iter.nextU2ToInt(); + System.out.println("length is " + length); + utf8Info.setLength(length); + byte[] bytes = iter.nextNbytesToHexString(length); + String value = ""; + try { + value = new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + System.out.println("value is " + value); + utf8Info.setValue(value); + + } else if (tag == 8) { + + // StringInfo + StringInfo stringInfo = new StringInfo(pool); + int stringIndex = iter.nextU2ToInt(); + stringInfo.setIndex(stringIndex); + } else if (tag == 9) { + + // FieldRefInfo + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + int classIndex = iter.nextU2ToInt(); + fieldRefInfo.setClassInfoIndex(classIndex); + int nameAndTypeIndex = iter.nextU2ToInt(); + fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + } else if (tag == 10) { + + // MethodRefInfo + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + int classIndex = iter.nextU2ToInt(); + methodRefInfo.setClassInfoIndex(classIndex); + int nameAndTypeIndex = iter.nextU2ToInt(); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + + } else if (tag == 12) { + + // NameAndTypeInfo + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + int index1 = iter.nextU2ToInt(); + nameAndTypeInfo.setIndex1(index1); + int index2 = iter.nextU2ToInt(); + nameAndTypeInfo.setIndex2(index2); + + } + + } + + return pool; + } + +} diff --git a/group12/382266293/src/com/coderising/jvm/method/Method.java b/group12/382266293/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..3c3e026a40 --- /dev/null +++ b/group12/382266293/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,81 @@ +package com.coderising.jvm.method; + +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.field.Field; +import com.coderising.jvm.loader.ByteCodeIterator; +import com.sun.org.apache.bcel.internal.classfile.Code; + + + +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){ + + int access_flags = iter.nextU2ToInt(); + int name_index = iter.nextU2ToInt(); + int descriptor_index = iter.nextU2ToInt(); + int attrbutes_count = iter.nextU2ToInt(); + System.out.println("count1 = " + attrbutes_count); + + Method method = new Method(clzFile, access_flags,name_index,descriptor_index); + + for (int i = 0; i < attrbutes_count; i++) { + int attr_nameIndex = iter.nextU2ToInt(); + String att_name = clzFile.getConstantPool().getUTF8String(attr_nameIndex); + iter.back(2); + + if (AttributeInfo.CODE.equalsIgnoreCase("Code")) { + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + method.setCodeAttr(codeAttr); + } else { + throw new RuntimeException(att_name + "has not been implemented"); + } + + } + + + + return method; + + } +} diff --git a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java index fb2f3be0a6..d4f255a763 100644 --- a/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group12/382266293/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,18 +1,41 @@ package com.coderising.jvm.test; +import java.io.UnsupportedEncodingException; import java.util.Arrays; +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.constant.*; +import com.coderising.jvm.field.Field; import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.Method; public class ClassFileloaderTest { - static String path1 = "C:\\Users\\Administrator\\git\\coding2017n\\group12\\382266293\\bin"; + static String path1 = "C:\\Users\\steve\\workspace\\coding2017n\\group12\\382266293\\bin"; static String path2 = "C:\temp"; + String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + String className = "com.coderising.jvm.test.EmployeeV1"; + + try { + clzFile = loader.loadClass(className); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + clzFile.print(); + } @Before public void setUp() throws Exception { @@ -45,7 +68,7 @@ public void testClassFileLength() { byte[] byteCodes = loader.readBinaryCode(className); - // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + // 娉ㄦ剰锛氳繖涓瓧鑺傛暟鍙兘鍜屼綘鐨凧VM鐗堟湰鏈夊叧绯伙紝 浣犲彲浠ョ湅鐪嬬紪璇戝ソ鐨勭被鍒板簳鏈夊澶� Assert.assertEquals(1056, byteCodes.length); } @@ -77,4 +100,162 @@ private String byteToHexString(byte[] codes) { 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()); + } + + + @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); + } + + } diff --git a/group12/382266293/src/com/coderising/jvm/util/Util.java b/group12/382266293/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..1f9e087bb9 --- /dev/null +++ b/group12/382266293/src/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 < 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/group12/382266293/src/com/coderising/litestruts/LoginAction.java b/group12/382266293/src/com/coderising/litestruts/LoginAction.java index a3ce652047..95fd144d4d 100644 --- a/group12/382266293/src/com/coderising/litestruts/LoginAction.java +++ b/group12/382266293/src/com/coderising/litestruts/LoginAction.java @@ -2,38 +2,41 @@ /** * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * * @author liuxin * */ -public class LoginAction{ - private String name ; - private String password; - private String message; +public class LoginAction { + private String name; + private String password; + private String message; - public String getName() { - return name; - } + public String getName() { + return name; + } - public String getPassword() { - return password; - } + 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 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; - } + 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/group12/382266293/src/litestruts/Configuration.java b/group12/382266293/src/litestruts/Configuration.java index 4efedbce67..731a4218b0 100644 --- a/group12/382266293/src/litestruts/Configuration.java +++ b/group12/382266293/src/litestruts/Configuration.java @@ -9,84 +9,84 @@ import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import static util.Print.*; + public class Configuration { - Map actions = new HashMap<>(); + Map actions = new HashMap<>(); private static Configuration cfg = new Configuration(); - + private Configuration() { } + public static Configuration getNewInstance() { - + if (cfg == null) { cfg = new Configuration(); } return cfg; } - + public void parse(String fileName) { - + String src = this.getClass().getPackage().getName(); - String filepath = src.replace(".", "/") + "/" +fileName; + String filepath = src.replace(".", "/") + "/" + fileName; InputStream is = this.getClass().getResourceAsStream("/" + filepath); - + parseXML(is); - + try { is.close(); - } catch (IOException e) { - + } catch (IOException e) { + } - + } - + public void parseXML(InputStream is) { SAXBuilder reader = new SAXBuilder(); - try { + try { Document doc = reader.build(is); Element root = doc.getRootElement(); - - for(Element element : root.getChildren("action")) { - + + for (Element element : root.getChildren("action")) { + String actionName = element.getAttributeValue("name"); String clz = element.getAttributeValue("class"); - ActionCfg ac = new ActionCfg(actionName,clz); - - for(Element e : element.getChildren("result")) { - + ActionCfg ac = new ActionCfg(actionName, clz); + + for (Element e : element.getChildren("result")) { + String result = e.getAttributeValue("name"); String jsp = e.getText().trim(); ac.addViewResult(result, jsp); } - + actions.put(actionName, ac); } - + } catch (JDOMException | IOException e) { e.printStackTrace(); } } - - + public String getClassName(String action) { ActionCfg cfg = this.actions.get(action); if (cfg == null) { return null; } - return cfg.getClassName(); + return cfg.getClassName(); } - - + public String getResultView(String action, String resultName) { ActionCfg cfg = this.actions.get(action); if (cfg == null) { return null; } - return cfg.getViewResult().get(resultName); + return cfg.getViewResult().get(resultName); } public static void main(String[] args) { @@ -94,17 +94,14 @@ public static void main(String[] args) { cfg.parse("struts.xml"); String clz = cfg.getClassName("login"); println(clz); - } - - private static class ActionCfg { - + String name; String clz; - Map viewResult = new HashMap<>(); + Map viewResult = new HashMap<>(); public Map getViewResult() { return viewResult; @@ -117,7 +114,7 @@ public ActionCfg(String name, String clz) { public void addViewResult(String result, String jsp) { viewResult.put(result, jsp); - + } public String getClassName() { @@ -126,10 +123,4 @@ public String getClassName() { } - - - - - - } diff --git a/group12/382266293/src/litestruts/ConfigurationTest.java b/group12/382266293/src/litestruts/ConfigurationTest.java index e9d41a07c9..bf47334da5 100644 --- a/group12/382266293/src/litestruts/ConfigurationTest.java +++ b/group12/382266293/src/litestruts/ConfigurationTest.java @@ -5,18 +5,13 @@ import org.junit.Before; import org.junit.Test; - - public class ConfigurationTest { - Configuration cfg = Configuration.getNewInstance(); - - - + @Before public void setUp() throws Exception { - + cfg.parse("struts.xml"); } @@ -27,29 +22,28 @@ 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"); + public void testGetResultView() { + String jsp = cfg.getResultView("login", "success"); Assert.assertEquals("/jsp/homepage.jsp", jsp); - - jsp = cfg.getResultView("login","fail"); + + jsp = cfg.getResultView("login", "fail"); Assert.assertEquals("/jsp/showLogin.jsp", jsp); - - jsp = cfg.getResultView("logout","success"); + + jsp = cfg.getResultView("logout", "success"); Assert.assertEquals("/jsp/welcome.jsp", jsp); - - jsp = cfg.getResultView("logout","error"); + + jsp = cfg.getResultView("logout", "error"); Assert.assertEquals("/jsp/error.jsp", jsp); - + } } diff --git a/group12/382266293/src/litestruts/Struts.java b/group12/382266293/src/litestruts/Struts.java index df9c4ed535..b84e2e6264 100644 --- a/group12/382266293/src/litestruts/Struts.java +++ b/group12/382266293/src/litestruts/Struts.java @@ -16,48 +16,46 @@ public class Struts { private static Object actionObj = null; private static String address = "src/litestruts/struts.xml"; private static ActionXMLreader reader = new ActionXMLreader(); - - @SuppressWarnings("unchecked") - public static View runAction(String actionName, Map parameters){ - - Node root = reader.getRootNode(address); - String clazz = reader.parseClass(root, actionName); - actionObj = getObj(clazz); - BeanInfo bi = getBeanInfo(actionObj); - PropertyDescriptor[] pd = bi.getPropertyDescriptors(); - - setParameters(actionObj, pd, parameters); - String executeResult = getResult(actionObj, bi, "execute"); - String jsp = reader.parseResult(root, actionName, executeResult); - Map readParamters = getReadParameters(actionObj, pd); - + + @SuppressWarnings("unchecked") + public static View runAction(String actionName, Map parameters) { + + Node root = reader.getRootNode(address); + String clazz = reader.parseClass(root, actionName); + actionObj = getObj(clazz); + BeanInfo bi = getBeanInfo(actionObj); + PropertyDescriptor[] pd = bi.getPropertyDescriptors(); + + setParameters(actionObj, pd, parameters); + String executeResult = getResult(actionObj, bi, "execute"); + String jsp = reader.parseResult(root, actionName, executeResult); + Map readParamters = getReadParameters(actionObj, pd); + View view = new View(); view.setJsp(jsp); view.setParameters(readParamters); - - return view; - } - + + return view; + } private static Object getObj(String clazz) { - @SuppressWarnings("rawtypes") + @SuppressWarnings("rawtypes") Class cls = null; - + try { cls = Class.forName(clazz); return cls.newInstance(); } catch (ClassNotFoundException e) { e.printStackTrace(); - }catch (InstantiationException | IllegalAccessException e) { + } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); - } + } return null; } + private static BeanInfo getBeanInfo(Object obj) { - private static BeanInfo getBeanInfo(Object obj) { - - BeanInfo bi = null; + BeanInfo bi = null; try { bi = Introspector.getBeanInfo(obj.getClass(), Object.class); } catch (IntrospectionException e) { @@ -65,51 +63,50 @@ private static BeanInfo getBeanInfo(Object obj) { } return bi; } - - private static void setParameters(Object obj, PropertyDescriptor[] pd ,Map parameters) { - - for (int i = 0; i < pd.length; i++) { - String name = pd[i].getName(); - if(parameters.containsKey(name)) - try { - pd[i].getWriteMethod().invoke(obj,parameters.get(name)); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - e.printStackTrace(); - } - } - } - - private static String getResult(Object obj, BeanInfo bi,String execute) { - MethodDescriptor[] methods = bi.getMethodDescriptors(); - for (int i = 0; i < methods.length; i++) { - String methodName = methods[i].getName(); - if(methodName.equals(execute)) + + private static void setParameters(Object obj, PropertyDescriptor[] pd, Map parameters) { + + for (int i = 0; i < pd.length; i++) { + String name = pd[i].getName(); + if (parameters.containsKey(name)) + try { + pd[i].getWriteMethod().invoke(obj, parameters.get(name)); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + } + } + + private static String getResult(Object obj, BeanInfo bi, String execute) { + MethodDescriptor[] methods = bi.getMethodDescriptors(); + for (int i = 0; i < methods.length; i++) { + String methodName = methods[i].getName(); + if (methodName.equals(execute)) try { return (String) methods[i].getMethod().invoke(actionObj); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } - } - return null; + } + return null; } - + @SuppressWarnings("rawtypes") - public static Map getReadParameters (Object obj, PropertyDescriptor[] pd) { + public static Map getReadParameters(Object obj, PropertyDescriptor[] pd) { - Map viewParams = new HashMap(); + Map viewParams = new HashMap(); - for (int i = 0; i < pd.length; i++) { - String readMethod = pd[i].getReadMethod().getName().substring(3); - String value = null; + for (int i = 0; i < pd.length; i++) { + String readMethod = pd[i].getReadMethod().getName().substring(3); + String value = null; try { value = (String) pd[i].getReadMethod().invoke(obj); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } - viewParams.put(readMethod.toLowerCase(), value); - } - return viewParams; - } - + viewParams.put(readMethod.toLowerCase(), value); + } + return viewParams; + } } \ No newline at end of file diff --git a/group12/382266293/src/litestruts/StrutsTest.java b/group12/382266293/src/litestruts/StrutsTest.java index 4b59f846f5..b450d7a935 100644 --- a/group12/382266293/src/litestruts/StrutsTest.java +++ b/group12/382266293/src/litestruts/StrutsTest.java @@ -6,38 +6,33 @@ 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")); + + 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")); + 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/group12/382266293/src/litestruts/View.java b/group12/382266293/src/litestruts/View.java index 5a7d948765..0c917dcb35 100644 --- a/group12/382266293/src/litestruts/View.java +++ b/group12/382266293/src/litestruts/View.java @@ -5,17 +5,20 @@ 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/group12/382266293/src/litestruts/struts.xml b/group12/382266293/src/litestruts/struts.xml index 4c6eeabbd4..1370971a4b 100644 --- a/group12/382266293/src/litestruts/struts.xml +++ b/group12/382266293/src/litestruts/struts.xml @@ -1,11 +1,11 @@ - - /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/group12/382266293/src/test.java b/group12/382266293/src/test.java index a705772df2..b3a32d2556 100644 --- a/group12/382266293/src/test.java +++ b/group12/382266293/src/test.java @@ -10,24 +10,24 @@ public class test { - public static String url = "http://sw.bos.baidu.com/sw-search-sp/software/89179b0b248b1/QQ_8.9.20026.0_setup.exe"; + public static String url = "http://sw.bos.baidu.com/sw-search-sp/software/89179b0b248b1/QQ_8.9.20026.0_setup.exe"; public static String url2 = "http://image.beekka.com/blog/201304/bg2013042401.jpg"; public static String downloadLocation = "C:\\"; public static String tempName = ""; public static String fileName = ""; - + LinkedList a; - + private static void createTempFile1(String from) { long length = 0; URL url = null; HttpURLConnection conn = null; try { url = new URL(from); - conn = (HttpURLConnection)url.openConnection(); + conn = (HttpURLConnection) url.openConnection(); String file = conn.getURL().getFile(); - fileName = file.substring(file.lastIndexOf('/')+1); - tempName = fileName.substring(0, fileName.lastIndexOf('.')+1) + "lyj"; + fileName = file.substring(file.lastIndexOf('/') + 1); + tempName = fileName.substring(0, fileName.lastIndexOf('.') + 1) + "lyj"; length = conn.getContentLength(); conn.disconnect(); } catch (IOException e) { @@ -37,7 +37,7 @@ private static void createTempFile1(String from) { } tempName = downloadLocation + tempName; fileName = downloadLocation + fileName; - bufferFile(tempName,length); + bufferFile(tempName, length); } public static void bufferFile(String name, long len) { @@ -53,7 +53,7 @@ public static void bufferFile(String name, long len) { temp.write(buffer); } temp.write(buffer, 0, left); - + } catch (Exception e) { e.printStackTrace(); } finally { @@ -65,23 +65,22 @@ public static void bufferFile(String name, long len) { } } } - - + public static void download(String src) { createTempFile1(src); - + URL url = null; HttpURLConnection conn = null; FileOutputStream out = null; InputStream in = null; try { url = new URL(src); - conn = (HttpURLConnection)url.openConnection(); - in = conn.getInputStream(); + conn = (HttpURLConnection) url.openConnection(); + in = conn.getInputStream(); out = new FileOutputStream(tempName); byte[] buffer = new byte[1024]; int len = 0; - while( (len = in.read(buffer)) != -1) { + while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } conn.disconnect(); @@ -95,20 +94,19 @@ public static void download(String src) { } } - + public static boolean rename(String temp) { - File file=new File(temp); - File f1=new File(fileName); - if( file.exists() ) { + File file = new File(temp); + File f1 = new File(fileName); + if (file.exists()) { file.renameTo(f1); file = f1; - System.out.println("文件重命名为:"+f1.getName()); + System.out.println("文件重命名为:" + f1.getName()); return true; } return false; } - public static void main(String[] args) throws IOException { download(url2); diff --git a/group12/446031103/src/com/coderising/jvm/clz/AccessFlag.java b/group12/446031103/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/clz/ClassFile.java b/group12/446031103/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/clz/ClassIndex.java b/group12/446031103/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/ClassInfo.java b/group12/446031103/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/ConstantInfo.java b/group12/446031103/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/ConstantPool.java b/group12/446031103/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/FieldRefInfo.java b/group12/446031103/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/MethodRefInfo.java b/group12/446031103/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group12/446031103/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/NullConstantInfo.java b/group12/446031103/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/StringInfo.java b/group12/446031103/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/constant/UTF8Info.java b/group12/446031103/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group12/446031103/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/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..9c9fac2839 --- /dev/null +++ b/group12/446031103/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + +} diff --git a/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java b/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java index e021b94d38..33185d8175 100644 --- a/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group12/446031103/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -1,8 +1,20 @@ 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 { @@ -11,33 +23,118 @@ public class ClassFileLoader { public byte[] readBinaryCode(String className) { - return null; + 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) { - return null; + 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_V1(){ + + + 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); - return null; } - public String getClassPath(){ + + + // ------------------------------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/group12/446031103/src/com/coderising/jvm/test/EmployeeV1.java b/group12/446031103/src/com/coderising/jvm/test/EmployeeV1.java index 5e2bd8668f..12e3d7efdd 100644 --- a/group12/446031103/src/com/coderising/jvm/test/EmployeeV1.java +++ b/group12/446031103/src/com/coderising/jvm/test/EmployeeV1.java @@ -25,4 +25,4 @@ public static void main(String[] args){ p.sayHello(); } -} +} \ No newline at end of file diff --git a/group12/446031103/src/com/coderising/jvm/util/Util.java b/group12/446031103/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group12/446031103/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= 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(); + } + + /*private static class Node { Node prev; Node next; @@ -38,12 +194,12 @@ public LRUPageFrame(int capacity) { first = new Node(); } - /** + *//** * 获取缓存中对象 * * @param key * @return - */ + *//* public void access(int pageNum) { if(null==this.last){ this.last = new Node(this.first,null,pageNum); @@ -153,6 +309,6 @@ public String toString(){ } } return buffer.toString(); - } + }*/ } \ No newline at end of file diff --git a/group12/446031103/src/com/datastructure/stack/Stack.java b/group12/446031103/src/com/datastructure/stack/Stack.java new file mode 100644 index 0000000000..82cdf178a6 --- /dev/null +++ b/group12/446031103/src/com/datastructure/stack/Stack.java @@ -0,0 +1,83 @@ +package com.datastructure.stack; + +import com.datastructure.array.ArrayList; + +/** + * + * 栈-先进后出 + * + * @ClassName Stack + * @author msh + * @date 2017年2月21日 下午9:05:39 + */ +public class Stack { + + private ArrayList elementData = new ArrayList(); + /** + * + * 向栈中加入元素 + * + * @MethodName push + * @author msh + * @date 2017年2月21日 下午9:12:03 + * @param o + */ + public void push(Object o){ + elementData.add(o); + } + /** + * + * 从栈中取出元素 + * + * @MethodName pop + * @author msh + * @date 2017年2月21日 下午9:12:51 + * @return + */ + public Object pop(){ + Object o= peek(); + elementData.remove(size()-1); + return o; + } + /** + * + * 取出栈顶元素 + * + * @MethodName peek + * @author msh + * @date 2017年2月21日 下午9:13:08 + * @return + */ + public Object peek(){ + Object o=elementData.get(size()-1); + return o; + } + /** + * + * 判断栈中是否有元素 + * + * @MethodName isEmpty + * @author msh + * @date 2017年2月21日 下午9:14:26 + * @return + */ + public boolean isEmpty(){ + boolean temp = false; + if(0==size()) + temp = true; + return temp; + } + /** + * + * 栈中有多少元素 + * + * @MethodName size + * @author msh + * @date 2017年2月21日 下午9:16:42 + * @return + */ + public int size(){ + return elementData.size(); + } + +} diff --git a/group12/446031103/src/com/datastructure/stack/StackUtil.java b/group12/446031103/src/com/datastructure/stack/StackUtil.java new file mode 100644 index 0000000000..7cab99ede3 --- /dev/null +++ b/group12/446031103/src/com/datastructure/stack/StackUtil.java @@ -0,0 +1,107 @@ +package com.datastructure.stack; +import java.util.Objects; +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 temp = new Stack(); + while(!s.isEmpty()){ + temp.push(s.pop()); + } + s = temp; + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + Stack temp = new Stack(); + while(!s.isEmpty()){ + Object result=s.pop(); + if(Objects.equals(result, o)){ + continue; + } + temp.push(result); + } + while(!temp.isEmpty()){ + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + Object [] obj= new Object[len] ; + Stack temp = new Stack(); + for (int i = 0; i totalLen){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + return baos.toByteArray(); + */ + /** + * 开始读[0,1603] + 开始读[1604,3207] + is read length: 1024 + is read length: 1024 + baos.size: 1024 + baos.size: 1024 + 开始读[3208,4811] + is read length: 580 + baos.size: 1604 ///size会累积,等于度过的所有buffer size + is read length: 1024 + baos.size: 1024 + is read length: 580 + baos.size: 1604 + is read length: 580 + baos.size: 1604 + */ } @Override diff --git a/group14/1091149131/2017JavaPro/src/com/m0312/download/impl/ConnectionManagerImpl.java b/group14/1091149131/2017JavaPro/src/com/m0312/download/impl/ConnectionManagerImpl.java index 142b40f2ad..749ec78ca0 100644 --- a/group14/1091149131/2017JavaPro/src/com/m0312/download/impl/ConnectionManagerImpl.java +++ b/group14/1091149131/2017JavaPro/src/com/m0312/download/impl/ConnectionManagerImpl.java @@ -12,7 +12,7 @@ public class ConnectionManagerImpl implements ConnectionManager { @Override public Connection open(String url) throws ConnectionException { - Connection con=new ConnectionImpl(); + Connection con=new ConnectionImpl(url); try { URL website = new URL(url); diff --git a/group14/1091149131/2017JavaPro/src/com/test/TestDemo.java b/group14/1091149131/2017JavaPro/src/com/test/TestDemo.java new file mode 100644 index 0000000000..6bc901bc88 --- /dev/null +++ b/group14/1091149131/2017JavaPro/src/com/test/TestDemo.java @@ -0,0 +1,26 @@ +package com.test; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +public class TestDemo { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + String str="123bbb45ddd5ccc567ddd012"; + String[] data=str.split("[0-9]+"); + System.out.println("共拆分"+data.length); + for (String s : data) { + System.out.println(s); + } + System.out.println("===="); + fail("Not yet implemented"); + } + +} diff --git a/group14/1091149131/2017JavaPro/src/com/test/TestThread.java b/group14/1091149131/2017JavaPro/src/com/test/TestThread.java new file mode 100644 index 0000000000..543d52fca0 --- /dev/null +++ b/group14/1091149131/2017JavaPro/src/com/test/TestThread.java @@ -0,0 +1,37 @@ +package com.test; + +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +/** + * 所有线程都写完后,才能进行下面任务 + * @author Joy + */ +public class TestThread { + public static void main(String[] args) { + int N = 3; + CyclicBarrier barrier = new CyclicBarrier(N); + for(int i=0;i" + end); + this.start = start; + this.end = end; + this.is = is; + this.raf = raf; + } + + public void run() { + try { + is.skip(start); + raf.seek(start); + // 定义读取输入流内容的的缓存数组(竹筒) + byte[] buff = new byte[BUFF_LEN]; + // 本线程负责下载资源的大小 + long contentLen = end - start; + // 定义最多需要读取几次就可以完成本线程的下载 + long times = contentLen / BUFF_LEN + 4; + // 实际读取的字节数 + int hasRead = 0; + for (int i = 0; i < times; i++) { + hasRead = is.read(buff); + // 如果读取的字节数小于0,则退出循环! + if (hasRead < 0) { + break; + } + raf.write(buff, 0, hasRead); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + // 使用finally块来关闭当前线程的输入流、输出流 + finally { + try { + if (is != null) { + is.close(); + } + if (raf != null) { + raf.close(); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } +} diff --git a/group14/1091149131/2017JavaPro/src/com/test/downfile/MutilDown.java b/group14/1091149131/2017JavaPro/src/com/test/downfile/MutilDown.java new file mode 100644 index 0000000000..21aa754b8b --- /dev/null +++ b/group14/1091149131/2017JavaPro/src/com/test/downfile/MutilDown.java @@ -0,0 +1,73 @@ +package com.test.downfile; + +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.URL; +import java.net.URLConnection; + +public class MutilDown { + + public static void main(String[] args) { + //定义几个线程去下载 + final int DOWN_THREAD_NUM = 4; + final String OUT_FILE_NAME = "e:/testfile/down.png"; + InputStream[] isArr = new InputStream[DOWN_THREAD_NUM]; + RandomAccessFile[] outArr = new RandomAccessFile[DOWN_THREAD_NUM]; + try { + // 创建一个URL对象 + URL url = new URL("http://127.0.0.3:8082/applogo.png"); + //URL url = new URL("http://hiphotos.baidu.com/240728057/pic/item/6a50e38242aad8f60cf4d2b3.jpg"); + // 以此URL对象打开第一个输入流 + isArr[0] = url.openStream(); + long fileLen = getFileLength(url); + System.out.println("网络资源的大小" + fileLen); + // 以输出文件名创建第一个RandomAccessFile输出流 + //创建从中读取和向其中写入(可选)的随机存取文件流,第一个参数:文件名,第二个参数是:参数指定用以打开文件的访问模式 + //"rw"可能是可读可写, + outArr[0] = new RandomAccessFile(OUT_FILE_NAME, "rw"); + // 创建一个与下载资源相同大小的空文件 + for (int i = 0; i < fileLen; i++) { + outArr[0].write(0); + } + // 每线程应该下载的字节数 + long numPerThred = fileLen / DOWN_THREAD_NUM; + // 整个下载资源整除后剩下的余数取模 + long left = fileLen % DOWN_THREAD_NUM; + for (int i = 0; i < DOWN_THREAD_NUM; i++) { + // 为每个线程打开一个输入流、一个RandomAccessFile对象, + // 让每个线程分别负责下载资源的不同部分。 + //isArr[0]和outArr[0]已经使用,从不为0开始 + if (i != 0) { + // 以URL打开多个输入流 + isArr[i] = url.openStream(); + // 以指定输出文件创建多个RandomAccessFile对象 + outArr[i] = new RandomAccessFile(OUT_FILE_NAME, "rw"); + } + // 分别启动多个线程来下载网络资源 + if (i == DOWN_THREAD_NUM - 1) { + // 最后一个线程下载指定numPerThred+left个字节 + new DownThread(i * numPerThred, (i + 1) * numPerThred + + left, isArr[i], outArr[i]).start(); + } else { + // 每个线程负责下载一定的numPerThred个字节 + new DownThread(i * numPerThred, (i + 1) * numPerThred, + isArr[i], outArr[i]).start(); + } + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + // 定义获取指定网络资源的长度的方法 + public static long getFileLength(URL url) throws Exception { + long length = 0; + // 打开该URL对应的URLConnection + URLConnection con = url.openConnection(); + // 获取连接URL资源的长度 + long size = con.getContentLength(); + length = size; + return length; + } + +} diff --git a/group15/1507_977996067/src/task5/jvm/clz/AccessFlag.java b/group15/1507_977996067/src/task5/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..65e98c15e6 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package task5.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/task5/jvm/clz/ClassFile.java b/group15/1507_977996067/src/task5/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..46717e108e --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/clz/ClassFile.java @@ -0,0 +1,72 @@ +package task5.jvm.clz; + +import task5.jvm.constant.ClassInfo; +import task5.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/group15/1507_977996067/src/task5/jvm/clz/ClassIndex.java b/group15/1507_977996067/src/task5/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..5aba6a953a --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package task5.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/task5/jvm/constant/ClassInfo.java b/group15/1507_977996067/src/task5/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..6f8e5229cc --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/ConstantInfo.java b/group15/1507_977996067/src/task5/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..3e00cd378c --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/ConstantPool.java b/group15/1507_977996067/src/task5/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..6b0762c481 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/ConstantPool.java @@ -0,0 +1,37 @@ +package task5.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/task5/jvm/constant/FieldRefInfo.java b/group15/1507_977996067/src/task5/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..957d882b7a --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/MethodRefInfo.java b/group15/1507_977996067/src/task5/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..2a25d2cbee --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/NameAndTypeInfo.java b/group15/1507_977996067/src/task5/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..e3a65591f1 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/NullConstantInfo.java b/group15/1507_977996067/src/task5/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..a8895facd3 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package task5.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group15/1507_977996067/src/task5/jvm/constant/StringInfo.java b/group15/1507_977996067/src/task5/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..509a008b1d --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/constant/UTF8Info.java b/group15/1507_977996067/src/task5/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..05aec836eb --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package task5.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/group15/1507_977996067/src/task5/jvm/loader/ByteCodeIterator.java b/group15/1507_977996067/src/task5/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..d97ceb2d1b --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,43 @@ +package task5.jvm.loader; + +import task5.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 nextFlag() { + return nextBytes(1); + } + + public byte[] getBytes(int length) { + byte[] bytes = Arrays.copyOfRange(this.bytes, position, position + length); + position += length; + return bytes; + } + + 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/task5/jvm/loader/ClassFileLoader.java b/group15/1507_977996067/src/task5/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..4e0224e961 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/loader/ClassFileLoader.java @@ -0,0 +1,126 @@ +package task5.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 task5.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/group15/1507_977996067/src/task5/jvm/loader/ClassFileParser.java b/group15/1507_977996067/src/task5/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..573d76ceff --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/loader/ClassFileParser.java @@ -0,0 +1,77 @@ +package task5.jvm.loader; + +import task5.jvm.clz.AccessFlag; +import task5.jvm.clz.ClassFile; +import task5.jvm.clz.ClassIndex; +import task5.jvm.constant.*; + +public class ClassFileParser { + + 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()); + + classFile.setConstPool(parseConstantPool(iterator)); + classFile.setAccessFlag(parseAccessFlag(iterator)); + classFile.setClassIndex(parseClassIndex(iterator)); + + 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 ConstantPool 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); + } + } + return pool; + } + + +} diff --git a/group15/1507_977996067/src/task5/jvm/test/ClassFileloaderTest.java b/group15/1507_977996067/src/task5/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..610af464ef --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,191 @@ +package task5.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import task5.jvm.clz.ClassFile; +import task5.jvm.clz.ClassIndex; +import task5.jvm.constant.*; +import task5.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/task5/jvm/test/EmployeeV1.java b/group15/1507_977996067/src/task5/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..34ca61b3a8 --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +package task5.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/task5/jvm/util/Util.java b/group15/1507_977996067/src/task5/jvm/util/Util.java new file mode 100644 index 0000000000..0a37ea65ec --- /dev/null +++ b/group15/1507_977996067/src/task5/jvm/util/Util.java @@ -0,0 +1,23 @@ +package task5.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 MyLinkedList elementData = new MyLinkedList(); + + public void push(T o) { + elementData.addFirst(o); + } + + public T pop() { + return elementData.removeFirst(); + } + + public T peek() { + return elementData.get(0); + } + + public boolean isEmpty() { + return elementData.size() == 0; + } + + public int size() { + return elementData.size(); + } + +} diff --git a/group15/1507_977996067/src/task5/stack/StackUtil.java b/group15/1507_977996067/src/task5/stack/StackUtil.java new file mode 100644 index 0000000000..301399c4d5 --- /dev/null +++ b/group15/1507_977996067/src/task5/stack/StackUtil.java @@ -0,0 +1,87 @@ +package task5.stack; + +@SuppressWarnings("unchecked") +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 temp1 = new Stack(); + Stack temp2 = new Stack(); + int size = s.size(); + while (size > 0) { + temp1.push(s.pop()); + size--; + } + while (size > 0) { + temp2.push(temp1.pop()); + size--; + } + while (size > 0) { + s.push(temp2.pop()); + size--; + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static void remove(Stack s, Object o) { + Stack temp = new Stack(); + while (!s.isEmpty()) { + Object val = s.pop(); + if (val != o) + temp.push(val); + else break; + } + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + */ + public static Object[] getTop(Stack s, int len) { + if (len > 0 && len <= s.size()) { + Object[] result = new Object[len]; + while (len > 0) { + result[len--] = s.pop(); + } + return result; + } + return null; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + */ + public static boolean isValidPairs(String s) { + int length = s.length(); + int size = length / 2; + Stack temp1 = new Stack(); + Stack temp2 = new Stack(); + int position = 0; + while (position <= size) { + temp1.push(s.charAt(position)); + temp2.push(s.charAt(length - position)); + } + + int tempPosition = 0; + while (tempPosition <= size) { + if (temp1.pop() != temp2.pop()) { + return false; + } + } + return true; + } + + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task6/expr/InfixExpr.java b/group15/1507_977996067/src/task6/expr/InfixExpr.java new file mode 100644 index 0000000000..ae4dda95ad --- /dev/null +++ b/group15/1507_977996067/src/task6/expr/InfixExpr.java @@ -0,0 +1,80 @@ +package task6.expr; + +import org.junit.Assert; +import task5.stack.Stack; + +import java.util.Arrays; +import java.util.stream.Collectors; + +public class InfixExpr { + + private String expr; + + private Stack numberStack = new Stack<>(); + + private Stack resultStack = new Stack<>(); + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + Assert.assertNotNull(expr); + + String[] operators = expr.split("[\\d]+"); + + int length = operators.length; + + Arrays.stream(expr.split("[+\\-*/]+")) + .map(Float::parseFloat) + .forEach(numberStack::push); + + numberStack = reverse(numberStack); + + resultStack.push(numberStack.pop()); + + for (int i = 1; i < length; i++) { + String currentOperator = operators[i]; +// 先做乘除,结果放resultStack里面 + switch (currentOperator) { + case "*": + resultStack.push(resultStack.pop() * numberStack.pop()); + break; + case "/": + resultStack.push(resultStack.pop() / numberStack.pop()); + break; + case "+": + resultStack.push(numberStack.pop()); + break; + case "-": + resultStack.push(numberStack.pop()); + break; + } + } + + resultStack = reverse(resultStack); + +// 做加减 + for (int i = 1; i < length; i++) { + String currentOperator = operators[i]; + if ("+".equals(currentOperator)) { + Float num1 = resultStack.pop(); + Float num2 = resultStack.pop(); + resultStack.push(num1 + num2); + } else if ("-".equals(currentOperator)) { + Float num1 = resultStack.pop(); + Float num2 = resultStack.pop(); + resultStack.push(num1 - num2); + } + } + return resultStack.peek(); + } + + private Stack reverse(Stack stackToReverse) { + Stack temp = new Stack<>(); + while (!stackToReverse.isEmpty()) + temp.push(stackToReverse.pop()); + return temp; + } +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task6/expr/InfixExprTest.java b/group15/1507_977996067/src/task6/expr/InfixExprTest.java new file mode 100644 index 0000000000..487b23a040 --- /dev/null +++ b/group15/1507_977996067/src/task6/expr/InfixExprTest.java @@ -0,0 +1,56 @@ +package task6.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +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); + } + + } + + @Test + public void testExprSplit() { + String expr = "3*20+12*5-40/2"; + Arrays.stream(expr.split("[+\\-*/]+")).forEach(System.out::println); + Arrays.stream(expr.split("[\\d]+")).forEach(System.out::println); + } + +} \ No newline at end of file diff --git a/group15/1507_977996067/src/task6/jvm/attr/AttributeInfo.java b/group15/1507_977996067/src/task6/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..22b7eb0ae0 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package task6.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/task6/jvm/attr/CodeAttr.java b/group15/1507_977996067/src/task6/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..301be0c14d --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/attr/CodeAttr.java @@ -0,0 +1,120 @@ +package task6.jvm.attr; + + +import task6.jvm.clz.ClassFile; +import task6.jvm.constant.ConstantPool; +import task6.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 = ByteCodeCommand.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 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/task6/jvm/attr/LocalVariableItem.java b/group15/1507_977996067/src/task6/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..78a2ac90b2 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package task6.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/task6/jvm/attr/LocalVariableTable.java b/group15/1507_977996067/src/task6/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..ec855987e1 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/attr/LocalVariableTable.java @@ -0,0 +1,57 @@ +package task6.jvm.attr; + + +import task6.jvm.constant.ConstantPool; +import task6.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/task6/jvm/attr/StackMapTable.java b/group15/1507_977996067/src/task6/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..8206b23797 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package task6.jvm.attr; + + +import task6.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/task6/jvm/clz/AccessFlag.java b/group15/1507_977996067/src/task6/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..5f2b079628 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package task6.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/task6/jvm/clz/ClassFile.java b/group15/1507_977996067/src/task6/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..f4e2c14bfb --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/clz/ClassFile.java @@ -0,0 +1,115 @@ +package task6.jvm.clz; + +import task6.jvm.constant.ClassInfo; +import task6.jvm.constant.ConstantPool; +import task6.jvm.field.Field; +import task6.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()); + + + } + + 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/group15/1507_977996067/src/task6/jvm/clz/ClassIndex.java b/group15/1507_977996067/src/task6/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..3460eacda5 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package task6.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/task6/jvm/constant/ClassInfo.java b/group15/1507_977996067/src/task6/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c9fa227420 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/ConstantInfo.java b/group15/1507_977996067/src/task6/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..5aaa5551e9 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/ConstantPool.java b/group15/1507_977996067/src/task6/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..e4f9e4cbc9 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/ConstantPool.java @@ -0,0 +1,37 @@ +package task6.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/task6/jvm/constant/FieldRefInfo.java b/group15/1507_977996067/src/task6/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..19c9cee941 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/MethodRefInfo.java b/group15/1507_977996067/src/task6/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..d39ccb2f1d --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/NameAndTypeInfo.java b/group15/1507_977996067/src/task6/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..a4164137db --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/NullConstantInfo.java b/group15/1507_977996067/src/task6/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fcadb33142 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package task6.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group15/1507_977996067/src/task6/jvm/constant/StringInfo.java b/group15/1507_977996067/src/task6/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..799f77598a --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/constant/UTF8Info.java b/group15/1507_977996067/src/task6/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..2df6a00f77 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package task6.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/group15/1507_977996067/src/task6/jvm/field/Field.java b/group15/1507_977996067/src/task6/jvm/field/Field.java new file mode 100644 index 0000000000..0c42b23787 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/field/Field.java @@ -0,0 +1,48 @@ +package task6.jvm.field; + + +import task6.jvm.constant.ConstantPool; +import task6.jvm.constant.UTF8Info; +import task6.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/task6/jvm/loader/ByteCodeIterator.java b/group15/1507_977996067/src/task6/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..b1d950b29c --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,56 @@ +package task6.jvm.loader; + +import task6.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/task6/jvm/loader/ClassFileLoader.java b/group15/1507_977996067/src/task6/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..6e09f888b5 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/loader/ClassFileLoader.java @@ -0,0 +1,122 @@ +package task6.jvm.loader; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import task6.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/task6/jvm/loader/ClassFileParser.java b/group15/1507_977996067/src/task6/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..a00f1b342e --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/loader/ClassFileParser.java @@ -0,0 +1,112 @@ +package task6.jvm.loader; + +import task6.jvm.clz.AccessFlag; +import task6.jvm.clz.ClassFile; +import task6.jvm.clz.ClassIndex; +import task6.jvm.constant.*; +import task6.jvm.field.Field; +import task6.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/task6/jvm/method/Method.java b/group15/1507_977996067/src/task6/jvm/method/Method.java new file mode 100644 index 0000000000..3b6bafa893 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/method/Method.java @@ -0,0 +1,91 @@ +package task6.jvm.method; + +import task6.jvm.attr.AttributeInfo; +import task6.jvm.attr.CodeAttr; +import task6.jvm.clz.ClassFile; +import task6.jvm.constant.ConstantPool; +import task6.jvm.constant.UTF8Info; +import task6.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.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; + + } +} diff --git a/group15/1507_977996067/src/task6/jvm/test/ClassFileloaderTest.java b/group15/1507_977996067/src/task6/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..b904b45388 --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,191 @@ +package task6.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import task6.jvm.clz.ClassFile; +import task6.jvm.clz.ClassIndex; +import task6.jvm.constant.*; +import task6.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/task6/jvm/test/EmployeeV1.java b/group15/1507_977996067/src/task6/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..6c894392dd --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +package task6.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/task6/jvm/util/Util.java b/group15/1507_977996067/src/task6/jvm/util/Util.java new file mode 100644 index 0000000000..a9e2cebf5c --- /dev/null +++ b/group15/1507_977996067/src/task6/jvm/util/Util.java @@ -0,0 +1,23 @@ +package task6.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 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/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/FieldRefInfo.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..1fc5bee059 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.bruce.homework0409.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/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/MethodRefInfo.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..e6cfe7d0a4 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.bruce.homework0409.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/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NameAndTypeInfo.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..aff23210a4 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.bruce.homework0409.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/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NullConstantInfo.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..e5c505e530 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.bruce.homework0409.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/StringInfo.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..944062270d --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.bruce.homework0409.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/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/UTF8Info.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..4c2d3b2783 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.bruce.homework0409.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/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ByteCodeIterator.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..f33ae3a203 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,50 @@ +package com.bruce.homework0409.jvm.loader; + +import com.bruce.homework0409.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 byte[] getBytes(int len) { + if (pos + len >= codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + byte[] array = Arrays.copyOfRange(codes, pos, pos + len); + pos += len; + return array; + } + + 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) { + if (len < 1) { + return null; + } + byte[] array = new byte[len]; + for (int i = 0; i < len; i++) { + array[i] = codes[pos++]; + } + return Util.byteToHexString(array); + } +} diff --git a/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ClassFileLoader.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..0b4d6ad870 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/loader/ClassFileLoader.java @@ -0,0 +1,102 @@ +package com.bruce.homework0409.jvm.loader; + +import com.bruce.homework0409.jvm.clz.ClassFile; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +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; + +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/group15/1510_739253131/src/com/bruce/homework0409/jvm/test/EmployeeV1.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..6e3cfdca42 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.bruce.homework0409.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/1510_739253131/src/com/bruce/homework0409/jvm/util/Util.java b/group15/1510_739253131/src/com/bruce/homework0409/jvm/util/Util.java new file mode 100644 index 0000000000..f316c1f339 --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.bruce.homework0409.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; j--) { + s.push(array[j]); + if (array.length-1-j < len) { + result[array.length-1-j] = array[j]; + } + } + 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 == null || s.trim().length() < 2) { + return false; + } + char[] array = s.toCharArray(); + StringBuffer sb = new StringBuffer("#"); + //从原字符串中提取出“()[]{}”这几种字符,顺序与在原字符串中出现的顺序相同 + for (int i = 0; i < array.length; i++) { + if (array[i] == '(' || array[i] == ')' || array[i] == '[' || array[i] == ']' + || array[i] == '{' || array[i] == '}') { + sb.append(array[i]); + } + } + if (sb.length() % 2 == 0) { + return false; + } + //将得到的新的字符串拆分为字符数组,根据数组下标判断应该成对出现的括号 + String str = sb.toString(); + char[] chars = str.toCharArray(); + LinkedHashMap map = new LinkedHashMap(); + for (int i = 1; i < chars.length; i++) { + if (map.containsKey(chars[i])) { + map.put(chars[i], map.get(chars[i]) + i); + } else { + map.put(chars[i], i); + } + } + if (map.containsKey('(') && !map.containsKey(')') || map.containsKey('[') && !map.containsKey(']') + || map.containsKey('{') && !map.containsKey('}')) { + return false; + } + int parentheses = map.get('(') + map.get(')'); + int bracket = map.get('[') + map.get(']'); + int brace = map.get('{') + map.get('}'); + return parentheses == bracket && bracket == brace; + } +} diff --git a/group15/1510_739253131/src/com/bruce/homework0409/stack/StackUtilTest.java b/group15/1510_739253131/src/com/bruce/homework0409/stack/StackUtilTest.java new file mode 100644 index 0000000000..e66a6e98aa --- /dev/null +++ b/group15/1510_739253131/src/com/bruce/homework0409/stack/StackUtilTest.java @@ -0,0 +1,55 @@ +package com.bruce.homework0409.stack; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Stack; + +/** + * Created by Bruce.Jiao on 2017/4/8. + */ +public class StackUtilTest { + + private Stack stack; + + @Before + public void create() { + stack = new Stack<>(); + stack.push(3); + stack.push(5); + stack.push(6); + stack.push(9); + stack.push(0); + } + + @Test + public void testReverse() { + System.out.println("original:" + stack.toString()); + stack = StackUtil.reverse(stack); + System.out.println("after reverse:" + stack.toString()); + } + + @Test + public void testRemove() { + System.out.println("original:" + stack.toString()); + StackUtil.remove(stack, 5); + System.out.println("after remove 5 :" + stack.toString()); + } + + @Test + public void testGetTop() { + System.out.println("original:" + stack.toString()); + Object[] top = StackUtil.getTop(stack, 3); + System.out.println("get top 3 :" + Arrays.toString(top)); + System.out.println("after get top :" + stack.toString()); + } + + @Test + public void test() { + System.out.println("({[e({d})f]}) : " + StackUtil.isValidPairs("({[e({d})f]})")); + System.out.println("(d)" + StackUtil.isValidPairs("(d)")); + System.out.println("([b{x]y})" + StackUtil.isValidPairs("([b{x]y})")); + } +} diff --git a/group15/1511_714512544/.idea/modules.xml b/group15/1511_714512544/.idea/modules.xml index 0ed960e3bf..77979d8e9c 100644 --- a/group15/1511_714512544/.idea/modules.xml +++ b/group15/1511_714512544/.idea/modules.xml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/group15/1511_714512544/.idea/workspace.xml b/group15/1511_714512544/.idea/workspace.xml index 79ca1863c1..630f12e7ca 100644 --- a/group15/1511_714512544/.idea/workspace.xml +++ b/group15/1511_714512544/.idea/workspace.xml @@ -1,7 +1,30 @@ - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -89,6 +113,7 @@ + @@ -178,7 +203,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - @@ -664,6 +710,13 @@ + + + + + + + @@ -744,12 +797,6 @@ - project - - - - - @@ -778,173 +825,64 @@ - - - - - - + + - - - - - - + + - - - - - 1488937211416 + + 1491741542361 - - 1488937445293 - - - 1489156650791 - - - 1489206126088 - - - 1489209258691 - - - 1489211483985 - - - 1489303022487 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - + + @@ -971,22 +909,8 @@ - - - - - - - file://$PROJECT_DIR$/src/com/coderising/download/FileDownloaderTest.java - 39 - - - - + @@ -994,387 +918,104 @@ - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + - + - - + + + - + - - + + + - + - - + + + - + - - + + + - + - - + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - - - - - - - - - - - - - - - - - + + - - - - - + - + - - + + - - - - - - - - - - - - + - - + + - - + diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/ConnectionTest.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/ConnectionTest.class new file mode 100644 index 0000000000..f163627946 Binary files /dev/null and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/ConnectionTest.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/DownloadThread.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/DownloadThread.class index cc15cd0084..f1a7edc3ff 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/DownloadThread.class and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/DownloadThread.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader$1.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader$1.class new file mode 100644 index 0000000000..548ab88f2d Binary files /dev/null and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader$1.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader.class index a72c54e489..40bd7f6b60 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader.class and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloader.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloaderTest.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloaderTest.class index 4746ef8b01..8b742b607f 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloaderTest.class and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/FileDownloaderTest.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionImpl.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionImpl.class index b4a5c8354f..68b0f11984 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionImpl.class and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionImpl.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionManagerImpl.class b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionManagerImpl.class index 1aec4647ba..50e93bc174 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionManagerImpl.class and b/group15/1511_714512544/out/production/1511_714512544/com/coderising/download/impl/ConnectionManagerImpl.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/BinarySearchTree.class b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/BinarySearchTree.class index 5998f97032..05ab8c349b 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/BinarySearchTree.class and b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/BinarySearchTree.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST$Node.class b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST$Node.class new file mode 100644 index 0000000000..408bbfa3fd Binary files /dev/null and b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST$Node.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST.class b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST.class new file mode 100644 index 0000000000..c998fe6a42 Binary files /dev/null and b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBST.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBSTTest.class b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBSTTest.class new file mode 100644 index 0000000000..a2d0244656 Binary files /dev/null and b/group15/1511_714512544/out/production/1511_714512544/com/coding/basic/ReConstructBSTTest.class differ diff --git a/group15/1511_714512544/out/production/1511_714512544/test/com/coding/basic/BinarySearchTreeTest.class b/group15/1511_714512544/out/production/1511_714512544/test/com/coding/basic/BinarySearchTreeTest.class index 167f83c32c..8fd0bf539b 100644 Binary files a/group15/1511_714512544/out/production/1511_714512544/test/com/coding/basic/BinarySearchTreeTest.class and b/group15/1511_714512544/out/production/1511_714512544/test/com/coding/basic/BinarySearchTreeTest.class differ diff --git a/group15/1511_714512544/src/com/coderising/download/ConnectionTest.java b/group15/1511_714512544/src/com/coderising/download/ConnectionTest.java new file mode 100644 index 0000000000..247817cf42 --- /dev/null +++ b/group15/1511_714512544/src/com/coderising/download/ConnectionTest.java @@ -0,0 +1,53 @@ +package com.coderising.download; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.impl.ConnectionManagerImpl; + + + +public class ConnectionTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testContentLength() throws Exception{ + 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 Exception{ + + 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, 35469); + + 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/group15/1511_714512544/src/com/coderising/download/DownloadThread.java b/group15/1511_714512544/src/com/coderising/download/DownloadThread.java index 9173329f7b..cf3c0dcadb 100644 --- a/group15/1511_714512544/src/com/coderising/download/DownloadThread.java +++ b/group15/1511_714512544/src/com/coderising/download/DownloadThread.java @@ -1,58 +1,39 @@ package com.coderising.download; import com.coderising.download.api.Connection; -import com.coderising.download.api.DownloadListener; -import com.coderising.download.impl.ConnectionImpl; -import com.coderising.download.impl.ConnectionManagerImpl; -import java.io.IOException; import java.io.RandomAccessFile; -import java.net.URL; +import java.util.concurrent.CyclicBarrier; public class DownloadThread extends Thread{ + Connection conn; int startPos; int endPos; - String url; String savePath; - DownloadListener listener; - private static int count = 0; - private Object lock = new Object(); //对象锁 + CyclicBarrier barrier; //栅栏 - public DownloadThread(String url, String savePath, DownloadListener listener, int startPos, int endPos){ + public DownloadThread(Connection conn, int startPos, int endPos, String savePath, CyclicBarrier barrier){ this.startPos = startPos; this.endPos = endPos; - this.url = url; + this.conn = conn; this.savePath = savePath; - this.listener = listener; + this.barrier = barrier; } public void run(){ RandomAccessFile raf = null; //实现 try { - Connection conn = new ConnectionManagerImpl().open(url); - raf = new RandomAccessFile(savePath,"rwd"); - + RandomAccessFile file = new RandomAccessFile(savePath,"rw"); byte[] data= conn.read(startPos,endPos); raf.seek(startPos); raf.write(data); - synchronized (lock){ //加对象锁 - count ++; - if(count == 3){ - listener.notifyFinished(); - } - } + raf.close(); + conn.close(); + barrier.await(); //等待其他线程执行到这里,//等待别的线程完成 } catch (Exception e) { throw new RuntimeException("读取错误"); - }finally { - try { - if(raf != null){ - raf.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } } } } diff --git a/group15/1511_714512544/src/com/coderising/download/FileDownloader.java b/group15/1511_714512544/src/com/coderising/download/FileDownloader.java index c620180530..f4351d66f1 100644 --- a/group15/1511_714512544/src/com/coderising/download/FileDownloader.java +++ b/group15/1511_714512544/src/com/coderising/download/FileDownloader.java @@ -1,27 +1,32 @@ package com.coderising.download; +import java.io.IOException; +import java.io.RandomAccessFile; +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; -import com.coderising.download.impl.ConnectionManagerImpl; -import java.io.RandomAccessFile; -/** - * 文件下载器 - */ public class FileDownloader { - String url; //下载路径 - String savePath = "d:/1.png"; //保存路径 - DownloadListener listener ; //下载监听器 - ConnectionManager cm ; //连接管理 - public FileDownloader(String _url) { + private String url; + private String savepath; + + DownloadListener listener; + + ConnectionManager cm; + + + private static final int DOWNLOAD_TRHEAD_NUM = 3; + + public FileDownloader(String _url, String savepath) { this.url = _url; - + this.savepath = savepath; + } - + public void execute(){ // 在这里实现你的代码, 注意: 需要用多线程实现下载 // 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 @@ -34,48 +39,92 @@ public void execute(){ // 然后调用read方法, read方法中有读取文件的开始位置和结束位置的参数, 返回值是byte[]数组 // 3. 把byte数组写入到文件中 // 4. 所有的线程都下载完成以后, 需要调用listener的notifiedFinished方法 - + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 - Connection conn = null; - RandomAccessFile raf = null; + + //栅栏 + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_TRHEAD_NUM , new Runnable(){ + public void run(){ + listener.notifyFinished(); //所有线程到了之后执行 + } + }); + + Connection conn = null; try { - cm = new ConnectionManagerImpl(); - conn = cm.open(this.url); + + conn = cm.open(this.url); + int length = conn.getContentLength(); - raf = new RandomAccessFile(savePath,"rwd"); - if(raf.length() == 0){ - raf.setLength(length); - } - raf.close(); - - for (int i = 0; i <= 2; i++) { - int startPos = i*length/3; - int endPos = length*(i+1)/3-1; - if(i == 2) { - endPos = length-1; - } - new DownloadThread(url, savePath,listener ,startPos, endPos).start(); + createPlaceHolderFile(this.savepath, length); + + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); + + for(int i=0; i< DOWNLOAD_TRHEAD_NUM; i++){ + + + DownloadThread thread = new DownloadThread( + cm.open(url),ranges[i][0], ranges[i][1], savepath, barrier ); + + thread.start(); } } catch (Exception e) { e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + + } + //占住磁盘位置 + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException{ + + RandomAccessFile file = new RandomAccessFile(fileName,"rw"); + + for(int i=0; i targetLen){ + byte[] result = bos.toByteArray(); + return Arrays.copyOf(result, targetLen); + } + return bos.toByteArray(); } /** * 得到数据内容的长度 @@ -47,22 +60,23 @@ public byte[] read(int startPos, int endPos) throws IOException { */ @Override public int getContentLength() { - return connection.getContentLength(); + HttpURLConnection conn; + + try { + conn = (HttpURLConnection) url.openConnection(); + return conn.getContentLength(); + } catch (IOException e) { + e.printStackTrace(); + } + return -1; + } /** * 关闭连接 */ @Override public void close() { - InputStream in; - try { - in = connection.getInputStream(); - if(in != null){ - in.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } + } } diff --git a/group15/1511_714512544/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group15/1511_714512544/src/com/coderising/download/impl/ConnectionManagerImpl.java index 55d27dc156..ccb7907072 100644 --- a/group15/1511_714512544/src/com/coderising/download/impl/ConnectionManagerImpl.java +++ b/group15/1511_714512544/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -17,22 +17,7 @@ public class ConnectionManagerImpl implements ConnectionManager { */ @Override public Connection open(String url) throws ConnectionException { - try { - URL u = new URL(url); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setConnectTimeout(5000); - conn.setRequestMethod("GET"); - int code = conn.getResponseCode(); - if(code == 200){ - return new ConnectionImpl(conn); - }else { - throw new RuntimeException("打开连接失败"); - } - } catch (MalformedURLException e) { - throw new RuntimeException("url非法"); - } catch (IOException e) { - throw new RuntimeException("IO异常"); - } + return new ConnectionImpl(url); } } diff --git a/group15/1511_714512544/src/com/coderising/jvm/clz/AccessFlag.java b/group15/1511_714512544/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/clz/ClassFile.java b/group15/1511_714512544/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/clz/ClassIndex.java b/group15/1511_714512544/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/ClassInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/ConstantInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/ConstantPool.java b/group15/1511_714512544/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/FieldRefInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/MethodRefInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/NullConstantInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/StringInfo.java b/group15/1511_714512544/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/constant/UTF8Info.java b/group15/1511_714512544/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group15/1511_714512544/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..9c9fac2839 --- /dev/null +++ b/group15/1511_714512544/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,5 @@ +package com.coderising.jvm.loader; + +public class ByteCodeIterator { + +} diff --git a/group15/1511_714512544/src/com/coderising/jvm/loader/ClassFileLoader.java b/group15/1511_714512544/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/group15/1511_714512544/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/group15/1511_714512544/src/com/coderising/jvm/test/EmployeeV1.java b/group15/1511_714512544/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..e644b00b41 --- /dev/null +++ b/group15/1511_714512544/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,27 @@ +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/group15/1511_714512544/src/com/coderising/jvm/util/Util.java b/group15/1511_714512544/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group15/1511_714512544/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 n){ + if(n == null) return; + + Queue> queue = new LinkedList>(); + queue.offer(n); //入队列 + + while(!queue.isEmpty()){ + BinarySearchTreeNode node = queue.poll(); //出队列 + System.out.print(node.getData() + " "); + if(node.getLeft() != null) queue.offer(node.getLeft()); + if(node.getRight() != null) queue.offer(node.getRight()); + } + } + //删除某个节点n public void delete(BinarySearchTreeNode n){ BinarySearchTreeNode p = n.getParent(); //节点的父节点 @@ -313,6 +335,22 @@ public BinarySearchTreeNode findMax(BinarySearchTreeNode n){ return current; } + /* + 求树的高度(利用后序遍历) + */ + public int postOrderGetHeight(BinarySearchTreeNode n){ + int hL = 0, hR = 0, maxH = 0; + + if(n != null){ + hL = postOrderGetHeight(n.getLeft()); //求左子树深度 + hR = postOrderGetHeight(n.getRight()); //求右子树深度 + maxH = hL> hR? hL : hR ; //求左右子树深度最大的那个 + return (maxH+1);//返回树的深度 + } + return 0; //空树返回0 + } + + } diff --git a/group15/1511_714512544/src/com/coding/basic/LRUPageFrame.java b/group15/1511_714512544/src/com/coding/basic/LRUPageFrame.java new file mode 100644 index 0000000000..a1c4777af2 --- /dev/null +++ b/group15/1511_714512544/src/com/coding/basic/LRUPageFrame.java @@ -0,0 +1,148 @@ +package com.coding.basic; + +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 pageNum + * @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/group15/1511_714512544/src/com/coding/basic/LRUPageFrameTest.java b/group15/1511_714512544/src/com/coding/basic/LRUPageFrameTest.java new file mode 100644 index 0000000000..9ea9809f10 --- /dev/null +++ b/group15/1511_714512544/src/com/coding/basic/LRUPageFrameTest.java @@ -0,0 +1,33 @@ +package com.coding.basic; + +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/group15/1511_714512544/src/com/coding/basic/ReConstructBST.java b/group15/1511_714512544/src/com/coding/basic/ReConstructBST.java new file mode 100644 index 0000000000..d8c7ac69e0 --- /dev/null +++ b/group15/1511_714512544/src/com/coding/basic/ReConstructBST.java @@ -0,0 +1,101 @@ +package com.coding.basic; + +import java.util.Queue; +import java.util.LinkedList; + +/** + * 由两种遍历结果确定二叉树(其中一个结果必须是中序遍历的结果) + */ +public class ReConstructBST{ + /** + * 前序遍历与中序遍历序列重建二叉树 + * @param preOrder 前序结果 + * @param inOrder 中序结果 + * @return root元素 + */ + public static Node construct(int[] preOrder, int[] inOrder){ + if(preOrder == null || inOrder == null || preOrder.length<=0||inOrder.length<=0) return null; + + return reConstruct(preOrder, 0 ,preOrder.length-1, inOrder,0, inOrder.length-1); + } + + /** + * + * @param preOrder 前序序列 + * @param ps 前序序列开始索引 + * @param pe 前序序列结束索引 + * @param inOrder 中序序列 + * @param is 中序序列开始索引 + * @param ie 中序序列结束索引 + * @return 本次的根节点 + */ + private static Node reConstruct(int[] preOrder, int ps, int pe, int[] inOrder, int is, int ie){ + int rootValue = preOrder[ps]; + Node root = new Node(rootValue); + //只有一个元素 + if(ps == pe){ + if(is == ie && preOrder[ps] == inOrder[is]){ + return root; + } + throw new RuntimeException("输入错误!"); + } + + //不止有一个元素,在中序遍历中找到根节点的位置 + int rootIndexInOrder = is; + while(rootIndexInOrder <= ie && inOrder[rootIndexInOrder]!=rootValue) rootIndexInOrder++; + + int lCTLengthInOrder = rootIndexInOrder - is; //左子树长度 + int lCTEndIndexPreOrder = ps + lCTLengthInOrder; //左子树末尾节点在前序遍历序列中的位置 + if(lCTLengthInOrder > 0){ + //左子树有元素,构建左子树 + root.left = reConstruct(preOrder, ps+1, lCTEndIndexPreOrder, inOrder, is, rootIndexInOrder-1); + } + if(lCTLengthInOrder < (pe-ps)){ + //有字数有元素,构建右子树 + root.right = reConstruct(preOrder, lCTEndIndexPreOrder+1, pe, inOrder, rootIndexInOrder+1, ie); + } + + return root; + } + + public static void printInPostOrder(Node n){ + if(n.left != null){ + printInPostOrder(n.left); + } + + if(n.right != null){ + printInPostOrder(n.right); + } + + System.out.print(n.data+" "); + } + + public static void traveralByLevel(Node n){ + if(n == null) return; + + Queue queue = new LinkedList(); + queue.offer(n); + + while(!queue.isEmpty()){ + Node node = queue.poll(); + System.out.print(node.data + " "); + if(node.left != null) queue.offer(node.left); + if(node.right != null) queue.offer(node.right); + } + } + + + //节点 + public static class Node{ + int data; + Node left; + Node right; + public Node(int data) { + this.data = data; + this.left = null; + this.right = null; + } + } +} + + diff --git a/group15/1511_714512544/src/com/coding/basic/ReConstructBSTTest.java b/group15/1511_714512544/src/com/coding/basic/ReConstructBSTTest.java new file mode 100644 index 0000000000..623cc4c470 --- /dev/null +++ b/group15/1511_714512544/src/com/coding/basic/ReConstructBSTTest.java @@ -0,0 +1,31 @@ +package com.coding.basic; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * 二叉树重建测试 + */ +public class ReConstructBSTTest { + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + + } + + @Test + public void construct() throws Exception { + int[] preOrder = {1,2,3,4,5,6,7}; + int[] inOrder = {3,2,4,1,6,5,7}; + ReConstructBST.Node n = ReConstructBST.construct(preOrder,inOrder); + ReConstructBST.traveralByLevel(n); + } + +} \ No newline at end of file diff --git a/group15/1511_714512544/src/test/com/coding/basic/BinarySearchTreeTest.java b/group15/1511_714512544/src/test/com/coding/basic/BinarySearchTreeTest.java index 3b7102e5cd..f82f485e02 100644 --- a/group15/1511_714512544/src/test/com/coding/basic/BinarySearchTreeTest.java +++ b/group15/1511_714512544/src/test/com/coding/basic/BinarySearchTreeTest.java @@ -3,13 +3,15 @@ import static org.junit.Assert.*; import com.coding.basic.BinarySearchTree; +import org.junit.After; +import org.junit.Before; import org.junit.Test; public class BinarySearchTreeTest { - - @Test - public void testInsert() { - BinarySearchTree bst = new BinarySearchTree(); + BinarySearchTree bst = null; + @Before + public void setUp() throws Exception { + bst = new BinarySearchTree(); bst.insert(5); bst.insert(2); bst.insert(7); @@ -19,95 +21,60 @@ public void testInsert() { bst.insert(8); } + @After + public void tearDown() throws Exception { + + } + + @Test + public void testInsert() { + } + @Test public void testContains() { - BinarySearchTree bst = new BinarySearchTree(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); assertEquals(true,bst.contains(8)); } @Test public void testPreOrder(){ - BinarySearchTree bst = new BinarySearchTree(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.preOrder(bst.getRoot()); } @Test public void testPreOrderWithoutRecursion(){ - BinarySearchTree bst = new BinarySearchTree<>(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.preOrderWithoutRecursion(); } @Test public void testMidOrder(){ - BinarySearchTree bst = new BinarySearchTree(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.midOrder(bst.getRoot()); } @Test public void testMidOrderWithoutRecursion(){ - BinarySearchTree bst = new BinarySearchTree<>(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.midOrderWithoutRecursion(); } @Test public void testPostOrder(){ - BinarySearchTree bst = new BinarySearchTree(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.postOrder(bst.getRoot()); } @Test public void testPostOrderWithoutRecursion(){ - BinarySearchTree bst = new BinarySearchTree<>(); - bst.insert(5); - bst.insert(2); - bst.insert(7); - bst.insert(1); - bst.insert(6); - bst.insert(4); - bst.insert(8); bst.postOrderWithoutRecursion(); } + @Test + public void traveralByLevel(){ + bst.traveralByLevel(bst.getRoot()); + } + + @Test + public void postOrderGetHeight(){ + int height = bst.postOrderGetHeight(bst.getRoot()); + assertEquals(3, height); + } + + } diff --git a/group15/1513_121469918/HomeWork/.gitignore b/group15/1513_121469918/HomeWork/.gitignore index c92e089b1e..e6416c5be6 100644 --- a/group15/1513_121469918/HomeWork/.gitignore +++ b/group15/1513_121469918/HomeWork/.gitignore @@ -1,3 +1,2 @@ /bin/ /lib/ -/.settings/ \ No newline at end of file diff --git a/group15/1513_121469918/HomeWork/src/task0409/coding/basic/stuck/StackUtil.java b/group15/1513_121469918/HomeWork/src/task0409/coding/basic/stuck/StackUtil.java new file mode 100644 index 0000000000..db2726b278 --- /dev/null +++ b/group15/1513_121469918/HomeWork/src/task0409/coding/basic/stuck/StackUtil.java @@ -0,0 +1,105 @@ +package task0409.coding.basic.stuck; + +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(null == s){ + 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(null == o|| null == s){ + return; + } + if(!s.isEmpty()){ + Object top = s.pop(); + remove(s,o); + if(top.equals(o)){ + return; + }else{ + s.push(top); + } + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, + * 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if(len<=0){ + return null; + } + Object[] result = new Object[len]; + Stack temp = new Stack(); + while(len>0){ + temp.push(s.pop()); + len--; + result[len] = temp.peek(); + } + 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) { + char[] chs = s.toCharArray(); + Stack left = new Stack(); + Stack right = new Stack(); + + for(int i=0;i oStack = new Stack<>(); + Stack nStack = new Stack<>(); + + TokenParser tp = new TokenParser(expr); + List array = tp.getParserList(); + + for (int i = 0; i < array.size(); i++) { + Token t = array.get(i); + String type = t.getType(); + + if(type.equals(Token.NUMBER)){ + nStack.push(Float.valueOf(t.getValue())); + }else if(type.equals(Token.OPERATOR)){ + if(oStack.isEmpty()||t.getLevel()>oStack.peek().getLevel()){ + oStack.push(t); + }else{ + nStack.push(operation(nStack,oStack)); + oStack.push(t); + } + } + } + while(!oStack.isEmpty()){ + nStack.push(operation(nStack,oStack)); + } + return nStack.peek(); + } + private Float operation(Stack nStack, Stack oStack) { + Float num1 = nStack.pop(); + Float num2 = nStack.pop(); + String operator = oStack.pop().getValue(); + + switch(operator){ + case "+": + return num2+num1; + case "-": + return num2-num1; + case "*": + return num2*num1; + case "/": + return num2/num1; + } + return null; + } + + + + +} diff --git a/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/InfixExprTest.java b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/InfixExprTest.java new file mode 100644 index 0000000000..ca93f9edad --- /dev/null +++ b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package task0416.coding.basic.stuck.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/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/Token.java b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/Token.java new file mode 100644 index 0000000000..50ae8f27aa --- /dev/null +++ b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/Token.java @@ -0,0 +1,36 @@ +package task0416.coding.basic.stuck.expr; + +public class Token { + static final String OPERATOR = "operator"; + static final String NUMBER = "number"; + static final int LEVEL_ADD_SUB = 1; + static final int LEVEL_MUL_DIV = 2; + + private String value; + private int level; + private String type; + + public Token(String type,String value){ + this.type = type; + this.value = value; + } + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + public int getLevel() { + return level; + } + public void setLevel(int level) { + this.level = level; + } + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } +} diff --git a/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/TokenParser.java b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/TokenParser.java new file mode 100644 index 0000000000..3ea319af4d --- /dev/null +++ b/group15/1513_121469918/HomeWork/src/task0416/coding/basic/stuck/expr/TokenParser.java @@ -0,0 +1,55 @@ +package task0416.coding.basic.stuck.expr; + +import java.util.ArrayList; +import java.util.List; + +import javax.print.attribute.standard.MediaSize.ISO; + +public class TokenParser { + private String expr; + + TokenParser(String expr){ + this.expr = expr; + } + + public List getParserList(){ + List array = new ArrayList<>(); + char[] chs = expr.toCharArray(); + int i = 0; + while(i0){ + 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableItem.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..afb7093863 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableTable.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..d8cb119b23 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,58 @@ +package coderising.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import coderising.jvm.constant.ConstantPool; + +import 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/StackMapTable.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..741820e732 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package coderising.jvm.attr; + + +import 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/AccessFlag.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..0719ffaa0b --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassFile.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..b56fc54162 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package coderising.jvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import coderising.jvm.constant.ClassInfo; +import coderising.jvm.constant.ConstantPool; +import coderising.jvm.field.Field; +import 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(); + } +} diff --git a/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassIndex.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..c58deb35b3 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ClassInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..4ed8312fd6 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..3dfcb48b74 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantPool.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..59128f899c --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/FieldRefInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7b1662b050 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/MethodRefInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f051473836 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NameAndTypeInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..af711bd28e --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NullConstantInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..cfbe82ac9d --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/StringInfo.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..8582ac7ac5 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/UTF8Info.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..f17afdc541 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/field/Field.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..69f08d350d --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/field/Field.java @@ -0,0 +1,50 @@ +package coderising.jvm.field; + +import coderising.jvm.constant.ConstantPool; +import coderising.jvm.constant.UTF8Info; +import 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ByteCodeIterator.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..bee04eb8ed --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,50 @@ +package coderising.jvm.loader; + +import java.util.Arrays; + +import coderising.jvm.util.Util; + +public class ByteCodeIterator { + private byte[] codes; + private 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 String nextU4ToHexString() { + byte[] bys = new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}; + return Util.byteToHexString(bys); + } + + public int nextU1ToInt(){ + byte[] bys = new byte[]{codes[pos++]}; + return Util.byteToInt(bys); + } + public int nextU2ToInt(){ + byte[] bys = new byte[]{codes[pos++],codes[pos++]}; + return Util.byteToInt(bys); + } + 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 int nextU4ToInt() { + return Util.byteToInt(new byte[] { codes[pos++], codes[pos++], codes[pos++], codes[pos++] }); + } +} diff --git a/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ClassFileLoader.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..c268287a98 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,136 @@ +package 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 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); + } + + +} diff --git a/group15/1513_121469918/mini-jvm/src/coderising/jvm/test/EmployeeV1.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..2261019193 --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package 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/group15/1513_121469918/mini-jvm/src/coderising/jvm/util/Util.java b/group15/1513_121469918/mini-jvm/src/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..ce3848b9df --- /dev/null +++ b/group15/1513_121469918/mini-jvm/src/coderising/jvm/util/Util.java @@ -0,0 +1,24 @@ +package 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) throws Exception { + String filePath = clzPaths.get(0)+File.separatorChar+className.replace('.',File.separatorChar)+".class"; + File file = new File(filePath); + + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + byte[] buffer = new byte[1024]; + int len = 0; + while((len = bis.read(buffer)) != -1){ + baos.write(buffer,0,len); + } + return baos.toByteArray(); + } + + public void addClassPath(String path) { + if (clzPaths.contains(path)) + return; + clzPaths.add(path); + } + + public String getClassPath(){ + return StringUtils.join(clzPaths,";"); + } + +} diff --git a/group15/1521_653895972/src/task4/jvm/test/ClassFileloaderTest.java b/group15/1521_653895972/src/task4/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..5b037ffe5d --- /dev/null +++ b/group15/1521_653895972/src/task4/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,83 @@ +package task4.jvm.test; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import task4.jvm.loader.ClassFileLoader; + + +public class ClassFileloaderTest { + + + static String path1 = "D:\\oneces\\GitHub\\coding2017\\group15\\1521_653895972\\out\\production\\1521_653895972"; + 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() throws Exception { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "task4.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1038, byteCodes.length); + + } + + + @Test + public void testMagicNumber() throws Exception{ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "task4.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= 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/group15/1521_653895972/src/task4/linklist/LRUPageFrameTest.java b/group15/1521_653895972/src/task4/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..5ebfe09c0f --- /dev/null +++ b/group15/1521_653895972/src/task4/linklist/LRUPageFrameTest.java @@ -0,0 +1,34 @@ +package task4.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()); + System.out.println("3232"); + } + +} diff --git a/group15/1521_653895972/src/task5/jvm/clz/AccessFlag.java b/group15/1521_653895972/src/task5/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..65e98c15e6 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package task5.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/1521_653895972/src/task5/jvm/clz/ClassFile.java b/group15/1521_653895972/src/task5/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..5e60ab4b81 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/clz/ClassFile.java @@ -0,0 +1,76 @@ +package task5.jvm.clz; + + +import task5.jvm.constant.ClassInfo; +import task5.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/group15/1521_653895972/src/task5/jvm/clz/ClassIndex.java b/group15/1521_653895972/src/task5/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..5aba6a953a --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package task5.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/1521_653895972/src/task5/jvm/constant/ClassInfo.java b/group15/1521_653895972/src/task5/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..6f8e5229cc --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/ConstantInfo.java b/group15/1521_653895972/src/task5/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..3e00cd378c --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/ConstantPool.java b/group15/1521_653895972/src/task5/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..eb6eb2b692 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/FieldRefInfo.java b/group15/1521_653895972/src/task5/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..957d882b7a --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/MethodRefInfo.java b/group15/1521_653895972/src/task5/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..2a25d2cbee --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/NameAndTypeInfo.java b/group15/1521_653895972/src/task5/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..e3a65591f1 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/NullConstantInfo.java b/group15/1521_653895972/src/task5/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..a8895facd3 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package task5.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group15/1521_653895972/src/task5/jvm/constant/StringInfo.java b/group15/1521_653895972/src/task5/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..509a008b1d --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/constant/UTF8Info.java b/group15/1521_653895972/src/task5/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..05aec836eb --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package task5.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/group15/1521_653895972/src/task5/jvm/loader/ByteCodeIterator.java b/group15/1521_653895972/src/task5/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..20e12c3503 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,5 @@ +package task5.jvm.loader; + +public class ByteCodeIterator { + +} diff --git a/group15/1521_653895972/src/task5/jvm/loader/ClassFileLoader.java b/group15/1521_653895972/src/task5/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..3778d22280 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/loader/ClassFileLoader.java @@ -0,0 +1,132 @@ +package task5.jvm.loader; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import task5.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", 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/1521_653895972/src/task5/jvm/test/EmployeeV1.java b/group15/1521_653895972/src/task5/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..21d20a053c --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package task5.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/1521_653895972/src/task5/jvm/util/Util.java b/group15/1521_653895972/src/task5/jvm/util/Util.java new file mode 100644 index 0000000000..d274eacc08 --- /dev/null +++ b/group15/1521_653895972/src/task5/jvm/util/Util.java @@ -0,0 +1,24 @@ +package task5.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 array2[index_b]) { + array[i] = array2[index_b]; + index_b++; + i++; + } else { + array[i] = array1[index_a]; + i++; + index_a++; + index_b++; + } + } + if (index_a == array1.length) { + for (int j = index_b; j < array2.length; j++) { + array[i] = array2[j]; + i++; + } + } else { + for (int j = index_a; j < array1.length; j++) { + array[i] = array1[j]; + i++; + } + } + int[] result = new int[i]; + System.arraycopy(array,0,result,0,i); + return result; + } + + @Test + public void testMerge() { + int[] test1 = new int[]{2,3, 5, 7,8}; + int[] test2 = new int[]{4, 5, 6,7,8,21,33}; + int[] newArray = merge(test1,test2); + for (int i = 0; i < newArray.length; i++) { + System.out.println(newArray[i]); + } + } + /** + * 把一个已经存满数据的数组 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; + } + + @Test + public void testGrow() { + int[] test1 = new int[]{2,3, 5, 7,8}; + int[] newArray = grow(test1, 5); + for (int i = 0; i < newArray.length; i++) { + System.out.println(newArray[i]); + } + } + + /** + * 斐波那契数列为: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 index_a = 1; + int index_b = 1; + int temp = 0; + int count = 2; + while ((temp = index_a + index_b) < max) { + index_a = index_b; + index_b = temp; + count++; + } + int[] newArray = new int[count]; + for (int i = count-1; i > -1 ; i--) { + newArray[i] = index_b; + temp = index_b - index_a; + index_b = index_a; + index_a = temp; + } + return newArray; + } + + @Test + public void testfibonacci() { + int[] newArray = fibonacci(15); + for (int i = 0; i < newArray.length; i++) { + System.out.println(newArray[i]); + } + } + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * @param max + * @return + */ + public int[] getPrimes(int max){ + int[] container = new int[5]; + int count = 0; + for (int i = 3; i < max; i++) { + if (isShusu(i)) { + if (count == container.length) { + container = grow(container,container.length << 1); + } + container[count] = i; + count++; + } + + } + int[] array = new int[count]; + System.arraycopy(container,0,array,0,count); + return array; + } + @Test + public void testGetPrimes() { + int[] newArray = getPrimes(4); + for (int i = 0; i < newArray.length; i++) { + System.out.println(newArray[i]); + } + } + private boolean isShusu(int num){ + int sqrt = 1; + while (sqrt * sqrt < num){ + sqrt++; + } + for (int i = 2; i < sqrt; i++) { + if (num % i == 0) { + return false; + } + } + return true; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * @param max + * @return + */ + public int[] getPerfectNumbers(int max){ + int[] container = new int[5]; + int count = 0; + for (int i = 1; i < max; i++) { + if (isWanshu(i)) { + if (count == container.length) { + container = grow(container,container.length << 1); + } + container[count] = i; + count++; + } + + } + int[] array = new int[count]; + System.arraycopy(container,0,array,0,count); + return array; + } + @Test + public void testGetPerfectNumbers() { + int[] newArray = getPerfectNumbers(29); + for (int i = 0; i < newArray.length; i++) { + System.out.println(newArray[i]); + } +// isWanshu(6); + } + private boolean isWanshu(int num){ + int sqrt = 1; + while (sqrt * sqrt < num){ + sqrt++; + } + int sum = 1; + for (int i = 2; i < sqrt; i++) { + if (num % i == 0 ) { + sum = sum + i + (num/i); + } + } + if (sum == num) { + return true; + } + return false; + } + + /** + * 用seperator 把数组 array给连接起来 + * 例如array= [3,8,9], seperator = "-" + * 则返回值为"3-8-9" + * @param array + * @param + * @return + */ + public String join(int[] array, String seperator){ + String result = ""; + + for (int i = 0; i < array.length; i++) { + if (i != 0) { + result = result + seperator; + } + result = result + array[i]; + } + + return result; + } + @Test + public void testJoin() { + int[] test = {1, 5, 8, 4}; + String seperator = "-"; + String join = join(test, seperator); + System.out.println(join); + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/FileDownloader.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/FileDownloader.java index e538a04769..13d9ab7001 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/FileDownloader.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/FileDownloader.java @@ -44,7 +44,7 @@ public void execute() throws ConnectionException { int length = conn.getContentLength(); System.out.println(length); int blockSize = length / 9; - ArrayList downloadThreads = new ArrayList<>(); + ArrayList downloadThreads = new ArrayList(); for (int i = 0; i < 9; i++) { int startPos = blockSize * i; @@ -57,9 +57,9 @@ public void execute() throws ConnectionException { downloadThreads.add(thread); thread.start(); } -// for(DownloadThread thread : downloadThreads){ -// thread.join(); -// } + for(DownloadThread thread : downloadThreads){ + thread.join(); + } } catch (Exception e) { e.printStackTrace(); @@ -70,11 +70,6 @@ public void execute() throws ConnectionException { } } listener.notifyFinished(); - try { - System.in.read(); - } catch (IOException e) { - e.printStackTrace(); - } } diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/api/Connection.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/api/Connection.java index 2bcddfcca8..c94d12e92d 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/api/Connection.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/api/Connection.java @@ -1,7 +1,5 @@ package org.xukai.coderising.download.api; -import java.io.IOException; - public interface Connection { /** * 给定开始和结束位置, 读取数据, 返回值是字节数组 diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/impl/ConnectionImpl.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/impl/ConnectionImpl.java index 8794707fa6..4698bb2825 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/impl/ConnectionImpl.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/download/impl/ConnectionImpl.java @@ -21,7 +21,6 @@ public byte[] read(int startPos, int endPos) throws ConnectionException { BufferedInputStream inputStream = null; try { urlConnection.setRequestProperty("Range","bytes=" + startPos + "-" + (endPos)); - System.out.println(urlConnection.getResponseCode()); inputStream = new BufferedInputStream(urlConnection.getInputStream()); buff = new byte[endPos-startPos]; int len = 0; diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/Struts.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/Struts.java index 524b0634e8..3e7a4301f7 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/Struts.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/Struts.java @@ -55,7 +55,7 @@ public static View runAction(String actionName, Map parameters) { //根据映射关系将值放入 view.setJsp(mapping.get(result)); List gets = ReflectUtil.getMethodBeginWith(cls, "get"); - HashMap models = new HashMap<>(); + HashMap models = new HashMap(); for(Method getMethod : gets){ //调用所有getter方法 Object getFieldResult = ReflectUtil.invokeMethod(obj, getMethod); @@ -87,7 +87,7 @@ private static List initalStruts() throws ClassNotFoundException, Docume Document doc = sr.read(strutsPath); XmlParseHelper helper = new XmlParseHelper(doc); List actions = helper.getNodeByPath("//action"); - ArrayList actionsList = new ArrayList<>(); + ArrayList actionsList = new ArrayList(); for (Element action : actions){ Action obj = new Action(); String nameAttr = helper.getNodeAttrValue(action, "name"); @@ -95,7 +95,7 @@ private static List initalStruts() throws ClassNotFoundException, Docume obj.setName(nameAttr); obj.setaClass(Class.forName(classAttr)); List results = helper.getChildNodeByName(action, "result"); - HashMap map = new HashMap<>(); + HashMap map = new HashMap(); for (Element result : results){ String resultNameAttr = helper.getNodeAttrValue(result, "name"); String resultValue = helper.getNodeValue(result); diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/StrutsTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/StrutsTest.java index 53bf155c33..d9157edf95 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/StrutsTest.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/litestruts/StrutsTest.java @@ -55,7 +55,7 @@ public void testInital() throws ClassNotFoundException { Document doc = sr.read(strutsPath); XmlParseHelper helper = new XmlParseHelper(doc); List actions = helper.getNodeByPath("//action"); - ArrayList actionsList = new ArrayList<>(); + ArrayList actionsList = new ArrayList(); for (Element action : actions){ Action obj = new Action(); String nameAttr = helper.getNodeAttrValue(action, "name"); @@ -66,7 +66,7 @@ public void testInital() throws ClassNotFoundException { for (Element result : results){ String resultNameAttr = helper.getNodeAttrValue(result, "name"); String resultValue = helper.getNodeValue(result); - HashMap map = new HashMap<>(); + HashMap map = new HashMap(); map.put("name",resultNameAttr); map.put("viewPath",resultValue); obj.setResultMapping(map); diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java new file mode 100644 index 0000000000..bec5202645 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExpr.java @@ -0,0 +1,139 @@ +package org.xukai.coderising.stack; + +import com.google.common.collect.Maps; +import com.sun.org.apache.bcel.internal.generic.IFNE; + +import java.util.HashMap; + +public class InfixExpr { + + 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 InfixExpr(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++) { +// if (expr.charAt(i) == TypeToken.add.token || expr.charAt(i) == TypeToken.substruct.token) { +// isNem = true; +// if (!tokenStack.isEmpty() && (char)tokenStack.pop() == '*') { +// Float num2 = Float.valueOf(numStack.pop().toString()); +// Float num1 = Float.valueOf(numStack.pop().toString()); +// numStack.push(num1*num2); +// } else if (!tokenStack.isEmpty() && ((char)tokenStack.pop()) == '/') { +// Float num2 = Float.valueOf(numStack.pop().toString()); +// Float num1 = Float.valueOf(numStack.pop().toString()); +// numStack.push(num1/num2); +// } +// tokenStack.push(expr.charAt(i)); +// } else if (expr.charAt(i) == TypeToken.devide.token){ +// isNem = true; +// tokenStack.push(expr.charAt(i)); +// } else if (expr.charAt(i) == TypeToken.plus.token){ +// isNem = true; +// tokenStack.push(expr.charAt(i)); +// } else if (String.valueOf(expr.charAt(i)).matches("\\d{1}")){ +// if (isNem) { +// numStack.push((expr.charAt(i))); +// } else { +// numStack.push(numStack.pop().toString() + (expr.charAt(i))); +// } +// isNem = false; +// +// } else { +// throw new RuntimeException(); +// } + 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(); + } +// System.out.println(Double.valueOf(numStack.pop().toString())); + return Double.valueOf(numStack.pop().toString()); + } + + public static void main(String[] args) { + + } + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExprTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExprTest.java new file mode 100644 index 0000000000..b261935703 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/InfixExprTest.java @@ -0,0 +1,48 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Stack.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Stack.java new file mode 100644 index 0000000000..dddfe7511a --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/Stack.java @@ -0,0 +1,40 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtil.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtil.java new file mode 100644 index 0000000000..d34eb23b4d --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtil.java @@ -0,0 +1,147 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtilTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtilTest.java new file mode 100644 index 0000000000..f8f2d1b4e4 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/stack/StackUtilTest.java @@ -0,0 +1,60 @@ +package org.xukai.coderising.stack; + +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/FileUtil.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/FileUtil.java new file mode 100644 index 0000000000..2f511dbb0c --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/FileUtil.java @@ -0,0 +1,55 @@ +package org.xukai.coderising.util; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; + +/** + * @author xukai + * @desc + * @date 2017-04-02-13:22 + */ +public class FileUtil { + + public static byte[] toByteArray(String fileName) throws IOException { + File file = new File(fileName); + return toByteArray(file); + } + + public static byte[] toByteArray(File file) throws IOException { + if (!file.exists()) { + throw new FileNotFoundException(); + } + BufferedInputStream in = new BufferedInputStream(new FileInputStream(file)); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buff = new byte[1024]; + int len = 0; + try { + while((len = in.read(buff)) != -1){ + out.write(buff,0,len); + } + return out.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/ReflectUtil.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/ReflectUtil.java index 7bca0d6506..6522b30daf 100644 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/ReflectUtil.java +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/coderising/util/ReflectUtil.java @@ -59,7 +59,7 @@ public static Method getMethod(Class cls, String methodName){ } public static List getMethodBeginWith(Class cls, String methodName){ - ArrayList methodsList = new ArrayList<>(); + ArrayList methodsList = new ArrayList(); try { Method[] methods = cls.getDeclaredMethods(); for(Method method : methods){ diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/Stack.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/Stack.java deleted file mode 100644 index de705e1fec..0000000000 --- a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/Stack.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.xukai.common; - -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(); - } -} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..35bd2f218d --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame.java @@ -0,0 +1,107 @@ +package org.xukai.common.linklist; + +/** + * 用双向链表实现LRU算法 + * @author liuxin + * + */ +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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrameTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..5f09e7fc70 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrameTest.java @@ -0,0 +1,35 @@ +package org.xukai.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()); + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame_liuxin.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame_liuxin.java new file mode 100644 index 0000000000..5a9b7cc940 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/common/linklist/LRUPageFrame_liuxin.java @@ -0,0 +1,150 @@ +package org.xukai.common.linklist; + + +public class LRUPageFrame_liuxin { + + 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_liuxin(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/AttributeInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..1408111d77 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/AttributeInfo.java @@ -0,0 +1,59 @@ +package org.xukai.jvm.attr; + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.UTF8Info; +import org.xukai.jvm.loader.ByteCodeIterator; + +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; + } + + + public static AttributeInfo parseAttribute(ByteCodeIterator iter, ClassFile clzFile) { + int attributeNameIndex = iter.nextToInt(2); + System.out.println(((UTF8Info)clzFile.getConstantPool().getConstantInfo(attributeNameIndex)).getValue()); + String attributeName = ((UTF8Info) clzFile.getConstantPool().getConstantInfo(attributeNameIndex)).getValue(); + switch(attributeName){ + case AttributeInfo.CODE : + iter.preToInt(2); + CodeAttr codeAttr = CodeAttr.parse(clzFile, iter); + return codeAttr; + case AttributeInfo.EXCEPTIONS : + iter.preToInt(2); + System.out.println("解析exception"); + return null; + case AttributeInfo.CONST_VALUE : + iter.preToInt(2); + System.out.println("解析constValue"); + return null; + case AttributeInfo.LINE_NUM_TABLE : + iter.preToInt(2); + LineNumberTable lineNumberTable = LineNumberTable.parse(iter); + return lineNumberTable; + case AttributeInfo.LOCAL_VAR_TABLE : + iter.preToInt(2); + LocalVariableTable localVariableTable = LocalVariableTable.parse(iter); + return localVariableTable; + case AttributeInfo.STACK_MAP_TABLE : + iter.preToInt(2); + StackMapTable stackMapTable = StackMapTable.parse(iter); + return stackMapTable; + default: + throw new RuntimeException(); + } + + + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..d0c8ef4e32 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/CodeAttr.java @@ -0,0 +1,83 @@ +package org.xukai.jvm.attr; + + +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack ; + private int maxLocals ; + private int codeLen ; + private String code; + + + + public String getCode() { + return code; + } + + //private ByteCodeCommand[] cmds ; + //public ByteCodeCommand[] getCmds() { + // return cmds; + //} + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code /*ByteCodeCommand[] cmds*/) { + super(attrNameIndex, attrLen); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.codeLen = codeLen; + this.code = code; + //this.cmds = cmds; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + public static CodeAttr parse(ClassFile clzFile, ByteCodeIterator iter){ + int attributeNameIndex = iter.nextToInt(2); + int attributeLength = iter.nextToInt(4); + int maxStack = iter.nextToInt(2); + int maxLocals = iter.nextToInt(2); + int codeLength = iter.nextToInt(4); + String code = iter.nextToString(codeLength); + System.out.println(code); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + int exceptionTableLength = iter.nextToInt(2); + if (exceptionTableLength > 0) { + iter.nextToInt(exceptionTableLength); + System.out.println("解析exception"); + } + int subAttributeCount = iter.nextToInt(2); + System.out.println("subAttributeCount" + subAttributeCount); + if (subAttributeCount > 0) { + for (int i = 0; i < subAttributeCount; i++) { + AttributeInfo attributeInfo = AttributeInfo.parseAttribute(iter, clzFile); + if (attributeInfo instanceof LineNumberTable) { + codeAttr.setLineNumberTable((LineNumberTable)attributeInfo); + } else if (attributeInfo instanceof LocalVariableTable){ + codeAttr.setLocalVariableTable((LocalVariableTable)attributeInfo); + } else if (attributeInfo instanceof StackMapTable){ + codeAttr.setStackMapTable((StackMapTable)attributeInfo); + } + } + } + return codeAttr; + } + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + + } + + + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LineNumberTable.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..fa66c6a2f1 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LineNumberTable.java @@ -0,0 +1,55 @@ +package org.xukai.jvm.attr; + +import org.xukai.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 attributeNameIndex = iter.nextToInt(2); + int attributeLength = iter.nextToInt(4); + LineNumberTable lineNumberTable = new LineNumberTable(attributeNameIndex, attributeLength); + int lineNumberTableLengh = iter.nextToInt(2); + if (lineNumberTableLengh > 0) { + for (int i = 0; i < lineNumberTableLengh; i++) { + int startPc = iter.nextToInt(2); + int lineNum = iter.nextToInt(2); + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(startPc); + lineNumberItem.setLineNum(lineNum); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + } + return lineNumberTable; + } + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableItem.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..658481d33b --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableTable.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..dcc5bbd4f3 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/LocalVariableTable.java @@ -0,0 +1,46 @@ +package org.xukai.jvm.attr; + + +import org.xukai.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); + } + + public static LocalVariableTable parse(ByteCodeIterator iter){ + int attributeNameIndex = iter.nextToInt(2); + int attributeLength = iter.nextToInt(4); + LocalVariableTable localVariableTable = new LocalVariableTable(attributeNameIndex, attributeLength); + int localVariableTableLength = iter.nextToInt(2); + if (localVariableTableLength > 0) { + for (int i = 0; i < localVariableTableLength; i++) { + int startPc = iter.nextToInt(2); + int length = iter.nextToInt(2); + int nameIndex = iter.nextToInt(2); + int descriptorIndex = iter.nextToInt(2); + int index = iter.nextToInt(2); + LocalVariableItem lineNumberItem = new LocalVariableItem(); + lineNumberItem.setStartPC(startPc); + lineNumberItem.setLength(length); + lineNumberItem.setNameIndex(nameIndex); + lineNumberItem.setLength(descriptorIndex); + lineNumberItem.setLength(index); + localVariableTable.addLocalVariableItem(lineNumberItem); + } + } + return localVariableTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/StackMapTable.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..1ad1f9d1ed --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package org.xukai.jvm.attr; + + +import org.xukai.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.nextToInt(2); + int len = iter.nextToInt(4); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.nextToString(len); + t.setOriginalCode(code); + + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/AccessFlag.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..bbfe6b2872 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..a2b2dfb515 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassFile.java @@ -0,0 +1,93 @@ +package org.xukai.jvm.clz; + +import org.xukai.jvm.constant.ClassInfo; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.field.Field; +import org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassIndex.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..93ba2d7b86 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..bf7171a966 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..24323692e9 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..ff4aa4b906 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..f0b846f47c --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..a0c02fedaf --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..c88c848d3a --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..0aa452b866 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package org.xukai.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..31a3c52910 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..caf1c19918 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/field/Field.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/field/Field.java new file mode 100644 index 0000000000..b482229294 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/field/Field.java @@ -0,0 +1,42 @@ +package org.xukai.jvm.field; + + +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.UTF8Info; +import org.xukai.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(){ + return getFieldName() +":"+ getFieldDescription(); + } + + public String getFieldName(){ + return ((UTF8Info)pool.getConstantInfo(this.nameIndex)).getValue(); + } + + public String getFieldDescription(){ + return ((UTF8Info)pool.getConstantInfo(this.descriptorIndex)).getValue(); + } + + public static Field parse(ConstantPool pool,ByteCodeIterator iter){ + + return null; + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ByteCodeIterator.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..7e3b9c0e9b --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,62 @@ +package org.xukai.jvm.loader; + +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + + private byte[] bytes; + + private int offset; + + public ByteCodeIterator(byte[] bytes,int offset) { + this.bytes = bytes; + this.offset = offset; + } + + + public int nextToInt(int length){ + Preconditions.checkArgument(length > 0); + if ((offset + length) < bytes.length) { + int i = Util.byteToInt(Arrays.copyOfRange(bytes, offset, offset + length)); + offset = offset + length; + return i; + } + return -1; + } + + public int preToInt(int length){ + Preconditions.checkArgument(length > 0); + if ((offset - length) > 0) { + int i = Util.byteToInt(Arrays.copyOfRange(bytes, offset - length, offset)); + offset = offset - length; + return i; + } + return -1; + } + + public String nextToString(int length){ + Preconditions.checkArgument(length > 0); + if ((offset + length) < bytes.length) { + String str = Util.byteToHexString(Arrays.copyOfRange(bytes,offset,offset + length)); + offset = offset + length; + return str; + } + return null; + } + + public String nextToUTF(int length){ + Preconditions.checkArgument(length > 0); + if ((offset + length) < bytes.length) { + String str = new String(Arrays.copyOfRange(bytes,offset,offset + length), Charsets.UTF_8); + offset = offset + length; + return str; + } + return null; + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ClassFileLoader.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..2f75ef3692 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/loader/ClassFileLoader.java @@ -0,0 +1,136 @@ +package org.xukai.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 org.xukai.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 parseFields(ConstantPool pool, ByteCodeIterator iter, ClassFile classFile) { + int fieldsCount = iter.nextToInt(2); + ArrayList fields = new ArrayList<>(fieldsCount); + for (int i = 0; i < fieldsCount; i++) { + int flages = iter.nextToInt(2); + int nameIndex = iter.nextToInt(2); + int descriptorIndex = iter.nextToInt(2); + int attributeCount = iter.nextToInt(2); + if (attributeCount > 0) { + System.out.println("jeixi"); + } + Field field = new Field(flages, nameIndex, descriptorIndex, pool); + classFile.addField(field); + } + + return fields; + } + + private void parseMethod(ConstantPool pool, ByteCodeIterator iter, ClassFile classFile) { + int methodsCount = iter.nextToInt(2); + for (int i = 0; i < methodsCount; i++) { + Method.parse(classFile,iter); + } + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.nextToInt(2)); + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextToInt(2)); + classIndex.setSuperClassIndex(iter.nextToInt(2)); + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constantCount = iter.nextToInt(2); + System.out.println(constantCount); + Preconditions.checkArgument(constantCount > 0, "无法解析此class文件"); + + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 0; i < constantCount - 1; i++) { + int tag = iter.nextToInt(1); + switch (tag) { + case 1: + UTF8Info info = new UTF8Info(pool); + int length = iter.nextToInt(2); + String value = iter.nextToUTF(length); + Preconditions.checkNotNull(value); + info.setLength(length); + info.setValue(value); + pool.addConstantInfo(info); + break; + case 4: + throw new RuntimeException(); + case 7: + ClassInfo classInfo = new ClassInfo(pool); + int ut8Index = iter.nextToInt(2); + Preconditions.checkArgument(-1 != ut8Index); + classInfo.setUtf8Index(ut8Index); + pool.addConstantInfo(classInfo); + break; + case 8: + StringInfo stringInfo = new StringInfo(pool); + int index = iter.nextToInt(2); + Preconditions.checkArgument(-1 != index); + stringInfo.setIndex(index); + pool.addConstantInfo(stringInfo); + break; + case 9: + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + int classIndex = iter.nextToInt(2); + int nameAndType = iter.nextToInt(2); + Preconditions.checkArgument(-1 != classIndex); + Preconditions.checkArgument(-1 != nameAndType); + fieldRefInfo.setClassInfoIndex(classIndex); + fieldRefInfo.setNameAndTypeIndex(nameAndType); + pool.addConstantInfo(fieldRefInfo); + break; + case 10: + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + int classIndex2 = iter.nextToInt(2); + int nameAndType2 = iter.nextToInt(2); + Preconditions.checkArgument(-1 != classIndex2); + Preconditions.checkArgument(-1 != nameAndType2); + methodRefInfo.setClassInfoIndex(classIndex2); + methodRefInfo.setNameAndTypeIndex(nameAndType2); + pool.addConstantInfo(methodRefInfo); + break; + case 12: + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + int nameIndex = iter.nextToInt(2); + int descriptorIndex = iter.nextToInt(2); + Preconditions.checkArgument(-1 != nameIndex); + Preconditions.checkArgument(-1 != descriptorIndex); + nameAndTypeInfo.setIndex1(nameIndex); + nameAndTypeInfo.setIndex2(descriptorIndex); + pool.addConstantInfo(nameAndTypeInfo); + break; + default: + throw new RuntimeException(); + } + } + return pool; + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextToInt(2); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java new file mode 100644 index 0000000000..6cd71db72c --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/method/Method.java @@ -0,0 +1,88 @@ +package org.xukai.jvm.method; + + +import org.xukai.jvm.attr.AttributeInfo; +import org.xukai.jvm.attr.CodeAttr; +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.constant.UTF8Info; +import org.xukai.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(){ + return getMethodName() +":"+ getMethodDescription(); + } + + public String getMethodName(){ + return ((UTF8Info)clzFile.getConstantPool().getConstantInfo(this.nameIndex)).getValue(); + } + + public String getMethodDescription(){ + return ((UTF8Info)clzFile.getConstantPool().getConstantInfo(this.descriptorIndex)).getValue(); + } + + + + public static Method parse(ClassFile clzFile, ByteCodeIterator iter){ + int flages = iter.nextToInt(2); + int nameIndex = iter.nextToInt(2); + int descriptorIndex = iter.nextToInt(2); + Method method = new Method(clzFile, flages, nameIndex, descriptorIndex); + int attributeCount = iter.nextToInt(2); + if (attributeCount > 0) { + for (int i = 0; i < attributeCount; i++) { + AttributeInfo info = AttributeInfo.parseAttribute(iter, clzFile); + if (info instanceof CodeAttr) { + method.setCodeAttr((CodeAttr) info); + } + } + } + clzFile.addMethod(method); + return method; + + } + + public static void main(String[] args) { + CodeAttr codeAttr = new CodeAttr(1, 1, 1, 1, 1, ""); + System.out.println(codeAttr instanceof AttributeInfo); + AttributeInfo codeAttr2 = new CodeAttr(1, 1, 1, 1, 1, ""); + System.out.println(codeAttr2 instanceof CodeAttr); + } + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..c4fad12ff6 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,309 @@ +package org.xukai.jvm.test; + +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.xukai.jvm.clz.ClassFile; +import org.xukai.jvm.clz.ClassIndex; +import org.xukai.jvm.constant.ClassInfo; +import org.xukai.jvm.constant.ConstantPool; +import org.xukai.jvm.constant.MethodRefInfo; +import org.xukai.jvm.constant.NameAndTypeInfo; +import org.xukai.jvm.constant.NullConstantInfo; +import org.xukai.jvm.constant.UTF8Info; +import org.xukai.jvm.field.Field; +import org.xukai.jvm.loader.ByteCodeIterator; +import org.xukai.jvm.loader.ClassFileLoader; +import org.xukai.jvm.loader.ClassFileParser; +import org.xukai.jvm.method.Method; +import org.xukai.jvm.util.Util; + +import java.util.Arrays; +import java.util.List; + + +public class ClassFileloaderTest { + + + private static final String FULL_QUALIFIED_CLASS_NAME = "org/xukai/jvm/test/EmployeeV1"; + + static String path1 = "D:\\java\\IDEA-Workspace\\coding2017\\group19\\527220084\\xukai_coding\\coding-common\\target\\classes"; + static String path2 = "C:\temp"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "org.xukai.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 = "org.xukai.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1046, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "org.xukai.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); + } + + @Test + public void testParse(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "org.xukai.jvm.test.EmployeeV1"; + byte[] bytes = loader.readBinaryCode(className); + + ClassFileParser parser = new ClassFileParser(); + parser.parse(bytes); + + + + } + + private ClassFile parse(byte[] bytes){ + ByteCodeIterator iter = new ByteCodeIterator(bytes, 0); + String magic = iter.nextToString(4); + Preconditions.checkArgument(magic.equals("cafebabe"),"无法解析此class文件"); + + ClassFile classFile = new ClassFile(); + + int minor_version = iter.nextToInt(2); + classFile.setMinorVersion(minor_version); + int major_version = iter.nextToInt(2); + System.out.println(minor_version + "_" + major_version); + classFile.setMajorVersion(major_version); + return null; + } + + 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); + } + + + +} diff --git a/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/EmployeeV1.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..0dcfd18b96 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package org.xukai.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/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/util/Util.java b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/util/Util.java new file mode 100644 index 0000000000..2ce88b8f57 --- /dev/null +++ b/group19/527220084/xukai_coding/coding-common/src/main/java/org/xukai/jvm/util/Util.java @@ -0,0 +1,25 @@ +package org.xukai.jvm.util; + +public class Util { + + public static int byteToInt(byte[] codes){ + String s1 = byteToHexString(codes); + return Integer.parseInt(s1,16); + } + + + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i + + 4.0.0 + + com.north + learning2017 + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + + + + + + dom4j + dom4j + 1.6.1 + + + + + \ No newline at end of file diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/ArrayList.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/ArrayList.java index 3f2fa618c5..85c1826bf6 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/ArrayList.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/ArrayList.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; import java.util.Arrays; diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/BinaryTreeNode.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/BinaryTreeNode.java index 2701270b5d..d7ac820192 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/BinaryTreeNode.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/BinaryTreeNode.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; public class BinaryTreeNode { diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/Iterator.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/Iterator.java index 86643482fb..06ef6311b2 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/Iterator.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/Iterator.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; public interface Iterator { public boolean hasNext(); diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/LinkedList.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/LinkedList.java index 1d8b56ede4..a6449c8b68 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/LinkedList.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/LinkedList.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; import java.util.NoSuchElementException; diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/List.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/List.java index ce830df7b8..10d13b5832 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/List.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/List.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; public interface List { public void add(Object o); diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/Queue.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/Queue.java index 744fbb2f10..4a189c64ad 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/Queue.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/Queue.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; import org.junit.Test; diff --git a/group19/604322962/learning2017/src/main/java/com/coding/basic/Stack.java b/group19/604322962/learning2017/src/main/java/com/coding/basic/Stack.java index 98e9fd701a..67ded99344 100644 --- a/group19/604322962/learning2017/src/main/java/com/coding/basic/Stack.java +++ b/group19/604322962/learning2017/src/main/java/com/coding/basic/Stack.java @@ -1,4 +1,4 @@ -package main.java.com.coding.basic; +package com.coding.basic; import org.junit.Test; diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/DownloadThread.java b/group19/604322962/learning2017/src/main/java/com/coding/download/DownloadThread.java new file mode 100644 index 0000000000..553fc51398 --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/DownloadThread.java @@ -0,0 +1,56 @@ +package com.coding.download; + +import com.coding.download.api.Connection; +import com.coding.download.api.ConnectionException; +import com.coding.download.impl.ConnectionManagerImpl; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CountDownLatch; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + String filelocal; + CountDownLatch cdl; + public DownloadThread(Connection conn, int startPos, int endPos, String filelocal, CountDownLatch cdl){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.filelocal = filelocal; + this.cdl = cdl; + } + public void run(){ + /*try { + RandomAccessFile fos = new RandomAccessFile("C:\\Users\\gaokun\\Desktop\\test3.jpg", "rwd"); + byte[] read = conn.read(startPos, endPos); + fos.seek(startPos); + fos.setLength(endPos-startPos); + fos.write(read); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + }*/ + RandomAccessFile raf = null; + try { + String url = "http://www.dabaoku.com/sucaidatu/dongwu/chongwujingling/804838.JPG"; + byte[] buf = conn.read(startPos, endPos); + raf = new RandomAccessFile(filelocal, "rwd"); + raf.seek(startPos); + raf.write(buf); + raf.close(); + cdl.countDown(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/FileDownloader.java b/group19/604322962/learning2017/src/main/java/com/coding/download/FileDownloader.java new file mode 100644 index 0000000000..a78c749f5c --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/FileDownloader.java @@ -0,0 +1,110 @@ +package com.coding.download; + +import com.coding.download.api.Connection; +import com.coding.download.api.ConnectionException; +import com.coding.download.api.ConnectionManager; +import com.coding.download.api.DownloadListener; + +import java.io.File; +import java.util.concurrent.CountDownLatch; + + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + + public FileDownloader(String _url) { + this.url = _url; + + } + + public void execute() throws InterruptedException, 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方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + /*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 { + int threadCount = 3; + Connection conn = cm.open(this.url); + int length = conn.getContentLength(); + int blockSize = length / threadCount; + for (int threadId = 1; threadId <= threadCount; threadId++) { + //第一个线程下载的开始位置 + int startIndex = (threadId - 1) * blockSize; + int endIndex = threadId * blockSize - 1; + if (threadId == threadCount) {//最后一个线程下载的长度要稍微长一点 + endIndex = length; + } + System.out.println("线程:"+threadId+"下载:---"+startIndex+"--->"+endIndex); + new DownloadThread(conn, startIndex, endIndex).start(); + } + } catch (ConnectionException e) { + e.printStackTrace(); + }*/ + + int threadCount = 3; + int startPos; + int endPos; + String filelocaltion = "C:\\Users\\gaokun\\Desktop\\demo.jpg"; + CountDownLatch cdl = new CountDownLatch(3); + for (int i = 0; i < threadCount; i++) { + Connection conn = cm.open(url); + int fileLength = conn.getContentLength(); + startPos = i*fileLength/threadCount; + endPos = (i+1)*fileLength/threadCount-1; + if (i == threadCount-1) + endPos = fileLength-1; + new DownloadThread(conn, startPos, endPos, filelocaltion, cdl).start(); + } + cdl.await(); + System.out.println("线程跑完了!"); + listener.notifyFinished(); + + } + + 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/604322962/learning2017/src/main/java/com/coding/download/FileDownloaderTest.java b/group19/604322962/learning2017/src/main/java/com/coding/download/FileDownloaderTest.java new file mode 100644 index 0000000000..10e70736f7 --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/FileDownloaderTest.java @@ -0,0 +1,61 @@ +package com.coding.download; + +import com.coding.download.api.ConnectionException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import com.coding.download.api.ConnectionManager; +import com.coding.download.api.DownloadListener; +import com.coding.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() throws ConnectionException, InterruptedException, ConnectionException { + + String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1489601005973&di=e104648a3c8dcaabb18dfb5d98870d84&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fbaike%2Fpic%2Fitem%2F3b292df5e0fe992536be579530a85edf8cb17140.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("下载完成!"); + + + + } + + void testRead(){ + + } +} diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/api/Connection.java b/group19/604322962/learning2017/src/main/java/com/coding/download/api/Connection.java new file mode 100644 index 0000000000..65f3dae9c5 --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/api/Connection.java @@ -0,0 +1,23 @@ +package com.coding.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/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionException.java b/group19/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionException.java new file mode 100644 index 0000000000..1db8b093ec --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.coding.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionManager.java b/group19/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionManager.java new file mode 100644 index 0000000000..1d1a83caf2 --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.coding.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/api/DownloadListener.java b/group19/604322962/learning2017/src/main/java/com/coding/download/api/DownloadListener.java new file mode 100644 index 0000000000..c41045b0e8 --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coding.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group19/604322962/learning2017/src/main/java/com/coding/download/impl/ConnectionImpl.java b/group19/604322962/learning2017/src/main/java/com/coding/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..85507313ad --- /dev/null +++ b/group19/604322962/learning2017/src/main/java/com/coding/download/impl/ConnectionImpl.java @@ -0,0 +1,61 @@ +package com.coding.download.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + +import com.coding.download.api.Connection; + +public class ConnectionImpl implements Connection{ + + private URLConnection urlConnection; + + public ConnectionImpl(URLConnection urlConnection) { + this.urlConnection = urlConnection; + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + int readBytes = 0; + /*int len = endPos-startPos+1; + byte[] buffer = new byte[1024]; + urlConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + InputStream is = urlConnection.getInputStream();//已经设置了请求的位置,返回的是当前位置对应的文件的输入流 + while (readBytes max){ - if(result.length < index + 2){ + int index = 1; + while(true){ + index ++; + if(result.length < index + 1){ result = grow(result, 10); } - result[index + 1] = result[index -1] + result[index]; - index ++; + result[index] = result[index -1] + result[index - 2]; + if(result[index] > max){ + break; + } } } - return result; + return removeZero(result); } /** @@ -124,32 +146,36 @@ public int[] fibonacci(int max){ * @return */ public int[] getPrimes(int max){ - int[] temArr = null; + int[] temArr = {2}; if(max < 2){ return null; }else if (max == 2){ - int[] re = {2}; - return re; + return temArr; }else{ - temArr = new int[max/2]; - temArr[0] = 2; - int index = 1; - for(int i = 3; i < max ; i= i+2){ + temArr = grow(temArr, 10); + int index = 0; + for(int i = 3;i < max; i ++){ boolean flag = true; - int isql = (int) Math.sqrt(i); - for(int j = 3; j < isql; j++){ - if(i % j == 0){ + int iSqrt = (int) Math.sqrt(i); + for(int j = 0; j < index + 1; j ++){ + if(iSqrt < temArr[j]){ + break; + } + if(i % temArr[j] == 0){ flag = false; + break; } } if(flag){ - temArr[index] = i; index ++; + if(temArr.length < index + 1){ + temArr = grow(temArr, 30); + } + temArr[index] = i; } } } - temArr = this.removeZero(temArr); - return temArr; + return removeZero(temArr); } /** @@ -163,17 +189,17 @@ public int[] getPerfectNumbers(int max){ int index = 0; if(max < 6){ return null; - }else{ - } + } + for (int n = 6; n <= max ; n ++){ - int[] allPrimeFactore = getPrimeFactors(n); + int[] allFactors = getAllFactors(n); int sum = 0; - for(int i = 0, len = allPrimeFactore.length; i < len; i ++){ - sum += allPrimeFactore[i]; + for(int i = 0, len = allFactors.length; i < len; i ++){ + sum += allFactors[i]; } if(sum == n){ if(result.length < index + 1){ - result = this.grow(result, 1); + result = this.grow(result, 3); } result[index] = n; index ++; @@ -183,10 +209,24 @@ public int[] getPerfectNumbers(int max){ return removeZero(result); } - private int[] getPrimeFactors(int n){ + public int[] getAllFactors(int n){ + int[] result = new int[n]; + int index = 0; + for(int i = 1; i < n; i++){ + if(n % i == 0){ + result[index] = i; + index ++; + } + } + return removeZero(result); + } + + //分解因式算法 + public int[] getPrimeFactors(int n){ int[] allPrimes = getPrimes(n); int[] result = new int[allPrimes.length]; - int index = 0; + int index = 1; + result[0] = 1; for(int i = 0, len = allPrimes.length; i < len; i ++){ int devide = n; while(devide % allPrimes[i] == 0){ diff --git a/group19/972815123/src/com/coderising/array/ArrayUtilTest.java b/group19/972815123/src/com/coderising/array/ArrayUtilTest.java new file mode 100644 index 0000000000..2fbd5ead5e --- /dev/null +++ b/group19/972815123/src/com/coderising/array/ArrayUtilTest.java @@ -0,0 +1,120 @@ +package com.coderising.array; + +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 junit.framework.Assert; + +public class ArrayUtilTest { + + private ArrayUtil au; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + au = new ArrayUtil(); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testReverseArray() { + int[] test = {1,2,3}; + au.reverseArray(test); + String result = au.join(test, "-"); + Assert.assertEquals(result, "3-2-1"); + } + + @Test + public void testRemoveZero() { + int[] test = {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5}; + test = au.removeZero(test); + String result = au.join(test, ","); + Assert.assertEquals(result, "1,3,4,5,6,6,5,4,7,6,7,5"); + } + + @Test + public void testMerge() { + int[] arr1 = {3, 5, 7,8}; + int[] arr2 = {4, 5, 6,7}; + int[] test = au.merge(arr1, arr2); + String result = au.join(test, ","); + System.out.println(result); + Assert.assertEquals(result, "3,4,5,6,7,8"); + } + + @Test + public void testGrow() { + int[] test = {3,5,6}; + test = au.grow(test, 2); + String result = au.join(test, ","); + System.out.println(result); + System.out.println(test.length); + Assert.assertTrue(5 == test.length); + } + + @Test + public void testFibonacci() { + int[] test = au.fibonacci(250); + String result = au.join(test, ","); + System.out.println(result); + Assert.assertEquals(result, "1,1,2,3,5,8,13,21,34,55,89,144,233,377"); + } + + @Test + public void testGetPrimes() { + //2,3,5,7,11,13,17,19 + int[] test = au.getPrimes(23); + String result = au.join(test, ","); + System.out.println(result); + Assert.assertEquals(result, "2,3,5,7,11,13,17,19"); + } + + @Test + public void testGetPerfectNumbers() { + int[] test = au.getPerfectNumbers(10000); + String result = au.join(test, ","); + System.out.println(result); + Assert.assertEquals(result, "6,28,496,8128"); + } + + + @Test + public void testGetAllFactors(){ + int[] test = au.getAllFactors(98); + String result = au.join(test, ","); + System.out.println(result); + Assert.fail(); + } + + @Test + public void testGetPrimeFactors(){ + int[] test = au.getPrimeFactors(98); + String result = au.join(test, ","); + System.out.println(result); + Assert.fail(); + } + + @Test + public void testJoin() { + int[] test = {1,2,3}; + String result = au.join(test, ","); + + Assert.assertEquals(result, "1,2,3"); + } + +} diff --git a/group19/972815123/src/com/coderising/array/Main.java b/group19/972815123/src/com/coderising/array/Main.java new file mode 100644 index 0000000000..5c8a9abcc6 --- /dev/null +++ b/group19/972815123/src/com/coderising/array/Main.java @@ -0,0 +1,20 @@ +package com.coderising.array; + +public class Main { + + public static void main(String[] args) { + ArrayUtil au = new ArrayUtil(); +// int[] test = {1,2}; +// au.reverseArray(test); +// String result = au.join(test, "-"); + + + int[] arr1 = {3, 5, 7,8}; + int[] arr2 = {4, 5, 6,7}; + int[] test = au.merge(arr1, arr2); + String result = au.join(test, ","); + + System.out.println(result); + } + +} diff --git a/group19/972815123/src/com/coderising/litestruts/Struts.java b/group19/972815123/src/com/coderising/litestruts/Struts.java index 7d908282b6..2aeaffd491 100644 --- a/group19/972815123/src/com/coderising/litestruts/Struts.java +++ b/group19/972815123/src/com/coderising/litestruts/Struts.java @@ -52,7 +52,7 @@ public class Struts { public static View runAction(String actionName, Map parameters) { HashMap> xml = parseStrutsXml(url); - HashMap login = xml.get("login"); + HashMap login = xml.get(actionName); String loginClassName = login.get("class"); System.out.println(loginClassName); diff --git a/group19/972815123/src/com/coding/basic/LinkedList.java b/group19/972815123/src/com/coding/basic/LinkedList.java index 04de763349..b001f06305 100644 --- a/group19/972815123/src/com/coding/basic/LinkedList.java +++ b/group19/972815123/src/com/coding/basic/LinkedList.java @@ -12,13 +12,24 @@ public LinkedList() { @Override public void add(Object o) { + + Node newNode = new Node(); - Node last = head; - while(last.next != null){ - last = last.next; + newNode.data = o; + newNode.next = null; + + if(size == 0){ + head = newNode; + size = 1; + return; } - last.next = newNode; - newNode.prev = last; + + Node _last = head; + while(_last.next != null){ + _last = _last.next; + } + _last.next = newNode; + newNode.prev = _last; last = newNode; size++; } @@ -60,7 +71,7 @@ public int size() { public Object remove(int index) { Node indexNode = head ; int i = 0; - while(i == index){ + while(i != index){ indexNode = indexNode.next; i++; @@ -131,4 +142,215 @@ public Object next() { index = index.next; return tem; } + + @Override + public String toString(){ + Node node = head; + StringBuffer sb = new StringBuffer(); + while(node.next != null){ + sb.append(node.data.toString() + ","); + node = node.next; + } + sb.append(node.data.toString()); + return sb.toString(); + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node index = head; + Node temPre = null; + while(true){ + Node tem = index.next; + if(index.next == null){ + head = index; + index.next = temPre; + break; + } + index.next = temPre; + temPre = index; + index = tem; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf(){ + int i = 0; + Node node = head; + while(i < size/2 + 1){ + head = node; + node = node.next; + i++; + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + //省略了数据合法性检查; + Node indexStart = head; + int index = 0; + for(int j = 0; j < i - 1; j++){ + indexStart= indexStart.next; + } + Node indexEnd = indexStart; + Node tem = null; + for(int k = 0 ; k <= length; k++){ + tem = indexEnd; + indexEnd = indexEnd.next; + } + tem.next = null; + indexStart.next = indexEnd; + } + /** + * 假定当前链表和listB均包含已升序排列的整数 + * 从当前链表中取出那些listB所指定的元素 + * 例如当前链表 = 11->101->201->301->401->501->601->701 + * listB = 1->3->4->6 + * 返回的结果应该是[101,301,401,601] + * @param list + */ + public Object[] getElements(LinkedList list){ + //省略了数据合法性检查; + Node pointHead = list.head; + Node node = head; + Object[] result = new Object[list.size]; + int point = 0; + int resultPoint = 0; + while(true){ + int temPoint = (int)pointHead.data; + if(point == temPoint){ + result[resultPoint] = node.data; + if(pointHead.next == null){ + break; + } + resultPoint++; + pointHead = pointHead.next; + } + if(node.next == null ){ + break; + } + node = node.next; + point++; + } + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + + * @param list + */ + //m * n 复杂度的算法,没有利用原链表已排序的特性; + public void subtract(LinkedList list){ + Node indexNode = head; + Node indexPreNode = null; + while(null != indexNode){ + Node pointNode = list.head; + while(null != pointNode){ + if((int)pointNode.data == (int)(indexNode.data)){ + if(indexPreNode == null){ + head = indexNode.next; + }else{ + indexPreNode.next = indexNode.next; + } + } + pointNode = pointNode.next; + } + indexPreNode = indexNode; + indexNode = indexNode.next; + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + Node indexNode = head; + Node indexPreNode = null; + while(null != indexNode){ + if(null == indexPreNode){ + indexPreNode = indexNode; + indexNode = indexNode.next; + continue; + } + if((int)indexPreNode.data == (int)indexNode.data){ + indexPreNode.next = indexNode.next; + }else{ + indexPreNode = indexNode; + } + indexNode = indexNode.next; + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + Node indexNode = head; + Node indexPreNode = null; + Node minNode = null; + Node maxNode = null; + boolean getMin = false, getMax = false; + while(indexNode != null){ + if((int)indexNode.data >= min){ + if(!getMin){ + minNode = indexPreNode; + getMin = true; + } + } + + if((int)indexNode.data > max){ + if(!getMax){ + maxNode = indexNode; + break; + } + } + indexPreNode = indexNode; + indexNode = indexNode.next; + } + if(null == minNode && null == maxNode){ + head.data = null; + head.next = null; + }else if(null != minNode && null != maxNode){ + minNode.next = maxNode; + } + + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + LinkedList result = new LinkedList(); + Node indexNode = head; + while(null != indexNode){ + Node pointNode = list.head; + while(null != pointNode){ + if((int)pointNode.data == (int)(indexNode.data)){ + result.add(indexNode.data); + } + pointNode = pointNode.next; + } + indexNode = indexNode.next; + } + return result; + } + } diff --git a/group19/972815123/src/com/coding/basic/LinkedListTest.java b/group19/972815123/src/com/coding/basic/LinkedListTest.java new file mode 100644 index 0000000000..1bb14396a0 --- /dev/null +++ b/group19/972815123/src/com/coding/basic/LinkedListTest.java @@ -0,0 +1,209 @@ +package com.coding.basic; + +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 junit.framework.Assert; + +public class LinkedListTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testRemove(){ + LinkedList ll = new LinkedList(); + ll.add("1"); + ll.add("2"); + ll.add("3"); + ll.add("4"); + ll.remove(3); + System.out.println(ll.toString()); + Assert.assertEquals("1,2,3,4", ll.toString()); + } + + @Test + public void testToString() { + LinkedList ll = new LinkedList(); + ll.add("1"); + ll.add("2"); + ll.add("3"); + ll.add("4"); + System.out.println(ll.toString()); + Assert.assertEquals("1,2,3,4", ll.toString()); + } + + @Test + public void testReverse() { + LinkedList ll = new LinkedList(); + ll.add("4"); + ll.add("3"); + ll.add("2"); + ll.add("1"); + System.out.println(ll.toString()); + ll.reverse(); + System.out.println(ll.toString()); + Assert.assertEquals("1,2,3,4", ll.toString()); + } + + @Test + public void testRemoveFirstHalf() { + LinkedList ll = new LinkedList(); + ll.add("4"); + ll.add("3"); + ll.add("2"); + ll.add("1"); + ll.add("0"); + System.out.println(ll.toString()); + ll.removeFirstHalf(); + System.out.println(ll.toString()); + Assert.assertEquals("2,1,0", ll.toString()); + } + + @Test + public void testRemoveIntInt() { + LinkedList ll = new LinkedList(); + ll.add("1"); + ll.add("2"); + ll.add("3"); + ll.add("4"); + ll.add("5"); + ll.add("6"); + ll.add("7"); + ll.add("8"); + ll.add("9"); + ll.remove(3,2); + System.out.println(ll.toString()); + Assert.assertEquals("1,2,3,6,7,8,9", ll.toString()); + } + + @Test + public void testGetElements() { + LinkedList ll = new LinkedList(); + ll.add("0"); + ll.add("1"); + ll.add("2"); + ll.add("3"); + ll.add("4"); + ll.add("5"); + ll.add("6"); + ll.add("7"); + ll.add("8"); + ll.add("9"); + LinkedList pointerList = new LinkedList(); + pointerList.add(1); + pointerList.add(3); + pointerList.add(5); + pointerList.add(7); + Object[] result = ll.getElements(pointerList); + for(Object o : result){ + System.out.print((String)o); + System.out.print(","); + } + Assert.assertEquals((String)result[3], "7"); + } + + @Test + public void testSubtract() { + LinkedList ll = new LinkedList(); + ll.add(0); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(4); + ll.add(5); + ll.add(6); + ll.add(7); + ll.add(8); + LinkedList pointerList = new LinkedList(); + pointerList.add(1); + pointerList.add(3); + pointerList.add(5); + pointerList.add(7); + ll.subtract(pointerList); + System.out.println(ll.toString()); + Assert.assertEquals("0,2,4,6,8", ll.toString()); + } + + @Test + public void testRemoveDuplicateValues() { + LinkedList ll = new LinkedList(); + ll.add(0); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(3); + ll.add(3); + ll.add(4); + ll.add(5); + ll.add(5); + ll.add(6); + ll.add(7); + ll.add(8); + ll.removeDuplicateValues(); + System.out.println(ll.toString()); + Assert.assertEquals("0,1,2,3,4,5,6,7,8", ll.toString()); + } + + @Test + public void testRemoveRange() { + LinkedList ll = new LinkedList(); + ll.add(0); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(3); + ll.add(3); + ll.add(4); + ll.add(5); + ll.add(5); + ll.add(6); + ll.add(7); + ll.add(8); + ll.removeRange(3,7); + System.out.println(ll.toString()); + Assert.assertEquals("0,1,2,8", ll.toString()); + } + + @Test + public void testIntersection() { + LinkedList ll = new LinkedList(); + ll.add(0); + ll.add(1); + ll.add(2); + ll.add(3); + ll.add(4); + ll.add(5); + ll.add(6); + ll.add(7); + ll.add(8); + LinkedList pointerList = new LinkedList(); + pointerList.add(1); + pointerList.add(5); + pointerList.add(3); + pointerList.add(11); + pointerList.add(7); + ll = ll.intersection(pointerList); + System.out.println(ll.toString()); + Assert.assertEquals("1,3,5,7", ll.toString()); + } + +} diff --git a/group19/972815123/src/com/download/DownloadDemo.java b/group19/972815123/src/com/download/DownloadDemo.java new file mode 100644 index 0000000000..ceb9f93309 --- /dev/null +++ b/group19/972815123/src/com/download/DownloadDemo.java @@ -0,0 +1,34 @@ +package com.coderising.download; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.net.URL; +import java.net.URLConnection; + +public class DownloadDemo { + + public static void main(String[] args) throws Exception { + URL url = new URL("http://bpic.588ku.com/back_pic/02/66/65/68578b3fca8af67.jpg"); + URLConnection conn = url.openConnection(); + InputStream is = conn.getInputStream(); + + System.out.println("content length:" + conn.getContentLength() /1024 + " * 1024"); + System.out.println("stream avilable:" + is.available()/1024 + " * 1024"); + int length = conn.getContentLength(); + + byte[] buffer = new byte[1024]; + int hasRead = 0; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + while((hasRead = is.read(buffer)) != -1){ + out.write(buffer, 0, hasRead); + } + byte[] result = out.toByteArray(); + + RandomAccessFile file = new RandomAccessFile("demo.jpg", "rw"); + file.write(result); + file.close(); + is.close(); + } +} diff --git a/group19/972815123/src/com/download/DownloadThread.java b/group19/972815123/src/com/download/DownloadThread.java new file mode 100644 index 0000000000..c699e81f5a --- /dev/null +++ b/group19/972815123/src/com/download/DownloadThread.java @@ -0,0 +1,58 @@ +package com.coderising.download; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import com.coderising.download.api.Connection; +import com.coderising.download.api.DownloadListener; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + + String fileName; + + Object obj; + private DownloadListener downLoadThread; + +// public DownloadThread setObj(Object obj){ +// this.obj = obj; +// return this; +// } + + public DownloadThread setOnThreadFinished(DownloadListener downLoadThread){ + this.downLoadThread = downLoadThread; + return this; + } + + + public DownloadThread( Connection conn, int startPos, int endPos, String fileName){ + + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.fileName = fileName; + } + public void run(){ + try { + double id = Thread.currentThread().getId(); + System.out.println(id); + byte[] byArr = conn.read(startPos, endPos); + int len = byArr.length; + + Thread.sleep(2000); + + RandomAccessFile currenctPart = new RandomAccessFile(fileName, "rw"); + currenctPart.seek(startPos); + System.out.println(len + "readed length"); + currenctPart.write(byArr,0,len); + currenctPart.close(); + System.out.println(id); + downLoadThread.notifyFinished(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/group19/972815123/src/com/download/FileDownloader.java b/group19/972815123/src/com/download/FileDownloader.java new file mode 100644 index 0000000000..d02b9970b8 --- /dev/null +++ b/group19/972815123/src/com/download/FileDownloader.java @@ -0,0 +1,88 @@ +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; +import com.coderising.download.impl.ConnectionManagerImpl; + + +public class FileDownloader { + + String url; + DownloadListener listener; + ConnectionManager cm; + private int threadRun = 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 { + cm = new ConnectionManagerImpl(); + conn = cm.open(this.url); + + int length = conn.getContentLength(); + String fileName = "test.jpg"; + Object obj = new Object(); + int part = 4; + int step = length / part; + for(int i = 0; i < part; i++){ + threadRun++; + new DownloadThread(cm.open(this.url), step * i,step * (i + 1) -1, fileName) + .setOnThreadFinished(new DownloadListener() { + + @Override + public void notifyFinished() { + synchronized (this) { + threadRun--; + if(threadRun==0){ + listener.notifyFinished(); + } + } + + } + }).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/group19/972815123/src/com/download/FileDownloaderTest.java b/group19/972815123/src/com/download/FileDownloaderTest.java new file mode 100644 index 0000000000..de22d5765e --- /dev/null +++ b/group19/972815123/src/com/download/FileDownloaderTest.java @@ -0,0 +1,52 @@ +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://img.sc115.com/uploads1/sc/jpgs/1504/fpic780_sc115.com.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/group05/284422826/src/com/coderising/download/api/Connection.java b/group19/972815123/src/com/download/api/Connection.java similarity index 100% rename from group05/284422826/src/com/coderising/download/api/Connection.java rename to group19/972815123/src/com/download/api/Connection.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionException.java b/group19/972815123/src/com/download/api/ConnectionException.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionException.java rename to group19/972815123/src/com/download/api/ConnectionException.java diff --git a/group05/284422826/src/com/coderising/download/api/ConnectionManager.java b/group19/972815123/src/com/download/api/ConnectionManager.java similarity index 100% rename from group05/284422826/src/com/coderising/download/api/ConnectionManager.java rename to group19/972815123/src/com/download/api/ConnectionManager.java diff --git a/group05/578505552/src/main/java/com/coderising/download/api/DownloadListener.java b/group19/972815123/src/com/download/api/DownloadListener.java similarity index 100% rename from group05/578505552/src/main/java/com/coderising/download/api/DownloadListener.java rename to group19/972815123/src/com/download/api/DownloadListener.java diff --git a/group19/972815123/src/com/download/impl/ConnectionImpl.java b/group19/972815123/src/com/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..46c5aaf387 --- /dev/null +++ b/group19/972815123/src/com/download/impl/ConnectionImpl.java @@ -0,0 +1,46 @@ +package com.coderising.download.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URLConnection; + +import com.coderising.download.api.Connection; + +public class ConnectionImpl implements Connection{ + + private URLConnection connect; + public void setHttpURLConnection(URLConnection conn){ + this.connect = conn; + this.connect.setRequestProperty("Connection", "Keep-Alive"); + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + InputStream is = connect.getInputStream(); + is.skip(startPos); + + byte[] buffer = new byte[1024]; + int hasRead = 0; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + while(startPos < endPos && (hasRead = is.read(buffer, 0, 1024)) != -1){ + out.write(buffer, 0, hasRead); + startPos += hasRead; + } + + byte[] result = out.toByteArray(); + return result; + } + + @Override + public int getContentLength() { + return connect.getContentLength(); + } + + @Override + public void close() { + } + +} diff --git a/group19/972815123/src/com/download/impl/ConnectionManagerImpl.java b/group19/972815123/src/com/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..7f16a4d1cd --- /dev/null +++ b/group19/972815123/src/com/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,28 @@ +package com.coderising.download.impl; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + +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 { + try { + URL u = new URL(url); + URLConnection conn = u.openConnection(); + ConnectionImpl connection = new ConnectionImpl(); + connection.setHttpURLConnection(conn); + return connection; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/group20/1107837739/1107837739Learning/lib/dom4j-1.6.1.jar b/group20/1107837739/1107837739Learning/data-structure/lib/dom4j-1.6.1.jar similarity index 100% rename from group20/1107837739/1107837739Learning/lib/dom4j-1.6.1.jar rename to group20/1107837739/1107837739Learning/data-structure/lib/dom4j-1.6.1.jar diff --git a/group20/1107837739/1107837739Learning/lib/fastjson-1.2.7.jar b/group20/1107837739/1107837739Learning/data-structure/lib/fastjson-1.2.7.jar similarity index 100% rename from group20/1107837739/1107837739Learning/lib/fastjson-1.2.7.jar rename to group20/1107837739/1107837739Learning/data-structure/lib/fastjson-1.2.7.jar diff --git a/group20/1107837739/1107837739Learning/lib/hamcrest-core-1.3.jar b/group20/1107837739/1107837739Learning/data-structure/lib/hamcrest-core-1.3.jar similarity index 100% rename from group20/1107837739/1107837739Learning/lib/hamcrest-core-1.3.jar rename to group20/1107837739/1107837739Learning/data-structure/lib/hamcrest-core-1.3.jar diff --git a/group20/1107837739/1107837739Learning/lib/junit-4.12.jar b/group20/1107837739/1107837739Learning/data-structure/lib/junit-4.12.jar similarity index 100% rename from group20/1107837739/1107837739Learning/lib/junit-4.12.jar rename to group20/1107837739/1107837739Learning/data-structure/lib/junit-4.12.jar diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/Main.java b/group20/1107837739/1107837739Learning/data-structure/src/com/Main.java new file mode 100644 index 0000000000..459b35980d --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/Main.java @@ -0,0 +1,8 @@ +package com; + +public class Main { + + public static void main(String[] args) { + System.out.println("Hello Korben : )"); + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtil.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtil.java new file mode 100644 index 0000000000..fca71735ea --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtil.java @@ -0,0 +1,258 @@ +package com.coderising.array; + +import java.util.ArrayList; +import java.util.List; + +/** + * ArrayUtil + * + * Created by Korben on 26/02/2017. + */ +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 static void reverseArray(int[] origin) { + ensureNotNull(origin); + + int length = origin.length; + for (int i = 0; i < length / 2; i++) { + int tmp = origin[i]; + origin[i] = origin[length - i - 1]; + origin[length - i - 1] = 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} + */ + public static int[] removeZero(int[] oldArray) { + ensureNotNull(oldArray); + + int nonZeroCount = 0; + for (int i : oldArray) { + if (i != 0) { + nonZeroCount++; + } + } + + int newArr[] = new int[nonZeroCount]; + int newArrIndex = 0; + for (int i : oldArray) { + if (i != 0) { + newArr[newArrIndex++] = i; + } + } + + return newArr; + } + + /** + * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 + * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 + */ + public static int[] merge(int[] array1, int[] array2) { + ensureNotNull(array1); + ensureNotNull(array2); + + int maxArraySize = array1.length + array2.length; + int[] mergedArray = new int[maxArraySize]; + + int index1 = 0; + int index2 = 0; + int mergedIndex = -1; + for (int i = 0; i < maxArraySize; i++) { + if (index1 == array1.length) { + System.arraycopy(array2, index2, mergedArray, mergedIndex + 1, array2.length - index2); + mergedIndex += array2.length - index2; + break; + } else if (index2 == array2.length) { + System.arraycopy(array1, index1, mergedArray, mergedIndex + 1, array1.length - index1); + mergedIndex += array1.length - index1; + break; + } else { + int compare = Integer.compare(array1[index1], array2[index2]); + if (compare < 0) { + mergedArray[++mergedIndex] = array1[index1++]; + } else if (compare > 0) { + mergedArray[++mergedIndex] = array2[index2++]; + } else { + mergedArray[++mergedIndex] = array1[index1++]; + index2++; + } + } + } + + // 清除数组多余部分 + if (mergedIndex + 1 < maxArraySize) { + int[] resultArray = new int[mergedIndex + 1]; + System.arraycopy(mergedArray, 0, resultArray, 0, mergedIndex + 1); + return resultArray; + } + + return mergedArray; + } + + /** + * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size + * 注意,老数组的元素在新数组中需要保持 + * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 + * [2,3,6,0,0,0] + */ + public static int[] grow(int[] oldArray, int size) { + ensureNotNull(oldArray); + + if (size < 0) { + throw new IllegalArgumentException("size must > 0"); + } + + int[] newArray = new int[oldArray.length + size]; + + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); + for (int i = oldArray.length; i < newArray.length; i++) { + newArray[i] = 0; + } + + return newArray; + } + + /** + * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 + * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] + * max = 1, 则返回空数组 [] + */ + public static int[] fibonacci(int max) { + if (max == 1) { + int[] array = new int[1]; + array[1] = 1; + return array; + } + + List list = new ArrayList<>(); + + for (int i = 1; ; i++) { + int fibonacciNumber = getFibonacciNumber(i); + if (fibonacciNumber <= max) { + list.add(fibonacciNumber); + } else { + break; + } + } + + return list2Array(list); + } + + private static int getFibonacciNumber(int index) { + if (index == 1) { + return 1; + } + if (index == 2) { + return 1; + } + return getFibonacciNumber(index - 2) + getFibonacciNumber(index - 1); + } + + /** + * 返回小于给定最大值max的所有素数数组 + * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + */ + public static int[] getPrimes(int max) { + List primeList = new ArrayList<>(); + if (max <= 1) { + return new int[0]; + } + + if (max >= 2) { + primeList.add(2); + } + + // 所有偶数都不是素数, 所以这里采用 i += 2 + for (int i = 3; i < max; i += 2) { + if (isPrimeNumber(i, primeList)) { + primeList.add(i); + } + } + + return list2Array(primeList); + } + + private static boolean isPrimeNumber(int number, List primeList) { + for (Integer prime : primeList) { + if (number % prime == 0) { + return false; + } + } + return true; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 + * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + */ + public static int[] getPerfectNumbers(int max) { + if (max <= 1) { + return new int[0]; + } + + List perfectNumberList = new ArrayList<>(); + for (int i = 2; i < max; i++) { + if (isPerfectNumber(i)) { + perfectNumberList.add(i); + } + } + return list2Array(perfectNumberList); + } + + private static boolean isPerfectNumber(int number) { + int sum = 1; + for (int i = 2; i <= number / 2; i++) { + if (number % i == 0) { + sum += i; + } + } + + return sum == number; + } + + /** + * 用separator 把数组 array给连接起来 + * 例如array= [3,8,9], separator = "-" + * 则返回值为"3-8-9" + */ + public static String join(int[] array, String separator) { + ensureNotNull(array); + + if (separator == null) { + throw new NullPointerException(); + } + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < array.length; i++) { + stringBuilder.append(array[i]); + if (i != array.length - 1) { + stringBuilder.append(separator); + } + } + + return stringBuilder.toString(); + } + + private static 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 static void ensureNotNull(int[] array) { + if (array == null) { + throw new NullPointerException(); + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtilTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtilTest.java new file mode 100644 index 0000000000..a2933fc48b --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/array/ArrayUtilTest.java @@ -0,0 +1,185 @@ +package com.coderising.array; + +import org.junit.Assert; +import org.junit.Test; + +/** + * ArrayUtil test + * + * Created by Korben on 26/02/2017. + */ +public class ArrayUtilTest { + + @Test + public void reverseArray() throws Exception { + // test reverse even number + { + int[] testArray = new int[5]; + for (int i = 0; i < 5; i++) { + testArray[i] = i; + } + ArrayUtil.reverseArray(testArray); + for (int i = 0; i < 5; i++) { + Assert.assertEquals(5 - 1 - i, testArray[i]); + } + } + + // test reverse odd number + { + int[] testArray = new int[4]; + for (int i = 0; i < 4; i++) { + testArray[i] = i; + } + ArrayUtil.reverseArray(testArray); + for (int i = 0; i < 4; i++) { + Assert.assertEquals(4 - 1 - i, testArray[i]); + } + } + } + + @Test + public void removeZero() throws Exception { + // 测试非空数组 + { + int[] testArray = new int[20]; + for (int i = 0; i < 20; i++) { + if (i % 5 == 0) { + testArray[i] = 0; + } else { + testArray[i] = i; + } + } + + int[] newArray = ArrayUtil.removeZero(testArray); + Assert.assertNotNull(newArray); + for (int i = 0; i < 20; i++) { + if (i % 5 == 0) { + continue; + } + + Assert.assertEquals(testArray[i], i); + } + } + + // 测试空数组 + { + int[] testArray = new int[5]; + for (int i = 0; i < 5; i++) { + testArray[i] = 0; + } + + int[] newArray = ArrayUtil.removeZero(testArray); + Assert.assertNotNull(newArray); + Assert.assertEquals(newArray.length, 0); + } + } + + @Test + public void merge() throws Exception { + // 构建数组 + int[] array1 = new int[10]; + int[] array2 = new int[11]; + array2[10] = 100; + for (int i = 0; i < 10; i++) { + if (i % 2 == 0) { + array1[i / 2] = i; // 0, 2, 4, 6, 8 + } else { + array2[i / 2] = i; // 1, 3, 5, 7, 9 + } + } + + for (int i = 10; i < 15; i++) { + array1[i - 5] = i; // 10, 11, 12, 13, 14, 15 + array2[i - 5] = i; // 10, 11, 12, 13, 14, 15 + } + + // 测试merge + { + int[] merge = ArrayUtil.merge(array1, array2); + Assert.assertNotNull(merge); + Assert.assertEquals(merge.length, 16); + for (int i = 0; i < 15; i++) { + Assert.assertEquals(merge[i], i); + } + Assert.assertEquals(merge[15], 100); + } + // 调换数组顺序 + { + int[] merge = ArrayUtil.merge(array2, array1); + Assert.assertNotNull(merge); + Assert.assertEquals(merge.length, 16); + for (int i = 0; i < 15; i++) { + Assert.assertEquals(merge[i], i); + } + Assert.assertEquals(merge[15], 100); + } + // 测试空数组 + { + int[] array3 = new int[0]; + int[] merge1 = ArrayUtil.merge(array1, array3); + Assert.assertArrayEquals(merge1, array1); + + int[] merge2 = ArrayUtil.merge(array3, array1); + Assert.assertArrayEquals(merge2, array1); + } + // 测试相同数组 + { + int[] merge = ArrayUtil.merge(array1, array1); + Assert.assertArrayEquals(merge, array1); + } + } + + @Test + public void grow() throws Exception { + int[] oldArray = new int[5]; + for (int i = 0; i < 5; i++) { + oldArray[i] = i; + } + + int[] newArray = ArrayUtil.grow(oldArray, 5); + for (int i = 0; i < 10; i++) { + if (i < 5) { + Assert.assertEquals(newArray[i], i); + } else { + Assert.assertEquals(newArray[i], 0); + } + } + } + + @Test + public void fibonacci() throws Exception { + int[] fibonacciArray = {1, 1, 2, 3, 5, 8, 13, 21}; + + int[] calculatedFibonacci = ArrayUtil.fibonacci(22); + Assert.assertArrayEquals(fibonacciArray, calculatedFibonacci); + } + + @Test + public void getPrimes() throws Exception { + int[] expected = {2, 3, 5, 7, 11, 13, 17, 19}; + int[] primes = ArrayUtil.getPrimes(23); + Assert.assertArrayEquals(primes, expected); + } + + @Test + public void getPerfectNumbers() throws Exception { + int[] perfectNumbers = {6, 28, 496, 8128}; + int[] calculatedPerfectNumbers = ArrayUtil.getPerfectNumbers(8220); + Assert.assertArrayEquals(perfectNumbers, calculatedPerfectNumbers); + } + + @Test + public void join() throws Exception { + { + int[] array = {1}; + String joinStr = ArrayUtil.join(array, "-"); + Assert.assertEquals("1", joinStr); + } + + { + int[] array = {1, 2, 3}; + String joinStr = ArrayUtil.join(array, "-"); + Assert.assertEquals("1-2-3", joinStr); + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/DownloadThread.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..031c966086 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/DownloadThread.java @@ -0,0 +1,79 @@ +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; +import java.io.IOException; +import java.io.RandomAccessFile; + +public class DownloadThread extends Thread { + + private int endPos; + private int startPos; + private String url; + private String destFilePath; + private ConnectionManager connManager; + private DownloadListener downloadListener; + + public DownloadThread(ConnectionManager connManager, String url, int startPos, int endPos, String destFilePath, + DownloadListener downloadListener) { + + this.url = url; + this.endPos = endPos; + this.startPos = startPos; + this.connManager = connManager; + this.destFilePath = destFilePath; + this.downloadListener = downloadListener; + } + + @Override + public void run() { + Connection conn = null; + RandomAccessFile randomAccessFile = null; + try { + doLog("BIN"); + conn = connManager.open(url, startPos, endPos); + byte[] read = conn.read(startPos, endPos); + String _filePath = destFilePath; + if (_filePath == null || _filePath.length() == 0) { + _filePath = conn.getFileName(); + } + randomAccessFile = new RandomAccessFile(_filePath, "rw"); + randomAccessFile.seek(startPos); + randomAccessFile.write(read); + doLog("END"); + } catch (IOException e) { + doLog("EXP"); + e.printStackTrace(); + } catch (ConnectionException e) { + doLog("EXP"); + e.printStackTrace(); + } finally { + if (randomAccessFile != null) { + try { + randomAccessFile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (conn != null) { + conn.close(); + } + if (downloadListener != null) { + downloadListener.notifyFinished(); + } + } + } + + private void doLog(String action) { + System.out.println( + "*********** " + action + + " [" + + startPos + + "-" + + endPos + + "]" + + " ***********"); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloader.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..aeeb726f53 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloader.java @@ -0,0 +1,81 @@ +package com.coderising.download; + +import com.coderising.download.api.ConnectionException; +import com.coderising.download.api.ConnectionManager; +import com.coderising.download.api.DownloadListener; +import java.util.concurrent.atomic.AtomicInteger; + +public class FileDownloader { + + private String url; + + private DownloadListener listener; + + private ConnectionManager cm; + + private AtomicInteger atomicInteger; + + public FileDownloader(String _url) { + this.url = _url; + atomicInteger = new AtomicInteger(); + } + + /** + * 在这里实现你的代码, 注意: 需要用多线程实现下载 + * 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 + * (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方法 + * + * 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + */ + public void execute() { + try { + + int threadCount = 5; + int length = this.cm.getContentLength(this.url); + for (int i = 0; i < threadCount; i++) { + + int threadLoadLength = length / threadCount; + int startPos = threadLoadLength * i; + int endPos; + if (i != threadCount - 1) { + endPos = threadLoadLength * (i + 1) - 1; + } else { + endPos = length - 1; + } + atomicInteger.getAndIncrement(); + new DownloadThread(cm, this.url, startPos, endPos, null, new DownloadListener() { + @Override + public void notifyFinished() { + if (atomicInteger.decrementAndGet() == 0) { + if (FileDownloader.this.listener != null) { + FileDownloader.this.listener.notifyFinished(); + } + } + } + }).start(); + } + } catch (ConnectionException e) { + e.printStackTrace(); + } + } + + public void setConnectionManager(ConnectionManager ucm) { + this.cm = ucm; + } + + public DownloadListener getListener() { + return this.listener; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloaderTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..404e55594f --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/FileDownloaderTest.java @@ -0,0 +1,55 @@ +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://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://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz"; + + 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("下载完成!"); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/Connection.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/Connection.java new file mode 100644 index 0000000000..46f573f5f2 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/Connection.java @@ -0,0 +1,33 @@ +package com.coderising.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return 读取的字节数组 + */ + byte[] read(int startPos, int endPos) throws IOException; + + /** + * 得到数据内容的长度 + * + * @return 数据内容长度 + */ + int getContentLength(); + + /** + * 关闭连接 + */ + void close(); + + /** + * 获取下载文件的文件名 + * + * @return 文件名 + */ + String getFileName(); +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionException.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..45d5e3a83b --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,11 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception { + public ConnectionException(Exception e) { + super(e); + } + + public ConnectionException(String msg) { + super(msg); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionManager.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..d0a7b84fcc --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/ConnectionManager.java @@ -0,0 +1,21 @@ +package com.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * + * @param url 连接地址 + * @param startPos 读取文件的起始位置 + * @param endPos 读取文件的结束位置 + * @return 连接 + */ + Connection open(String url, int startPos, int endPos) throws ConnectionException; + + /** + * 获取文件长度 + * + * @param url 连接地址 + * @return 文件长度 + */ + int getContentLength(String url) throws ConnectionException; +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/DownloadListener.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..b7100fa723 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public interface DownloadListener { + void notifyFinished(); +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionImpl.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..b9efbb3794 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,93 @@ +package com.coderising.download.impl; + +import com.coderising.download.api.Connection; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +public class ConnectionImpl implements Connection { + + private static final int BUFFER_SIZE = 4096; + private HttpURLConnection httpConn; + private String fileUrl; + private InputStream inputStream; + + public ConnectionImpl(HttpURLConnection httpConn, String fileUrl) { + this.httpConn = httpConn; + this.fileUrl = fileUrl; + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + if (endPos < startPos) { + throw new IllegalArgumentException("argument endPos[" + endPos + "] less than startPos[" + startPos + "]"); + } + int bytesNeed2Read = endPos - startPos + 1; + if (bytesNeed2Read > getContentLength()) { + throw new IllegalArgumentException( + "endPos[" + endPos + "] is bigger than content length[" + getContentLength() + "]"); + } + + inputStream = httpConn.getInputStream(); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[Math.min(bytesNeed2Read, BUFFER_SIZE)]; + int read; + + long startTime = System.currentTimeMillis(); + final long progressInterval = 2000; + while ((read = inputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, read); + + if (System.currentTimeMillis() - startTime > progressInterval) { + startTime = System.currentTimeMillis(); + System.out.println(String.format(Thread.currentThread().getName() + + " [%.2f%%]", byteArrayOutputStream.size() * 100.0 / bytesNeed2Read) + ); + } + } + System.out.println(String.format(Thread.currentThread().getName() + " [%.2f%%]", 100.0)); + System.out.println("bytes read: " + byteArrayOutputStream.size()); + + return byteArrayOutputStream.toByteArray(); + } + + @Override + public int getContentLength() { + if (httpConn != null) { + return httpConn.getContentLength(); + } + return 0; + } + + @Override + public void close() { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (httpConn != null) { + httpConn.disconnect(); + } + } + + @Override + public String getFileName() { + String disposition = httpConn.getHeaderField("Content-Disposition"); + if (disposition != null) { + // extracts file name from header field + int index = disposition.indexOf("filename="); + if (index > 0) { + return disposition.substring(index + 10, + disposition.length() - 1); + } + } + // extracts file name from URL + return fileUrl.substring(fileUrl.lastIndexOf("/") + 1, + fileUrl.length()); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionManagerImpl.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..c3ad775b11 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,60 @@ +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.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String fileURL, int startPos, int endPos) throws ConnectionException { + try { + System.out.println("try to open file url: " + fileURL); + + URL url = new URL(fileURL); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + + // 设定读取range + httpConn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + System.out.println("Range: bytes=" + startPos + "-" + endPos); + + int responseCode = httpConn.getResponseCode(); + + System.out.println("server replied HTTP code: " + responseCode); + if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_PARTIAL) { + System.out.println("return new ConnectionImpl"); + return new ConnectionImpl(httpConn, fileURL); + } else { + throw new ConnectionException("server replied HTTP code: " + responseCode); + } + } catch (IOException e) { + throw new ConnectionException(e); + } + } + + @Override + public int getContentLength(String fileURL) throws ConnectionException { + try { + System.out.println("try to open file url: " + fileURL); + + URL url = new URL(fileURL); + HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); + int responseCode = httpConn.getResponseCode(); + + System.out.println("server replied HTTP code: " + responseCode); + if (responseCode == HttpURLConnection.HTTP_OK) { + System.out.println("return contentLength: " + httpConn.getContentLength()); + int contentLength = httpConn.getContentLength(); + httpConn.disconnect(); + return contentLength; + } else { + throw new ConnectionException("server replied HTTP code: " + responseCode); + } + } catch (IOException e) { + throw new ConnectionException(e); + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/LoginAction.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/LoginAction.java new file mode 100644 index 0000000000..f187e45227 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/LoginAction.java @@ -0,0 +1,41 @@ +package com.coderising.litestruts; + +/** + * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 + * + * @author liuxin + */ +public class LoginAction { + private String name; + private String password; + private String message; + + 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 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 getMessage() { + return this.message; + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/Struts.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/Struts.java new file mode 100644 index 0000000000..a282279ff4 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/Struts.java @@ -0,0 +1,111 @@ +package com.coderising.litestruts; + +import com.coderising.litestruts.dom.StrutsAction; +import com.coderising.litestruts.util.StrutsParser; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class Struts { + + /** + * 0. 读取配置文件struts.xml + * + * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) + * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 + * ("name"="test" , "password"="1234") , + * 那就应该调用 setName和setPassword方法 + * + * 2. 通过反射调用对象的execute 方法, 并获得返回值,例如"success" + * + * 3. 通过反射找到对象的所有getter方法(例如 getMessage), + * 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , + * 放到View对象的parameters + * + * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, + * 放到View对象的jsp字段中。 + */ + public static View runAction(String actionName, Map parameters) { + Map actionMap = StrutsParser.doParse(); + StrutsAction action = actionMap.get(actionName); + + if (action == null) { + System.out.println("couldn't get action: " + actionName + ", return"); + return null; + } + + try { + // 通过反射, 创建实例对象 + Class actionClass = Class.forName(action.getActionClassName()); + Object actionObj = actionClass.newInstance(); + + // 调用 parameters 中的 set 方法 + for (Map.Entry parameterEntry : parameters.entrySet()) { + Method[] methods = actionClass.getMethods(); + for (Method method : methods) { + if (method.getName().equalsIgnoreCase("set" + parameterEntry.getKey())) { + method.invoke(actionObj, parameterEntry.getValue()); + } + } + } + //for (Map.Entry parameterEntry : parameters.entrySet()) { + // for (PropertyDescriptor propertyDescriptor : + // Introspector.getBeanInfo(actionClass).getPropertyDescriptors()) { + // if (propertyDescriptor.getDisplayName().equals(parameterEntry.getKey())) { + // Method writeMethod = propertyDescriptor.getWriteMethod(); + // writeMethod.invoke(actionObj, parameterEntry.getValue()); + // } + // } + //} + + // 调用 execute 方法 + Method executeMethod = actionClass.getMethod("execute"); + Object executeResult = executeMethod.invoke(actionObj); + + // 根据 execute 方法的结果, 获取 xml 配置的 jsp 页面 + String jsp = action.getAttributes().get(Objects.toString(executeResult)); + + // 调用 get 方法 + Map actionFieldMap = new HashMap<>(); + Field[] actionFields = actionClass.getDeclaredFields(); + for (Field actionFiled : actionFields) { + Method[] methods = actionClass.getMethods(); + for (Method method : methods) { + if (method.getName().equalsIgnoreCase("get" + actionFiled.getName())) { + method.invoke(actionObj); + actionFieldMap.put(actionFiled.getName(), Objects.toString(method.invoke(actionObj))); + } + } + } + //for (PropertyDescriptor propertyDescriptor : + // Introspector.getBeanInfo(actionClass).getPropertyDescriptors()) { + // Method readMethod = propertyDescriptor.getReadMethod(); + // Object readMethodResult = readMethod.invoke(actionObj); + // actionFieldMap.put(propertyDescriptor.getDisplayName(), Objects.toString(readMethodResult)); + //} + + // 返回 View 对象 + View view = new View(); + view.setParameters(actionFieldMap); + view.setJsp(jsp); + return view; + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + }/* catch (IntrospectionException e) { + e.printStackTrace(); + }*/ + + return null; + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/StrutsTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..9d940ed44b --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/StrutsTest.java @@ -0,0 +1,37 @@ +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")); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/View.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..e96403d8fc --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/View.java @@ -0,0 +1,26 @@ +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; + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/dom/StrutsAction.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/dom/StrutsAction.java similarity index 92% rename from group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/dom/StrutsAction.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/dom/StrutsAction.java index c16de22c44..e08c65bbc4 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/dom/StrutsAction.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/dom/StrutsAction.java @@ -1,4 +1,4 @@ -package org.korben.coderising.litestruts.dom; +package com.coderising.litestruts.dom; import java.util.Map; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/StrutsParser.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/util/StrutsParser.java similarity index 91% rename from group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/StrutsParser.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/util/StrutsParser.java index 239ac2e4cd..74a85739c4 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/StrutsParser.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coderising/litestruts/util/StrutsParser.java @@ -1,8 +1,8 @@ -package org.korben.coderising.litestruts.util; +package com.coderising.litestruts.util; +import com.coderising.litestruts.dom.StrutsAction; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -10,7 +10,6 @@ import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; -import org.korben.coderising.litestruts.dom.StrutsAction; /** * 解析struts.xml @@ -72,7 +71,7 @@ public static Map doParse() { private static InputStream getStrutsInputStream() { StrutsParser.class.getPackage().getName(); InputStream in = StrutsParser.class.getClassLoader() - .getResourceAsStream("org/korben/coderising/litestruts/util/" + STRUTS_XML); + .getResourceAsStream("com/coderising/litestruts/util/" + STRUTS_XML); if (in == null) { throw new IllegalStateException(STRUTS_XML + " doesn't exist"); } diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrame.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..63ff3851c0 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,104 @@ +package com.coding.basic.linklist; + +/** + * 用双向链表实现LRU算法 + * + * @author Korben + */ +public class LRUPageFrame { + + private int capacity; + private int size; + private Node first; // 链表头 + private Node last; // 链表尾 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + */ + public void access(int pageNum) { + if (this.first == null) { + add2First(pageNum); + return; + } + + if (this.first.pageNum == pageNum) { + return; + } + + if (reorderCache(pageNum)) { + return; + } + + add2First(pageNum); + + if (this.size > this.capacity) { + removeNode(this.last); + } + } + + private boolean reorderCache(int pageNum) { + Node node = this.first; + for (int i = 0; i < this.size - 1; i++) { + node = node.next; + if (node.pageNum == pageNum) { + removeNode(node); + add2First(node.pageNum); + return true; + } + } + + return false; + } + + private void removeNode(Node node) { + node.prev.next = node.next; + if (node.next != null) { + node.next.prev = node.prev; + } else { + this.last = node.prev; + } + this.size--; + } + + private void add2First(int pageNum) { + Node oldFirst = this.first; + this.first = new Node(pageNum); + this.first.next = oldFirst; + if (oldFirst == null) { + this.last = this.first; + } else { + oldFirst.prev = this.first; + } + + this.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(); + } + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node(int pageNum) { + this.pageNum = pageNum; + } + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrameTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..3569190716 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,28 @@ +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/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KArrayList.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KArrayList.java similarity index 98% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KArrayList.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KArrayList.java index 5df5408e67..dc67aa7516 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KArrayList.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KArrayList.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; import java.util.Objects; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KIterator.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KIterator.java similarity index 75% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KIterator.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KIterator.java index b5245ecca0..83be164f95 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KIterator.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KIterator.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; /** * Created by Korben on 24/02/2017. diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedList.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedList.java similarity index 99% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedList.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedList.java index 5f0975d3fb..5ce4fdc916 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedList.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedList.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; import java.util.ArrayList; import java.util.List; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedListTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedListTest.java similarity index 99% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedListTest.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedListTest.java index f086efdbdc..e7a35a7a49 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KLinkedListTest.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KLinkedListTest.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; import org.junit.Assert; import org.junit.Before; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KList.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KList.java similarity index 91% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KList.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KList.java index e5b166094e..a70076509e 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KList.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KList.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; /** * Korben's List diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListIteratorTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListIteratorTest.java similarity index 94% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListIteratorTest.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListIteratorTest.java index 7017e0ed2c..2cab546462 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListIteratorTest.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListIteratorTest.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; import org.junit.Assert; import org.junit.Before; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListTest.java similarity index 99% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListTest.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListTest.java index d789318174..8edc8e2b31 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/list/KListTest.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/list/KListTest.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.list; +package com.coding.basic.list; import java.util.Objects; import org.junit.Assert; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KArrayQueue.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KArrayQueue.java similarity index 98% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KArrayQueue.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KArrayQueue.java index eea57cf035..3b47fcce1b 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KArrayQueue.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KArrayQueue.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.queue; +package com.coding.basic.queue; import java.util.NoSuchElementException; diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueue.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueue.java similarity index 84% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueue.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueue.java index 9d8146d50d..d5719527aa 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueue.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueue.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.queue; +package com.coding.basic.queue; /** * Korben's Queue Interface diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueueTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueueTest.java similarity index 97% rename from group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueueTest.java rename to group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueueTest.java index 17c3703a64..ef1f930e58 100644 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/queue/KQueueTest.java +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/queue/KQueueTest.java @@ -1,4 +1,4 @@ -package org.korben.coding.basic.queue; +package com.coding.basic.queue; import java.util.NoSuchElementException; import org.junit.Assert; diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/Stack.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..a76dc3a16a --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,72 @@ +package com.coding.basic.stack; + +import java.util.EmptyStackException; +import java.util.Objects; + +/** + * Korben's Stack + * + * Created by Korben on 18/02/2017. + */ +public class Stack { + + private int size; + private Object[] dataArray = {}; + + public Stack() { + } + + public int size() { + return size; + } + + public T push(T item) { + ensureCapacity(size + 1); + this.dataArray[size] = item; + this.size++; + return item; + } + + @SuppressWarnings("unchecked") + public T pop() { + if (size == 0) { + throw new EmptyStackException(); + } + + T data = (T) this.dataArray[size - 1]; + this.dataArray[size - 1] = null; + this.size--; + return data; + } + + @SuppressWarnings("unchecked") + public T peek() { + if (size == 0) { + throw new EmptyStackException(); + } + return (T) dataArray[size - 1]; + } + + public boolean isEmpty() { + return size == 0; + } + + public synchronized int search(Object o) { + for (int i = 0; i < size; i++) { + if (Objects.equals(o, dataArray[i])) { + return i; + } + } + return -1; + } + + private void ensureCapacity(int minCapacity) { + if (minCapacity > dataArray.length) { + int newCapacity = Math.max(minCapacity, dataArray.length * 2); + Object[] newDataArray = new Object[newCapacity]; + System.arraycopy(dataArray, 0, newDataArray, 0, dataArray.length); + + this.dataArray = newDataArray; + } + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackTest.java new file mode 100644 index 0000000000..9e47545014 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackTest.java @@ -0,0 +1,71 @@ +package com.coding.basic.stack; + +import java.util.EmptyStackException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * KStack测试 + * + * Created by Korben on 18/02/2017. + */ +public class StackTest { + private Stack stack; + private int initTestSize; + + @Before + public void init() { + stack = new Stack<>(); + initTestSize = 5; + + for (int i = 0; i < initTestSize; i++) { + stack.push(i); + } + } + + @Test + public void size() throws Exception { + Assert.assertEquals(initTestSize, stack.size()); + } + + @Test + public void push() throws Exception { + stack.push(9); + } + + @Test(expected = EmptyStackException.class) + public void pop() throws Exception { + for (int i = 0; i < initTestSize; i++) { + Integer value = stack.pop(); + Assert.assertEquals(value.intValue(), initTestSize - 1 - i); + } + + stack.pop(); + } + + @Test(expected = EmptyStackException.class) + public void peek() throws Exception { + Assert.assertEquals(initTestSize - 1, stack.peek().intValue()); + for (int i = 0; i < initTestSize; i++) { + stack.pop(); + } + stack.peek(); + } + + @Test + public void empty() throws Exception { + Assert.assertFalse(stack.isEmpty()); + for (int i = 0; i < initTestSize; i++) { + stack.pop(); + } + Assert.assertTrue(stack.isEmpty()); + } + + @Test + public void search() throws Exception { + for (int i = 0; i < initTestSize; i++) { + Assert.assertEquals(i, stack.search(i)); + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtil.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..a9df9b8d88 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,130 @@ +package com.coding.basic.stack; + +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 || s.isEmpty()) { + return; + } + + Stack tmp = new Stack(); + + for (int i = 0; i < s.size(); i++) { + tmp.push(get(s, i)); + } + while (!s.isEmpty()) { + s.pop(); + } + while (!tmp.isEmpty()) { + s.push(tmp.pop()); + } + } + + private static Object get(Stack s, int indexFromBottom) { + Stack tmp = new Stack(); + int size = s.size(); + for (int i = 0; i < size - indexFromBottom - 1; i++) { + tmp.push(s.pop()); + } + + Object rtn = s.peek(); + while (!tmp.isEmpty()) { + s.push(tmp.pop()); + } + return rtn; + } + + /** + * 删除栈中的某个元素 注意:只能使用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 data = s.pop(); + if (Objects.equals(data, o)) { + break; + } + + tmp.push(data); + } + + while (!tmp.isEmpty()) { + s.push(tmp.pop()); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len 长度 + */ + public static Object[] getTop(Stack s, int len) { + if (len < 0 || len >= s.size()) { + throw new IndexOutOfBoundsException(); + } + + Object[] rtn = new Object[len]; + Stack tmp = new Stack(); + for (int i = 0; i < len; i++) { + Object data = s.pop(); + rtn[i] = data; + tmp.push(data); + } + + for (int i = 0; i < len; i++) { + s.push(tmp.pop()); + } + + return rtn; + } + + /** + * 字符串s 可能包含这些字符: ( ) [ ] { }, a,b,c... x,yz + * 使用堆栈检查字符串s中的括号是不是成对出现的。 + * 例如s = "([e{d}f])" , 则该字符串中的括号是成对出现, 该方法返回true + * 如果 s = "([b{x]y})", 则该字符串中的括号不是成对出现的, 该方法返回false; + * + * @param s 输入字符串 + */ + public static boolean isValidPairs(String s) { + String[] chars = s.split(""); + + Stack stack = new Stack(); + for (int i = 0; i < chars.length; i++) { + if ("(".equals(chars[i])) { + stack.push(")"); + } else if ("[".equals(chars[i])) { + stack.push("]"); + } else if ("{".equals(chars[i])) { + stack.push("}"); + } else if (")".equals(chars[i])) { + if (!stack.pop().equals(")")) { + return false; + } + } else if ("]".equals(chars[i])) { + if (!stack.pop().equals("]")) { + return false; + } + } else if ("}".equals(chars[i])) { + if (!stack.pop().equals("}")) { + return false; + } + } + } + return true; + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtilTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..845a53b826 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,81 @@ +package com.coding.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Korben on 09/04/2017. + */ +public class StackUtilTest { + + private Stack stack; + + @Before + public void setUp() { + stack = new Stack(); + for (int i = 0; i < 5; i++) { + stack.push(i); + } + } + + @Test + public void reverse() throws Exception { + StackUtil.reverse(stack); + + for (int i = 0; i < 5; i++) { + Assert.assertEquals(i, stack.pop()); + } + + stack.push(1); + StackUtil.reverse(stack); + Assert.assertEquals(1, stack.pop()); + } + + @Test + public void remove() throws Exception { + StackUtil.remove(stack, 1); + Assert.assertEquals(stack.size(), 4); + for (int i = 4; i >= 0; i--) { + if (i == 1) { + continue; + } + Assert.assertEquals(i, stack.pop()); + } + + stack.push(1); + Assert.assertEquals(stack.size(), 1); + } + + @Test + public void getTop() throws Exception { + Object[] top = StackUtil.getTop(stack, 3); + Assert.assertEquals(top.length, 3); + Assert.assertEquals(top[0], 4); + Assert.assertEquals(top[1], 3); + Assert.assertEquals(top[2], 2); + + Assert.assertEquals(stack.size(), 5); + + stack.push(1); + Assert.assertEquals(stack.size(), 6); + stack.pop(); + + for (int i = 0; i < 5; i++) { + Assert.assertEquals(4 - i, stack.pop()); + } + } + + @Test + public void isValidPairs() throws Exception { + { + String str = "([e{d}f])"; + Assert.assertTrue(StackUtil.isValidPairs(str)); + } + + { + String str = "([b{x]y})"; + Assert.assertFalse(StackUtil.isValidPairs(str)); + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..7efc063bba --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,103 @@ +package com.coding.basic.stack.expr; + +import com.coding.basic.stack.Stack; +import java.util.Arrays; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public static void main(String[] args) { + String[] ss = new InfixExpr("3*20+12*5-40/2").getOperatorsAndNumbers("3*20+12*5-40/2"); + System.out.println(Arrays.toString(ss)); + } + + /** + * 根据输入的表达式,计算结果 + * 只支持 +、-、*、/,不支持括号 + * 数值只支持整数 + * + * @return 计算结果 + */ + public float evaluate() { + if (expr == null) { + throw new NullPointerException("expr can't be null!"); + } + + Stack operators = new Stack<>(); + Stack nums = new Stack<>(); + + String[] operatorsAndNumbers = getOperatorsAndNumbers(expr); + + for (int i = 0; i < operatorsAndNumbers.length; i++) { + String data = operatorsAndNumbers[i]; + if ("+".equals(data) || "-".equals(data)) { + operators.push(data); + } + // "*" 的优先级最高,遇到 "*" 直接进行计算 + else if ("*".equals(data)) { + nums.push(nums.pop().floatValue() * Integer.valueOf(operatorsAndNumbers[++i])); + } + // "/" 的优先级最高,遇到 "/" 直接进行计算 + else if ("/".equals(data)) { + nums.push(nums.pop().floatValue() / Integer.valueOf(operatorsAndNumbers[++i])); + } + // 如果是数值,判断数值下一位的操作符,如果是 "+" 或 "-", + // 则优先级不高于堆栈中存储的操作符,取出堆栈中的进行计算 + else { + if ((i + 1 < operatorsAndNumbers.length && !nums.isEmpty()) + && + ("+".equals(operatorsAndNumbers[i + 1]) || "-".equals(operatorsAndNumbers[i + 1])) + ) { + String operator = operators.pop(); + float rightValue = Integer.valueOf(data); + float leftValue = nums.pop().floatValue(); + + if ("+".equals(operator)) { + nums.push(leftValue + rightValue); + } else { + nums.push(leftValue - rightValue); + } + } else { + try { + nums.push(Integer.valueOf(data)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("表达式不合法!"); + } + } + } + } + + if (!operators.isEmpty()) { + String operator = operators.pop(); + float rightValue = nums.pop().floatValue(); + float leftValue = nums.pop().floatValue(); + + if ("+".equals(operator)) { + nums.push(leftValue + rightValue); + } else { + nums.push(leftValue - rightValue); + } + } + + return nums.pop().floatValue(); + } + + private String[] getOperatorsAndNumbers(String expr) { + String[] numberArray = expr.split("\\+|-|\\*|/"); + String[] operatorsArray = expr.split("[0-9]+"); + + String[] operatorsAndNumbers = new String[operatorsArray.length + numberArray.length - 1]; + for (int i = 1; i < operatorsArray.length; i++) { + operatorsAndNumbers[2 * i - 1] = operatorsArray[i]; + } + for (int i = 0; i < numberArray.length; i++) { + operatorsAndNumbers[2 * i] = numberArray[i]; + } + + return operatorsAndNumbers; + } +} diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..77768b3847 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,44 @@ +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("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/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNode.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNode.java new file mode 100644 index 0000000000..3c788266c9 --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNode.java @@ -0,0 +1,127 @@ +package com.coding.basic.tree; + +/** + * Korben's BinaryTreeNode + * + * Created by Korben on 21/02/2017. + */ +public class BinaryTreeNode { + + private T data; + private BinaryTreeNode left; + private BinaryTreeNode right; + private int size; + + 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; + } + + @SuppressWarnings("unchecked") + public BinaryTreeNode insert(T data) { + if (this.data == null) { + this.data = data; + return this; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + if (this.left == null) { + this.left = new BinaryTreeNode(); + this.left.data = data; + return this.left; + } else { + return this.left.insert(data); + } + } else if (compareResult < 0) { + if (this.right == null) { + this.right = new BinaryTreeNode(); + this.right.data = data; + return this.right; + } else { + return this.right.insert(data); + } + } else { + return this; + } + } + + @SuppressWarnings("unchecked") + public BinaryTreeNode delete(T data) { + BinaryTreeNode treeNode = search(data); + if (treeNode == null) { + return null; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + return this.left.delete(data); + } else if (compareResult < 0) { + return this.right.delete(data); + } else { + if (treeNode.right == null) { + if (this.left == null) { + this.data = null; + } else { + this.left = this; + } + } else { + this.data = (T) this.right.findMin().data; + + this.right.delete(this.data); + } + } + + return this; + } + + private BinaryTreeNode findMin() { + if (this.data == null) { + return null; + } + if (this.left == null) { + return this; + } + return this.left.findMin(); + } + + @SuppressWarnings("unchecked") + public BinaryTreeNode search(T data) { + if (this.data == null) { + return null; + } + int compareResult = this.data.compareTo(data); + if (compareResult > 0) { + if (this.left == null) { + return null; + } else { + return this.left.search(data); + } + } else if (compareResult < 0) { + if (this.right == null) { + return null; + } else { + return this.right.search(data); + } + } else { + return this; + } + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNodeTest.java b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..51f9263e9a --- /dev/null +++ b/group20/1107837739/1107837739Learning/data-structure/src/com/coding/basic/tree/BinaryTreeNodeTest.java @@ -0,0 +1,59 @@ +package com.coding.basic.tree; + +import org.junit.Assert; + +/** + * Korben's BinaryTreeNode Test + * + * Created by Korben on 21/02/2017. + */ +public class BinaryTreeNodeTest { + + private BinaryTreeNode treeNode; + + @org.junit.Before + public void setUp() throws Exception { + treeNode = new BinaryTreeNode<>(); + treeNode.insert(5); + treeNode.insert(3); + treeNode.insert(7); + treeNode.insert(1); + treeNode.insert(4); + treeNode.insert(2); + treeNode.insert(8); + treeNode.insert(6); + } + + @org.junit.Test + public void insert() { + Assert.assertEquals(treeNode.getData().intValue(), 5); + Assert.assertEquals(treeNode.getLeft().getData(), 3); + Assert.assertEquals(treeNode.getRight().getData(), 7); + Assert.assertEquals(treeNode.getLeft().getLeft().getData(), 1); + Assert.assertEquals(treeNode.getLeft().getRight().getData(), 4); + Assert.assertEquals(treeNode.getLeft().getLeft().getRight().getData(), 2); + Assert.assertEquals(treeNode.getRight().getRight().getData(), 8); + Assert.assertEquals(treeNode.getRight().getLeft().getData(), 6); + } + + @org.junit.Test + public void delete() throws Exception { + treeNode.delete(3); + for (int i = 1; i < 9; i++) { + if (i != 3) { + Assert.assertNotNull(treeNode.search(i)); + } else { + Assert.assertNull(treeNode.search(i)); + } + } + } + + @org.junit.Test + public void search() throws Exception { + for (int i = 1; i < 9; i++) { + Assert.assertNotNull(treeNode.search(i)); + } + Assert.assertNull(treeNode.search(0)); + Assert.assertNull(treeNode.search(9)); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-io-2.5.jar b/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-io-2.5.jar new file mode 100644 index 0000000000..107b061f5f Binary files /dev/null and b/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-io-2.5.jar differ diff --git a/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-lang3-3.5.jar b/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-lang3-3.5.jar new file mode 100644 index 0000000000..6328c8de41 Binary files /dev/null and b/group20/1107837739/1107837739Learning/mini-jvm/lib/commons-lang3-3.5.jar differ diff --git a/group20/1107837739/1107837739Learning/mini-jvm/lib/hamcrest-core-1.3.jar b/group20/1107837739/1107837739Learning/mini-jvm/lib/hamcrest-core-1.3.jar new file mode 100644 index 0000000000..9d5fe16e3d Binary files /dev/null and b/group20/1107837739/1107837739Learning/mini-jvm/lib/hamcrest-core-1.3.jar differ diff --git a/group20/1107837739/1107837739Learning/mini-jvm/lib/junit-4.12.jar b/group20/1107837739/1107837739Learning/mini-jvm/lib/junit-4.12.jar new file mode 100644 index 0000000000..3a7fc266c3 Binary files /dev/null and b/group20/1107837739/1107837739Learning/mini-jvm/lib/junit-4.12.jar differ diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..1edbad5321 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/AttributeInfo.java @@ -0,0 +1,18 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..8876114724 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/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.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo { + private int maxStack; + private int maxLocals; + private int codeLen; + private String 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 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: " + code); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionCodeLen = iter.nextU2ToInt(); + if (exceptionCodeLen > 0) { + String exTable = iter.nextUxToHexString(exceptionCodeLen); + System.out.println("Encountered exception table, just ignore it"); + } + + int subAttrCount = iter.nextU2ToInt(); + + for (int i = 0; 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(subAttrName + " hasn't been implemented yet"); + } + } + + return codeAttr; + } + + public String getCode() { + return code; + } + + public void setLineNumberTable(LineNumberTable t) { + this.lineNumTable = t; + } + + public void setLocalVariableTable(LocalVariableTable t) { + this.localVarTable = t; + } + + private void setStackMapTable(StackMapTable t) { + this.stackMapTable = t; + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..fa037d407f --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LineNumberTable.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.attr; + +import com.coderising.jvm.loader.ByteCodeIterator; +import java.util.ArrayList; +import java.util.List; + +public class LineNumberTable extends AttributeInfo { + List items = new ArrayList(); + + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static LineNumberTable parse(ByteCodeIterator iter) { + int attributeNameIndex = iter.nextU2ToInt(); + int attributeLen = iter.nextU4ToInt(); + int itemLen = iter.nextU2ToInt(); + + LineNumberTable numberTable = new LineNumberTable(attributeNameIndex, attributeLen); + + for (int i = 0; i < itemLen; i++) { + LineNumberItem item = new LineNumberItem(); + item.setStartPC(iter.nextU2ToInt()); + item.setLineNum(iter.nextU2ToInt()); + + numberTable.addLineNumberItem(item); + } + return numberTable; + } + + public void addLineNumberItem(LineNumberItem item) { + this.items.add(item); + } + + 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; + } + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..224858246a --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..93cbe31c82 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/LocalVariableTable.java @@ -0,0 +1,37 @@ +package com.coderising.jvm.attr; + +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); + } + + public static LocalVariableTable parse(ByteCodeIterator iter) { + int attributeNameIndex = iter.nextU2ToInt(); + int attributeLen = iter.nextU4ToInt(); + int itemLen = iter.nextU2ToInt(); + + LocalVariableTable variableTable = new LocalVariableTable(attributeNameIndex, attributeLen); + for (int i = 0; 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()); + + variableTable.addLocalVariableItem(item); + } + return variableTable; + } + + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..9f838584fd --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/attr/StackMapTable.java @@ -0,0 +1,28 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..74c8c09b58 --- /dev/null +++ b/group20/1107837739/1107837739Learning/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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..a56d8793dc --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,97 @@ +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()); + } + + 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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..86dd768e57 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,22 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..6d4b1b0614 --- /dev/null +++ b/group20/1107837739/1107837739Learning/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(); + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..f95b04cff4 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,30 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..1f65ae0d0c --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,30 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..92aa99b18d --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,57 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..08bed198d3 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,56 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..d7cd146895 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,48 @@ +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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..0ee9e721ad --- /dev/null +++ b/group20/1107837739/1107837739Learning/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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..5cd3df772e --- /dev/null +++ b/group20/1107837739/1107837739Learning/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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..49bfcb9434 --- /dev/null +++ b/group20/1107837739/1107837739Learning/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; + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/field/Field.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..c52202ee69 --- /dev/null +++ b/group20/1107837739/1107837739Learning/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.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(); + + System.out.println("Filed accessFlag: " + accessFlag); + System.out.println("Filed nameIndex: " + nameIndex); + System.out.println("Filed descriptorIndex: " + descriptorIndex); + System.out.println("Filed attributeCount: " + attributeCount); + + if (attributeCount > 0) { + throw new RuntimeException("Filed attribute hasn't been implemented yet"); + } + + return new Field(accessFlag, nameIndex, descriptorIndex, pool); + } + + @Override + public String toString() { + String name = pool.getUTF8String(this.nameIndex); + String desc = pool.getUTF8String(this.descriptorIndex); + + return name + ":" + desc; + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..2667b40753 --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,53 @@ +package com.coderising.jvm.loader; + +import com.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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..20fb8c530e --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,59 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.clz.ClassFile; +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.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/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..78b419c23f --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,146 @@ +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.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.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 java.io.UnsupportedEncodingException; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + + String magicNumber = iterator.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + + classFile.setMinorVersion(iterator.nextU2ToInt()); + classFile.setMajorVersion(iterator.nextU2ToInt()); + + classFile.setConstPool(parseConstantPool(iterator)); + classFile.setAccessFlag(parseAccessFlag(iterator)); + classFile.setClassIndex(parseClassInfex(iterator)); + + parseInterfaces(classFile, iterator); + + parseFields(classFile, iterator); + + parseMethods(classFile, iterator); + + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2ToInt()); + return accessFlag; + } + + 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 pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i < constantPoolCount; i++) { + int type = iter.nextU1toInt(); + + if (type == ConstantInfo.CLASS_INFO) { + int utf8Index = iter.nextU2ToInt(); + ClassInfo clzInfo = new ClassInfo(pool); + clzInfo.setUtf8Index(utf8Index); + + pool.addConstantInfo(clzInfo); + } else if (type == ConstantInfo.UTF8_INFO) { + int len = iter.nextU2ToInt(); + byte[] data = iter.getBytes(len); + + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + // ignore + } + + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setLength(len); + utf8Info.setValue(value); + + pool.addConstantInfo(utf8Info); + } else if (type == ConstantInfo.STRING_INFO) { + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.nextU2ToInt()); + + pool.addConstantInfo(stringInfo); + } else if (type == ConstantInfo.FIELD_INFO) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + + pool.addConstantInfo(fieldRefInfo); + } else if (type == ConstantInfo.METHOD_INFO) { + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + + pool.addConstantInfo(methodRefInfo); + } else if (type == ConstantInfo.NAME_AND_TYPE_INFO) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(iter.nextU2ToInt()); + nameAndTypeInfo.setIndex2(iter.nextU2ToInt()); + + pool.addConstantInfo(nameAndTypeInfo); + } else { + throw new RuntimeException("the constant pool type " + type + " hasn't been implemented yet!"); + } + } + + return pool; + } + + private void parseInterfaces(ClassFile clzFile, ByteCodeIterator iter) { + int interfaceCount = iter.nextU2ToInt(); + + System.out.println("Interface Count: " + interfaceCount); + } + + private void parseFields(ClassFile clzFile, ByteCodeIterator iter) { + int filedCount = iter.nextU2ToInt(); + System.out.println("Field Count: " + filedCount); + + for (int i = 0; i < filedCount; i++) { + Field field = Field.parse(clzFile.getConstantPool(), iter); + clzFile.addField(field); + } + } + + private void parseMethods(ClassFile clzFile, ByteCodeIterator iter) { + int methodCount = iter.nextU2ToInt(); + System.out.println("Method Count: " + methodCount); + + for (int i = 0; i < methodCount; i++) { + Method method = Method.parse(clzFile, iter); + clzFile.addMethod(method); + } + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/method/Method.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/method/Method.java new file mode 100644 index 0000000000..bc3d9a843a --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/method/Method.java @@ -0,0 +1,73 @@ +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.loader.ByteCodeIterator; + +public class Method { + + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + + private ClassFile clzFile; + + 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) { + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + int attributeCount = iter.nextU2ToInt(); + + System.out.println("Filed accessFlag: " + accessFlag); + System.out.println("Filed nameIndex: " + nameIndex); + System.out.println("Filed descriptorIndex: " + descriptorIndex); + System.out.println("Filed attributeCount: " + attributeCount); + + Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); + + for (int i = 0; i < attributeCount; 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); + method.setCodeAttr(codeAttr); + } else { + throw new RuntimeException("Only CODE attribute is implemented!"); + } + } + + return method; + } + + 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; + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..e92c5580ac --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,258 @@ +package com.coderising.jvm.test; + +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.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; +import java.util.List; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class ClassFileloaderTest { + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "/Users/Korben/Downloads"; + 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); + } + + 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); + } +} diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..029d3c8d3d --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,29 @@ +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 static void main(String[] args) { + EmployeeV1 p = new EmployeeV1("Andy", 29); + p.sayHello(); + } + + 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 "); + } +} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/util/Util.java b/group20/1107837739/1107837739Learning/mini-jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..f6e9689c5a --- /dev/null +++ b/group20/1107837739/1107837739Learning/mini-jvm/src/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 < 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/group20/1107837739/1107837739Learning/src/org/korben/Main.java b/group20/1107837739/1107837739Learning/src/org/korben/Main.java deleted file mode 100644 index 671f67a9a7..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/Main.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.korben; - -public class Main { - - public static void main(String[] args) { - System.out.println("Hello Korben : )"); - } -} diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtil.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtil.java deleted file mode 100644 index 87ea998621..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,258 +0,0 @@ -package org.korben.coderising.array; - -import java.util.ArrayList; -import java.util.List; - -/** - * ArrayUtil - * - * Created by Korben on 26/02/2017. - */ -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 static void reverseArray(int[] origin) { - ensureNotNull(origin); - - int length = origin.length; - for (int i = 0; i < length / 2; i++) { - int tmp = origin[i]; - origin[i] = origin[length - i - 1]; - origin[length - i - 1] = 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} - */ - public static int[] removeZero(int[] oldArray) { - ensureNotNull(oldArray); - - int nonZeroCount = 0; - for (int i : oldArray) { - if (i != 0) { - nonZeroCount++; - } - } - - int newArr[] = new int[nonZeroCount]; - int newArrIndex = 0; - for (int i : oldArray) { - if (i != 0) { - newArr[newArrIndex++] = i; - } - } - - return newArr; - } - - /** - * 给定两个已经排序好的整形数组, a1和a2 , 创建一个新的数组a3, 使得a3 包含a1和a2 的所有元素, 并且仍然是有序的 - * 例如 a1 = [3, 5, 7,8] a2 = [4, 5, 6,7] 则 a3 为[3,4,5,6,7,8] , 注意: 已经消除了重复 - */ - public static int[] merge(int[] array1, int[] array2) { - ensureNotNull(array1); - ensureNotNull(array2); - - int maxArraySize = array1.length + array2.length; - int[] mergedArray = new int[maxArraySize]; - - int index1 = 0; - int index2 = 0; - int mergedIndex = -1; - for (int i = 0; i < maxArraySize; i++) { - if (index1 == array1.length) { - System.arraycopy(array2, index2, mergedArray, mergedIndex + 1, array2.length - index2); - mergedIndex += array2.length - index2; - break; - } else if (index2 == array2.length) { - System.arraycopy(array1, index1, mergedArray, mergedIndex + 1, array1.length - index1); - mergedIndex += array1.length - index1; - break; - } else { - int compare = Integer.compare(array1[index1], array2[index2]); - if (compare < 0) { - mergedArray[++mergedIndex] = array1[index1++]; - } else if (compare > 0) { - mergedArray[++mergedIndex] = array2[index2++]; - } else { - mergedArray[++mergedIndex] = array1[index1++]; - index2++; - } - } - } - - // 清除数组多余部分 - if (mergedIndex + 1 < maxArraySize) { - int[] resultArray = new int[mergedIndex + 1]; - System.arraycopy(mergedArray, 0, resultArray, 0, mergedIndex + 1); - return resultArray; - } - - return mergedArray; - } - - /** - * 把一个已经存满数据的数组 oldArray的容量进行扩展, 扩展后的新数据大小为oldArray.length + size - * 注意,老数组的元素在新数组中需要保持 - * 例如 oldArray = [2,3,6] , size = 3,则返回的新数组为 - * [2,3,6,0,0,0] - */ - public static int[] grow(int[] oldArray, int size) { - ensureNotNull(oldArray); - - if (size < 0) { - throw new IllegalArgumentException("size must > 0"); - } - - int[] newArray = new int[oldArray.length + size]; - - System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); - for (int i = oldArray.length; i < newArray.length; i++) { - newArray[i] = 0; - } - - return newArray; - } - - /** - * 斐波那契数列为:1,1,2,3,5,8,13,21...... ,给定一个最大值, 返回小于该值的数列 - * 例如, max = 15 , 则返回的数组应该为 [1,1,2,3,5,8,13] - * max = 1, 则返回空数组 [] - */ - public static int[] fibonacci(int max) { - if (max == 1) { - int[] array = new int[1]; - array[1] = 1; - return array; - } - - List list = new ArrayList<>(); - - for (int i = 1; ; i++) { - int fibonacciNumber = getFibonacciNumber(i); - if (fibonacciNumber <= max) { - list.add(fibonacciNumber); - } else { - break; - } - } - - return list2Array(list); - } - - private static int getFibonacciNumber(int index) { - if (index == 1) { - return 1; - } - if (index == 2) { - return 1; - } - return getFibonacciNumber(index - 2) + getFibonacciNumber(index - 1); - } - - /** - * 返回小于给定最大值max的所有素数数组 - * 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - */ - public static int[] getPrimes(int max) { - List primeList = new ArrayList<>(); - if (max <= 1) { - return new int[0]; - } - - if (max >= 2) { - primeList.add(2); - } - - // 所有偶数都不是素数, 所以这里采用 i += 2 - for (int i = 3; i < max; i += 2) { - if (isPrimeNumber(i, primeList)) { - primeList.add(i); - } - } - - return list2Array(primeList); - } - - private static boolean isPrimeNumber(int number, List primeList) { - for (Integer prime : primeList) { - if (number % prime == 0) { - return false; - } - } - return true; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 - * 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - */ - public static int[] getPerfectNumbers(int max) { - if (max <= 1) { - return new int[0]; - } - - List perfectNumberList = new ArrayList<>(); - for (int i = 2; i < max; i++) { - if (isPerfectNumber(i)) { - perfectNumberList.add(i); - } - } - return list2Array(perfectNumberList); - } - - private static boolean isPerfectNumber(int number) { - int sum = 1; - for (int i = 2; i <= number / 2; i++) { - if (number % i == 0) { - sum += i; - } - } - - return sum == number; - } - - /** - * 用separator 把数组 array给连接起来 - * 例如array= [3,8,9], separator = "-" - * 则返回值为"3-8-9" - */ - public static String join(int[] array, String separator) { - ensureNotNull(array); - - if (separator == null) { - throw new NullPointerException(); - } - - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - stringBuilder.append(array[i]); - if (i != array.length - 1) { - stringBuilder.append(separator); - } - } - - return stringBuilder.toString(); - } - - private static 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 static void ensureNotNull(int[] array) { - if (array == null) { - throw new NullPointerException(); - } - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtilTest.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtilTest.java deleted file mode 100644 index 9f23e2c341..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/array/ArrayUtilTest.java +++ /dev/null @@ -1,185 +0,0 @@ -package org.korben.coderising.array; - -import org.junit.Assert; -import org.junit.Test; - -/** - * ArrayUtil test - * - * Created by Korben on 26/02/2017. - */ -public class ArrayUtilTest { - - @Test - public void reverseArray() throws Exception { - // test reverse even number - { - int[] testArray = new int[5]; - for (int i = 0; i < 5; i++) { - testArray[i] = i; - } - ArrayUtil.reverseArray(testArray); - for (int i = 0; i < 5; i++) { - Assert.assertEquals(5 - 1 - i, testArray[i]); - } - } - - // test reverse odd number - { - int[] testArray = new int[4]; - for (int i = 0; i < 4; i++) { - testArray[i] = i; - } - ArrayUtil.reverseArray(testArray); - for (int i = 0; i < 4; i++) { - Assert.assertEquals(4 - 1 - i, testArray[i]); - } - } - } - - @Test - public void removeZero() throws Exception { - // 测试非空数组 - { - int[] testArray = new int[20]; - for (int i = 0; i < 20; i++) { - if (i % 5 == 0) { - testArray[i] = 0; - } else { - testArray[i] = i; - } - } - - int[] newArray = ArrayUtil.removeZero(testArray); - Assert.assertNotNull(newArray); - for (int i = 0; i < 20; i++) { - if (i % 5 == 0) { - continue; - } - - Assert.assertEquals(testArray[i], i); - } - } - - // 测试空数组 - { - int[] testArray = new int[5]; - for (int i = 0; i < 5; i++) { - testArray[i] = 0; - } - - int[] newArray = ArrayUtil.removeZero(testArray); - Assert.assertNotNull(newArray); - Assert.assertEquals(newArray.length, 0); - } - } - - @Test - public void merge() throws Exception { - // 构建数组 - int[] array1 = new int[10]; - int[] array2 = new int[11]; - array2[10] = 100; - for (int i = 0; i < 10; i++) { - if (i % 2 == 0) { - array1[i / 2] = i; // 0, 2, 4, 6, 8 - } else { - array2[i / 2] = i; // 1, 3, 5, 7, 9 - } - } - - for (int i = 10; i < 15; i++) { - array1[i - 5] = i; // 10, 11, 12, 13, 14, 15 - array2[i - 5] = i; // 10, 11, 12, 13, 14, 15 - } - - // 测试merge - { - int[] merge = ArrayUtil.merge(array1, array2); - Assert.assertNotNull(merge); - Assert.assertEquals(merge.length, 16); - for (int i = 0; i < 15; i++) { - Assert.assertEquals(merge[i], i); - } - Assert.assertEquals(merge[15], 100); - } - // 调换数组顺序 - { - int[] merge = ArrayUtil.merge(array2, array1); - Assert.assertNotNull(merge); - Assert.assertEquals(merge.length, 16); - for (int i = 0; i < 15; i++) { - Assert.assertEquals(merge[i], i); - } - Assert.assertEquals(merge[15], 100); - } - // 测试空数组 - { - int[] array3 = new int[0]; - int[] merge1 = ArrayUtil.merge(array1, array3); - Assert.assertArrayEquals(merge1, array1); - - int[] merge2 = ArrayUtil.merge(array3, array1); - Assert.assertArrayEquals(merge2, array1); - } - // 测试相同数组 - { - int[] merge = ArrayUtil.merge(array1, array1); - Assert.assertArrayEquals(merge, array1); - } - } - - @Test - public void grow() throws Exception { - int[] oldArray = new int[5]; - for (int i = 0; i < 5; i++) { - oldArray[i] = i; - } - - int[] newArray = ArrayUtil.grow(oldArray, 5); - for (int i = 0; i < 10; i++) { - if (i < 5) { - Assert.assertEquals(newArray[i], i); - } else { - Assert.assertEquals(newArray[i], 0); - } - } - } - - @Test - public void fibonacci() throws Exception { - int[] fibonacciArray = {1, 1, 2, 3, 5, 8, 13, 21}; - - int[] calculatedFibonacci = ArrayUtil.fibonacci(22); - Assert.assertArrayEquals(fibonacciArray, calculatedFibonacci); - } - - @Test - public void getPrimes() throws Exception { - int[] expected = {2, 3, 5, 7, 11, 13, 17, 19}; - int[] primes = ArrayUtil.getPrimes(23); - Assert.assertArrayEquals(primes, expected); - } - - @Test - public void getPerfectNumbers() throws Exception { - int[] perfectNumbers = {6, 28, 496, 8128}; - int[] calculatedPerfectNumbers = ArrayUtil.getPerfectNumbers(8220); - Assert.assertArrayEquals(perfectNumbers, calculatedPerfectNumbers); - } - - @Test - public void join() throws Exception { - { - int[] array = {1}; - String joinStr = ArrayUtil.join(array, "-"); - Assert.assertEquals("1", joinStr); - } - - { - int[] array = {1, 2, 3}; - String joinStr = ArrayUtil.join(array, "-"); - Assert.assertEquals("1-2-3", joinStr); - } - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/DownloadThread.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/DownloadThread.java deleted file mode 100644 index 52a5fd20a9..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/DownloadThread.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.korben.coderising.download; - -import java.io.IOException; -import java.io.RandomAccessFile; -import org.korben.coderising.download.api.Connection; -import org.korben.coderising.download.api.ConnectionException; -import org.korben.coderising.download.api.ConnectionManager; -import org.korben.coderising.download.api.DownloadListener; - -public class DownloadThread extends Thread { - - private int endPos; - private int startPos; - private String url; - private String destFilePath; - private ConnectionManager connManager; - private DownloadListener downloadListener; - - public DownloadThread(ConnectionManager connManager, String url, int startPos, int endPos, String destFilePath, - DownloadListener downloadListener) { - - this.url = url; - this.endPos = endPos; - this.startPos = startPos; - this.connManager = connManager; - this.destFilePath = destFilePath; - this.downloadListener = downloadListener; - } - - @Override - public void run() { - Connection conn = null; - RandomAccessFile randomAccessFile = null; - try { - doLog("BIN"); - conn = connManager.open(url, startPos, endPos); - byte[] read = conn.read(startPos, endPos); - String _filePath = destFilePath; - if (_filePath == null || _filePath.length() == 0) { - _filePath = conn.getFileName(); - } - randomAccessFile = new RandomAccessFile(_filePath, "rw"); - randomAccessFile.seek(startPos); - randomAccessFile.write(read); - doLog("END"); - } catch (IOException e) { - doLog("EXP"); - e.printStackTrace(); - } catch (ConnectionException e) { - doLog("EXP"); - e.printStackTrace(); - } finally { - if (randomAccessFile != null) { - try { - randomAccessFile.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (conn != null) { - conn.close(); - } - if (downloadListener != null) { - downloadListener.notifyFinished(); - } - } - } - - private void doLog(String action) { - System.out.println( - "*********** " + action - + " [" - + startPos - + "-" - + endPos - + "]" - + " ***********"); - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloader.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloader.java deleted file mode 100644 index 43fde0b69e..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloader.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.korben.coderising.download; - -import java.util.concurrent.atomic.AtomicInteger; -import org.korben.coderising.download.api.ConnectionException; -import org.korben.coderising.download.api.ConnectionManager; -import org.korben.coderising.download.api.DownloadListener; - -public class FileDownloader { - - private String url; - - private DownloadListener listener; - - private ConnectionManager cm; - - private AtomicInteger atomicInteger; - - public FileDownloader(String _url) { - this.url = _url; - atomicInteger = new AtomicInteger(); - } - - /** - * 在这里实现你的代码, 注意: 需要用多线程实现下载 - * 这个类依赖于其他几个接口, 你需要写这几个接口的实现代码 - * (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方法 - * - * 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 - */ - public void execute() { - try { - - int threadCount = 5; - int length = this.cm.getContentLength(this.url); - for (int i = 0; i < threadCount; i++) { - - int threadLoadLength = length / threadCount; - int startPos = threadLoadLength * i; - int endPos; - if (i != threadCount - 1) { - endPos = threadLoadLength * (i + 1) - 1; - } else { - endPos = length - 1; - } - atomicInteger.getAndIncrement(); - new DownloadThread(cm, this.url, startPos, endPos, null, new DownloadListener() { - @Override - public void notifyFinished() { - if (atomicInteger.decrementAndGet() == 0) { - if (FileDownloader.this.listener != null) { - FileDownloader.this.listener.notifyFinished(); - } - } - } - }).start(); - } - } catch (ConnectionException e) { - e.printStackTrace(); - } - } - - public void setConnectionManager(ConnectionManager ucm) { - this.cm = ucm; - } - - public DownloadListener getListener() { - return this.listener; - } - - public void setListener(DownloadListener listener) { - this.listener = listener; - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloaderTest.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloaderTest.java deleted file mode 100644 index 53b6b6e45e..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/FileDownloaderTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.korben.coderising.download; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.korben.coderising.download.api.ConnectionManager; -import org.korben.coderising.download.api.DownloadListener; -import org.korben.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 = "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://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz"; - - 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("下载完成!"); - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/Connection.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/Connection.java deleted file mode 100644 index 6f58852d56..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/Connection.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.korben.coderising.download.api; - -import java.io.IOException; - -public interface Connection { - /** - * 给定开始和结束位置, 读取数据, 返回值是字节数组 - * - * @param startPos 开始位置, 从0开始 - * @param endPos 结束位置 - * @return 读取的字节数组 - */ - byte[] read(int startPos, int endPos) throws IOException; - - /** - * 得到数据内容的长度 - * - * @return 数据内容长度 - */ - int getContentLength(); - - /** - * 关闭连接 - */ - void close(); - - /** - * 获取下载文件的文件名 - * - * @return 文件名 - */ - String getFileName(); -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionException.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionException.java deleted file mode 100644 index d74b432783..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionException.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.korben.coderising.download.api; - -public class ConnectionException extends Exception { - public ConnectionException(Exception e) { - super(e); - } - - public ConnectionException(String msg) { - super(msg); - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionManager.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionManager.java deleted file mode 100644 index 5e0d4afe3f..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/ConnectionManager.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.korben.coderising.download.api; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * - * @param url 连接地址 - * @param startPos 读取文件的起始位置 - * @param endPos 读取文件的结束位置 - * @return 连接 - */ - Connection open(String url, int startPos, int endPos) throws ConnectionException; - - /** - * 获取文件长度 - * - * @param url 连接地址 - * @return 文件长度 - */ - int getContentLength(String url) throws ConnectionException; -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/DownloadListener.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/DownloadListener.java deleted file mode 100644 index e2685665b7..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.korben.coderising.download.api; - -public interface DownloadListener { - void notifyFinished(); -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionImpl.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionImpl.java deleted file mode 100644 index cce16fafbe..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.korben.coderising.download.impl; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import org.korben.coderising.download.api.Connection; - -public class ConnectionImpl implements Connection { - - private static final int BUFFER_SIZE = 4096; - private HttpURLConnection httpConn; - private String fileUrl; - private InputStream inputStream; - - public ConnectionImpl(HttpURLConnection httpConn, String fileUrl) { - this.httpConn = httpConn; - this.fileUrl = fileUrl; - } - - @Override - public byte[] read(int startPos, int endPos) throws IOException { - if (endPos < startPos) { - throw new IllegalArgumentException("argument endPos[" + endPos + "] less than startPos[" + startPos + "]"); - } - int bytesNeed2Read = endPos - startPos + 1; - if (bytesNeed2Read > getContentLength()) { - throw new IllegalArgumentException( - "endPos[" + endPos + "] is bigger than content length[" + getContentLength() + "]"); - } - - inputStream = httpConn.getInputStream(); - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - byte[] buffer = new byte[Math.min(bytesNeed2Read, BUFFER_SIZE)]; - int read; - - long startTime = System.currentTimeMillis(); - final long progressInterval = 2000; - while ((read = inputStream.read(buffer)) != -1) { - byteArrayOutputStream.write(buffer, 0, read); - - if (System.currentTimeMillis() - startTime > progressInterval) { - startTime = System.currentTimeMillis(); - System.out.println(String.format(Thread.currentThread().getName() + - " [%.2f%%]", byteArrayOutputStream.size() * 100.0 / bytesNeed2Read) - ); - } - } - System.out.println(String.format(Thread.currentThread().getName() + " [%.2f%%]", 100.0)); - System.out.println("bytes read: " + byteArrayOutputStream.size()); - - return byteArrayOutputStream.toByteArray(); - } - - @Override - public int getContentLength() { - if (httpConn != null) { - return httpConn.getContentLength(); - } - return 0; - } - - @Override - public void close() { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (httpConn != null) { - httpConn.disconnect(); - } - } - - @Override - public String getFileName() { - String disposition = httpConn.getHeaderField("Content-Disposition"); - if (disposition != null) { - // extracts file name from header field - int index = disposition.indexOf("filename="); - if (index > 0) { - return disposition.substring(index + 10, - disposition.length() - 1); - } - } - // extracts file name from URL - return fileUrl.substring(fileUrl.lastIndexOf("/") + 1, - fileUrl.length()); - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionManagerImpl.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index 16d8df8f7c..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.korben.coderising.download.impl; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import org.korben.coderising.download.api.Connection; -import org.korben.coderising.download.api.ConnectionException; -import org.korben.coderising.download.api.ConnectionManager; - -public class ConnectionManagerImpl implements ConnectionManager { - - @Override - public Connection open(String fileURL, int startPos, int endPos) throws ConnectionException { - try { - System.out.println("try to open file url: " + fileURL); - - URL url = new URL(fileURL); - HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); - - // 设定读取range - httpConn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); - System.out.println("Range: bytes=" + startPos + "-" + endPos); - - int responseCode = httpConn.getResponseCode(); - - System.out.println("server replied HTTP code: " + responseCode); - if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_PARTIAL) { - System.out.println("return new ConnectionImpl"); - return new ConnectionImpl(httpConn, fileURL); - } else { - throw new ConnectionException("server replied HTTP code: " + responseCode); - } - } catch (IOException e) { - throw new ConnectionException(e); - } - } - - @Override - public int getContentLength(String fileURL) throws ConnectionException { - try { - System.out.println("try to open file url: " + fileURL); - - URL url = new URL(fileURL); - HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); - int responseCode = httpConn.getResponseCode(); - - System.out.println("server replied HTTP code: " + responseCode); - if (responseCode == HttpURLConnection.HTTP_OK) { - System.out.println("return contentLength: " + httpConn.getContentLength()); - int contentLength = httpConn.getContentLength(); - httpConn.disconnect(); - return contentLength; - } else { - throw new ConnectionException("server replied HTTP code: " + responseCode); - } - } catch (IOException e) { - throw new ConnectionException(e); - } - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/LoginAction.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/LoginAction.java deleted file mode 100644 index 20fa9e766b..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/LoginAction.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.korben.coderising.litestruts; - -/** - * 这是一个用来展示登录的业务类, 其中的用户名和密码都是硬编码的。 - * - * @author liuxin - */ -public class LoginAction { - private String name; - private String password; - private String message; - - 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 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 getMessage() { - return this.message; - } -} diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/Struts.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/Struts.java deleted file mode 100644 index 7ac88522bf..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/Struts.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.korben.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; -import java.util.Objects; -import org.korben.coderising.litestruts.dom.StrutsAction; -import org.korben.coderising.litestruts.util.StrutsParser; - -public class Struts { - - /** - * 0. 读取配置文件struts.xml - * - * 1. 根据actionName找到相对应的class , 例如LoginAction, 通过反射实例化(创建对象) - * 据parameters中的数据,调用对象的setter方法, 例如parameters中的数据是 - * ("name"="test" , "password"="1234") , - * 那就应该调用 setName和setPassword方法 - * - * 2. 通过反射调用对象的execute 方法, 并获得返回值,例如"success" - * - * 3. 通过反射找到对象的所有getter方法(例如 getMessage), - * 通过反射来调用, 把值和属性形成一个HashMap , 例如 {"message": "登录成功"} , - * 放到View对象的parameters - * - * 4. 根据struts.xml中的 配置,以及execute的返回值, 确定哪一个jsp, - * 放到View对象的jsp字段中。 - */ - public static View runAction(String actionName, Map parameters) { - Map actionMap = StrutsParser.doParse(); - StrutsAction action = actionMap.get(actionName); - - if (action == null) { - System.out.println("couldn't get action: " + actionName + ", return"); - return null; - } - - try { - // 通过反射, 创建实例对象 - Class actionClass = Class.forName(action.getActionClassName()); - Object actionObj = actionClass.newInstance(); - - // 调用 parameters 中的 set 方法 - for (Map.Entry parameterEntry : parameters.entrySet()) { - Method[] methods = actionClass.getMethods(); - for (Method method : methods) { - if (method.getName().equalsIgnoreCase("set" + parameterEntry.getKey())) { - method.invoke(actionObj, parameterEntry.getValue()); - } - } - } - //for (Map.Entry parameterEntry : parameters.entrySet()) { - // for (PropertyDescriptor propertyDescriptor : - // Introspector.getBeanInfo(actionClass).getPropertyDescriptors()) { - // if (propertyDescriptor.getDisplayName().equals(parameterEntry.getKey())) { - // Method writeMethod = propertyDescriptor.getWriteMethod(); - // writeMethod.invoke(actionObj, parameterEntry.getValue()); - // } - // } - //} - - // 调用 execute 方法 - Method executeMethod = actionClass.getMethod("execute"); - Object executeResult = executeMethod.invoke(actionObj); - - // 根据 execute 方法的结果, 获取 xml 配置的 jsp 页面 - String jsp = action.getAttributes().get(Objects.toString(executeResult)); - - // 调用 get 方法 - Map actionFieldMap = new HashMap<>(); - Field[] actionFields = actionClass.getDeclaredFields(); - for (Field actionFiled : actionFields) { - Method[] methods = actionClass.getMethods(); - for (Method method : methods) { - if (method.getName().equalsIgnoreCase("get" + actionFiled.getName())) { - method.invoke(actionObj); - actionFieldMap.put(actionFiled.getName(), Objects.toString(method.invoke(actionObj))); - } - } - } - //for (PropertyDescriptor propertyDescriptor : - // Introspector.getBeanInfo(actionClass).getPropertyDescriptors()) { - // Method readMethod = propertyDescriptor.getReadMethod(); - // Object readMethodResult = readMethod.invoke(actionObj); - // actionFieldMap.put(propertyDescriptor.getDisplayName(), Objects.toString(readMethodResult)); - //} - - // 返回 View 对象 - View view = new View(); - view.setParameters(actionFieldMap); - view.setJsp(jsp); - return view; - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - }/* catch (IntrospectionException e) { - e.printStackTrace(); - }*/ - - return null; - } -} diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/StrutsTest.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/StrutsTest.java deleted file mode 100644 index 024f678100..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/StrutsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.korben.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")); - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/View.java b/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/View.java deleted file mode 100644 index f4af03febc..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/View.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.korben.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; - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/struts.xml b/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/struts.xml deleted file mode 100644 index 1cb3f4a5df..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coderising/litestruts/util/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/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStack.java b/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStack.java deleted file mode 100644 index eb83eb47cd..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStack.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.korben.coding.basic.stack; - -import java.util.EmptyStackException; -import java.util.Objects; - -/** - * Korben's Stack - * - * Created by Korben on 18/02/2017. - */ -public class KStack { - - private int size; - private Object[] dataArray = {}; - - public KStack() { - } - - public int size() { - return size; - } - - public T push(T item) { - ensureCapacity(size + 1); - this.dataArray[size] = item; - this.size++; - return item; - } - - @SuppressWarnings("unchecked") - public T pop() { - if (size == 0) { - throw new EmptyStackException(); - } - - T data = (T) this.dataArray[size - 1]; - this.dataArray[size - 1] = null; - this.size--; - return data; - } - - @SuppressWarnings("unchecked") - public T peek() { - if (size == 0) { - throw new EmptyStackException(); - } - return (T) dataArray[size - 1]; - } - - public boolean empty() { - return size == 0; - } - - public synchronized int search(Object o) { - for (int i = 0; i < size; i++) { - if (Objects.equals(o, dataArray[i])) { - return i; - } - } - return -1; - } - - private void ensureCapacity(int minCapacity) { - if (minCapacity > dataArray.length) { - int newCapacity = Math.max(minCapacity, dataArray.length * 2); - Object[] newDataArray = new Object[newCapacity]; - System.arraycopy(dataArray, 0, newDataArray, 0, dataArray.length); - - this.dataArray = newDataArray; - } - } -} diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStackTest.java b/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStackTest.java deleted file mode 100644 index 20b451a7ef..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/stack/KStackTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.korben.coding.basic.stack; - -import java.util.EmptyStackException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * KStack测试 - * - * Created by Korben on 18/02/2017. - */ -public class KStackTest { - private KStack stack; - private int initTestSize; - - @Before - public void init() { - stack = new KStack<>(); - initTestSize = 5; - - for (int i = 0; i < initTestSize; i++) { - stack.push(i); - } - } - - @Test - public void size() throws Exception { - Assert.assertEquals(initTestSize, stack.size()); - } - - @Test - public void push() throws Exception { - stack.push(9); - } - - @Test(expected = EmptyStackException.class) - public void pop() throws Exception { - for (int i = 0; i < initTestSize; i++) { - Integer value = stack.pop(); - Assert.assertEquals(value.intValue(), initTestSize - 1 - i); - } - - stack.pop(); - } - - @Test(expected = EmptyStackException.class) - public void peek() throws Exception { - Assert.assertEquals(initTestSize - 1, stack.peek().intValue()); - for (int i = 0; i < initTestSize; i++) { - stack.pop(); - } - stack.peek(); - } - - @Test - public void empty() throws Exception { - Assert.assertFalse(stack.empty()); - for (int i = 0; i < initTestSize; i++) { - stack.pop(); - } - Assert.assertTrue(stack.empty()); - } - - @Test - public void search() throws Exception { - for (int i = 0; i < initTestSize; i++) { - Assert.assertEquals(i, stack.search(i)); - } - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNode.java b/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNode.java deleted file mode 100644 index 3cfcacc37c..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNode.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.korben.coding.basic.tree; - -/** - * Korben's BinaryTreeNode - * - * Created by Korben on 21/02/2017. - */ -public class BinaryTreeNode { - - private T data; - private BinaryTreeNode left; - private BinaryTreeNode right; - private int size; - - 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; - } - - @SuppressWarnings("unchecked") - public BinaryTreeNode insert(T data) { - if (this.data == null) { - this.data = data; - return this; - } - int compareResult = this.data.compareTo(data); - if (compareResult > 0) { - if (this.left == null) { - this.left = new BinaryTreeNode(); - this.left.data = data; - return this.left; - } else { - return this.left.insert(data); - } - } else if (compareResult < 0) { - if (this.right == null) { - this.right = new BinaryTreeNode(); - this.right.data = data; - return this.right; - } else { - return this.right.insert(data); - } - } else { - return this; - } - } - - @SuppressWarnings("unchecked") - public BinaryTreeNode delete(T data) { - BinaryTreeNode treeNode = search(data); - if (treeNode == null) { - return null; - } - int compareResult = this.data.compareTo(data); - if (compareResult > 0) { - return this.left.delete(data); - } else if (compareResult < 0) { - return this.right.delete(data); - } else { - if (treeNode.right == null) { - if (this.left == null) { - this.data = null; - } else { - this.left = this; - } - } else { - this.data = (T) this.right.findMin().data; - - this.right.delete(this.data); - } - } - - return this; - } - - private BinaryTreeNode findMin() { - if (this.data == null) { - return null; - } - if (this.left == null) { - return this; - } - return this.left.findMin(); - } - - @SuppressWarnings("unchecked") - public BinaryTreeNode search(T data) { - if (this.data == null) { - return null; - } - int compareResult = this.data.compareTo(data); - if (compareResult > 0) { - if (this.left == null) { - return null; - } else { - return this.left.search(data); - } - } else if (compareResult < 0) { - if (this.right == null) { - return null; - } else { - return this.right.search(data); - } - } else { - return this; - } - } -} \ No newline at end of file diff --git a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNodeTest.java b/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNodeTest.java deleted file mode 100644 index 05873872a7..0000000000 --- a/group20/1107837739/1107837739Learning/src/org/korben/coding/basic/tree/BinaryTreeNodeTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.korben.coding.basic.tree; - -import org.junit.Assert; - -/** - * Korben's BinaryTreeNode Test - * - * Created by Korben on 21/02/2017. - */ -public class BinaryTreeNodeTest { - - private BinaryTreeNode treeNode; - - @org.junit.Before - public void setUp() throws Exception { - treeNode = new BinaryTreeNode<>(); - treeNode.insert(5); - treeNode.insert(3); - treeNode.insert(7); - treeNode.insert(1); - treeNode.insert(4); - treeNode.insert(2); - treeNode.insert(8); - treeNode.insert(6); - } - - @org.junit.Test - public void insert() { - Assert.assertEquals(treeNode.getData().intValue(), 5); - Assert.assertEquals(treeNode.getLeft().getData(), 3); - Assert.assertEquals(treeNode.getRight().getData(), 7); - Assert.assertEquals(treeNode.getLeft().getLeft().getData(), 1); - Assert.assertEquals(treeNode.getLeft().getRight().getData(), 4); - Assert.assertEquals(treeNode.getLeft().getLeft().getRight().getData(), 2); - Assert.assertEquals(treeNode.getRight().getRight().getData(), 8); - Assert.assertEquals(treeNode.getRight().getLeft().getData(), 6); - } - - @org.junit.Test - public void delete() throws Exception { - treeNode.delete(3); - for (int i = 1; i < 9; i++) { - if (i != 3) { - Assert.assertNotNull(treeNode.search(i)); - } else { - Assert.assertNull(treeNode.search(i)); - } - } - } - - @org.junit.Test - public void search() throws Exception { - for (int i = 1; i < 9; i++) { - Assert.assertNotNull(treeNode.search(i)); - } - Assert.assertNull(treeNode.search(0)); - Assert.assertNull(treeNode.search(9)); - } -} \ No newline at end of file diff --git a/group20/1107837739/korben.md b/group20/1107837739/korben.md index 1259561cb0..927e364da5 100644 --- a/group20/1107837739/korben.md +++ b/group20/1107837739/korben.md @@ -7,3 +7,5 @@ | [初窥计算机程序的运行](http://korben-chy.github.io/2017/02/26/%E5%88%9D%E7%AA%A5%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%BF%90%E8%A1%8C/) | 2017/02/26 | | [程序在计算机中的运行过程简析](http://korben-chy.github.io/2017/03/06/%E7%A8%8B%E5%BA%8F%E5%9C%A8%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%B8%AD%E7%9A%84%E8%BF%90%E8%A1%8C%E8%BF%87%E7%A8%8B%E7%AE%80%E6%9E%90) | 2017/03/05 | | [并发编程之-Volatile浅析](http://korben-chy.github.io/2017/03/12/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E4%B9%8B-Volatile%E6%B5%85%E6%9E%90) | 2017/03/12 | +| [并发编程之-synchronized浅析](http://blog.korbenc.space/2017/03/29/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E4%B9%8B-synchronized%E6%B5%85%E6%9E%90/) | 2017/03/29 | +| [Java类加载器--Classloader](http://blog.korbenc.space/2017/04/09/Java%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%99%A8-Classloader/) | 2017/04/09 | diff --git a/group20/404130810/src/com/basic/linklist/LRUPageFrame.java b/group20/404130810/src/com/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..8c32659437 --- /dev/null +++ b/group20/404130810/src/com/basic/linklist/LRUPageFrame.java @@ -0,0 +1,121 @@ +package com.basic.linklist; + +/** + * ˫ʵLRU㷨 + * + * @author liuxin + * + */ +public class LRUPageFrame { + + private static class Node { + + private Node prev; + private Node next; + private 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; + + } + + /** + * ȡж + * + * @param key + * @return + */ + public void access(int pageNum) { + if (first == null && last == null) { + handleEmptyContainer(pageNum); + size++; + } else if (existingPage(pageNum) != null) { + if (size == 1) { + return; + } else if(existingPage(pageNum).pageNum == first.pageNum) { + return; + } else{ + moveToFirst(existingPage(pageNum)); + } + } else { + addFirst(pageNum); + if (!ensureCapacity()) { + removeLast(); + } + } + } + + 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 boolean ensureCapacity() { + return size <= capacity; + } + + private void handleEmptyContainer(int pageNum) { + first = new Node(pageNum); + last = first; + } + + private Node existingPage(int pageNum) { + Node node = first; + while (node != null) { + if (node.pageNum == pageNum) { + return node; + } + node = node.next; + } + return null; + } + + private void addFirst(int pageNum) { + Node newerFirstNode = new Node(pageNum); + newerFirstNode.next = first; + first.prev = newerFirstNode; + first = newerFirstNode; + size++; + } + + private void removeLast() { + Node lastPreNode = last.prev; + last.prev = null; + lastPreNode.next = null; + last = lastPreNode; + size--; + } + + private void moveToFirst(Node existingPage) { + if(existingPage.pageNum == last.pageNum){ + addFirst(existingPage.pageNum); + removeLast(); + }else{ + int tempPageNum = first.pageNum; + first.pageNum = existingPage.pageNum; + existingPage.pageNum = tempPageNum; + } + } + +} \ No newline at end of file diff --git a/group20/404130810/src/com/basic/linklist/LRUPageFrameTest.java b/group20/404130810/src/com/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..4220724649 --- /dev/null +++ b/group20/404130810/src/com/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +package com.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/group20/404130810/src/com/coderising/jvm/clz/AccessFlag.java b/group20/404130810/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..cdb8f8859a --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/clz/ClassFile.java b/group20/404130810/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..43378d0dd6 --- /dev/null +++ b/group20/404130810/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,79 @@ +package com.coderising.jvm.clz; + +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + private String magicNumer; + + private int minorVersion; + private int majorVersion; + + private AccessFlag accessFlag; + private ClassIndex clzIndex; + private ConstantPool pool; + + + + public String getMagicNumer() { + return magicNumer; + } + public void setMagicNumer(String magicNumer) { + this.magicNumer = magicNumer; + } + 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 getClzIndex() { + return clzIndex; + } + public void setClassIndex(ClassIndex clzIndex) { + this.clzIndex = clzIndex; + } + + public ConstantPool getPool() { + return pool; + } + public void setPool(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.getPool().getConstantInfo(thisClassIndex); + return thisClass.getClassName(); + } + private String getSuperClassName(){ + ClassInfo superClass = (ClassInfo)this.getPool().getConstantInfo(this.clzIndex.getSuperClassIndex()); + return superClass.getClassName(); + } + + +} diff --git a/group20/404130810/src/com/coderising/jvm/clz/ClassIndex.java b/group20/404130810/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..df22981441 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/ClassInfo.java b/group20/404130810/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e12b3e164e --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/ConstantInfo.java b/group20/404130810/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..c8035ae876 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/ConstantPool.java b/group20/404130810/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..0e940b78d0 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/FieldRefInfo.java b/group20/404130810/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ff9d5fb77 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/MethodRefInfo.java b/group20/404130810/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..0feffa65b5 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group20/404130810/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..1785dc3b33 --- /dev/null +++ b/group20/404130810/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,55 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + + + private int index_Name; + private int index_Describe; + + public int getIndex_Name() { + return index_Name; + } + + + public void setIndex_Name(int index_Name) { + this.index_Name = index_Name; + } + + + public int getIndex_Describe() { + return index_Describe; + } + + + public void setIndex_Describe(int index_Describe) { + this.index_Describe = index_Describe; + } + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index_Name); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index_Describe); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group20/404130810/src/com/coderising/jvm/constant/NullConstantInfo.java b/group20/404130810/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fa90d110fe --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/StringInfo.java b/group20/404130810/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d01065fd53 --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/constant/UTF8Info.java b/group20/404130810/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..b7407d146f --- /dev/null +++ b/group20/404130810/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/group20/404130810/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group20/404130810/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..1ded13d243 --- /dev/null +++ b/group20/404130810/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,47 @@ +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; + pos = 0; + } + public int nextByteToInt(){ + if (pos < this.codes.length) { + return Util.byteToInt(new byte[]{codes[pos++]}); + } + return -1; + } + public int next2BytesToInt(){ + if (pos < this.codes.length) { + return Util.byteToInt(new byte[]{codes[pos++],codes[pos++]}); + } + return -1; + } + public String next2BytesToHexString(){ + if (pos < this.codes.length) { + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++]}); + } + return null; + } + public String next4BytesToString(){ + if (pos < this.codes.length) { + return Util.byteToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + return null; + } + public byte[] getBytes(int length) { + if ((pos + length) < this.codes.length) { + byte[] by = new byte[length]; + for (int i = 0; i < by.length; i++) { + by[i] = this.codes[pos++]; + } + return by; + } + return null; + } +} diff --git a/group20/404130810/src/com/coderising/jvm/loader/ClassFileLoader.java b/group20/404130810/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..73a21d0157 --- /dev/null +++ b/group20/404130810/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,106 @@ +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; + +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.getIndex_Name()); + Assert.assertEquals(14, nameAndType.getIndex_Describe()); + } + // 鼸 + { + 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.getPool().getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo) clzFile.getPool().getConstantInfo(clzIndex.getSuperClassIndex()); + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + +} diff --git a/group20/404130810/src/com/coderising/jvm/test/EmployeeV1.java b/group20/404130810/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..d36b122f60 --- /dev/null +++ b/group20/404130810/src/com/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,30 @@ +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/group20/404130810/src/com/coderising/jvm/util/Util.java b/group20/404130810/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..176f70d002 --- /dev/null +++ b/group20/404130810/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> 1); i++) { - int num = origin[i]; - origin[i] = origin[origin.length - 1 - i]; - origin[origin.length - 1 - i] = num; - } - } - - /** - * 现在有如下的一个数组: 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;// 计数器 - /* - * 利用冒泡,将0元素向后排 {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} - * {1,3,4,5,0,6,6,0,5,4,7,6,7,0,5,0} {1,3,4,5,6,6,0,5,4,7,6,7,0,5,0,0} - * .... - */ - for (int i = 0; i < oldArray.length - count; i++) { - // 索引为i的元素为0,则依次将索引i的元素与i+1的元素对换 - if (oldArray[i] == 0) { - for (int j = i; j < oldArray.length - 1 - count; j++) { - int num = oldArray[j]; - oldArray[j] = oldArray[j + 1]; - oldArray[j + 1] = num; - } - count++;// 计数器+1 - i--;// 防止原索引i+1位置的元素为0, - } - } - // 创建新数组 - int[] newArray = new int[oldArray.length - count]; - System.arraycopy(oldArray, 0, newArray, 0, newArray.length); - return newArray; - } - - /** - * 现在有如下的一个数组: 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[] removeZero2(int[] oldArray) { - int count = 0;// 计数器 - for (int i = 0; i < oldArray.length; i++) { - if (oldArray[i] == 0) - count++;// 计数器+1 - } - // 创建新数组 - int[] newArray = new int[oldArray.length - count]; - for (int i = 0, j = 0; i < oldArray.length; i++) { - if (oldArray[i] != 0) { - newArray[j] = oldArray[i]; - j++; - } - } - 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) { - int[] newArray = new int[array1.length + array2.length]; - int i = 0, j = 0, k = 0; - while (i < array1.length && j < array2.length) { - // <= 都取 array1 - if (array1[i] <= array2[j]) { - // 等于时,将array2下标++ - if (array1[i] == array2[j]) - j++; - newArray[k++] = array1[i++]; - } else - newArray[k++] = array2[j++]; - - } - // 将没有循环完毕的元素插入 - while (i < array1.length) - newArray[k++] = array1[i++]; - while (j < array2.length) - newArray[k++] = array2[j++]; - int[] result = newArray; - // 长度缩短则新建数组 - if (k < newArray.length) { - result = new int[k]; - for (int l = 0; l < result.length; l++) - result[l] = newArray[l]; - } - return result; - } - - /** - * 把一个已经存满数据的数组 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[] {}; - int[] nums = new int[max]; - nums[0] = nums[1] = 1; - int flag; - for (flag = 0; (flag < max - 2 && nums[flag] + nums[flag + 1] < max); flag++) { - nums[flag + 2] = nums[flag] + nums[flag + 1]; - } - // 创建新数组 - int[] newArray = nums; - if (newArray.length != flag + 2) { - newArray = new int[flag + 2]; - for (int i = 0; i < newArray.length; i++) { - newArray[i] = nums[i]; - } - } - return newArray; - } - - /** - * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public static int[] getPrimes(int max) { - int[] array = new int[max>>1]; - int flag = 0; - for (int i = 2; i < max; i++) { - int j; - for (j = 2; j <= (i >> 1); j++) { - if (i % j == 0) - break; - - } - //如果大于,则证明j++有运行,已经完整对比 - if(j > i>>1) - array[flag++] = i; - - } - int[] newArray = array; - if(flag < array.length){ - newArray = new int[flag]; - for (int i = 0; i < newArray.length; i++) { - newArray[i] = array[i]; - } - } - return newArray; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * - * @param max - * @return - */ - public static int[] getPerfectNumbers(int max) { - int[] array = new int[max]; - int flag = 0; - for (int i = 1; i < max; i++) { - int sum = 0; - for (int j = 1; j < i; j++) { - if (i % j == 0) - sum+=j; - } - //如果大于,则证明j++有运行,已经完整对比 - if(sum == i) - array[flag++] = i; - - } - int[] newArray = array; - if(flag < array.length){ - newArray = new int[flag]; - for (int i = 0; i < newArray.length; i++) { - newArray[i] = array[i]; - } - } - return newArray; - } - - /** - * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" - * - * @param array - * @param s - * @return - */ - public static String join(int[] array, String seperator) { - String str = ""; - for (int i = 0; i < array.length; i++) - str += i != array.length - 1 ? array[i] + seperator : array[i]; - return str; - } -} diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/array/ArrayUtilTest.java b/group20/592146505/592146505Learning/src/org/wsc/coderising/array/ArrayUtilTest.java deleted file mode 100644 index e459aa175f..0000000000 --- a/group20/592146505/592146505Learning/src/org/wsc/coderising/array/ArrayUtilTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.wsc.coderising.array; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class ArrayUtilTest { - - @Test - public void testReverseArray() { - int[] nums = new int[]{7, 9 , 30, 3, 5}; - ArrayUtil.reverseArray(nums); - assertArrayEquals(nums, new int[]{5, 3 ,30, 9, 7}); - } - - /** - * 删除0 - */ - @Test - public void testRemoveZero() { - int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; - nums = ArrayUtil.removeZero(nums); - assertArrayEquals(nums, new int[]{7, 9 ,30, 3, 5}); - } - - /** - * 删除0 - */ - @Test - public void testRemoveZero2() { - int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; - nums = ArrayUtil.removeZero2(nums); - assertArrayEquals(nums, new int[]{7, 9 ,30, 3, 5}); - } - - /** - * 拼接 - */ - @Test - public void testJoin() { - int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; - String str = ArrayUtil.join(nums,"-"); - assertEquals(str, "0-7-9-0-0-30-0-3-5-0"); - } - - /** - * 扩容 - */ - @Test - public void testGrow() { - int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5}; - nums = ArrayUtil.grow(nums,3); - assertTrue(nums.length==12); - } - - /** - * 合并 - */ - @Test - public void testMerge() { - int[] nums = new int[]{3, 5, 7,8}; - int[] nums2 = new int[]{4, 5, 6,7,8}; - nums = ArrayUtil.merge(nums,nums2); - assertTrue(nums.length==6); - assertArrayEquals(nums, new int[]{3, 4 ,5, 6, 7,8}); - } - - /** - *斐波那契数列 - */ - @Test - public void testFibonacci() { - int[] nums = ArrayUtil.fibonacci(15); - assertTrue(nums.length==7); - assertArrayEquals(nums, new int[]{1,1,2,3,5,8,13}); - } - - /** - * 素数 - */ - @Test - public void testGetPrimes() { - int[] nums = ArrayUtil.getPrimes(23); - assertTrue(nums.length==8); - assertArrayEquals(nums, new int[]{2,3,5,7,11,13,17,19}); - } - - /** - * 完数 - */ - @Test - public void testGetPerfectNumbers() { - int[] nums = ArrayUtil.getPerfectNumbers(10000); - assertTrue(nums.length==4); - assertArrayEquals(nums, new int[]{6,28,496,8128}); - } - -} diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/struts.xml b/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/struts.xml deleted file mode 100644 index b709ec6636..0000000000 --- a/group20/592146505/592146505Learning/src/org/wsc/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/group20/592146505/592146505Learning/src/org/wsc/coding/basic/stack/Stack.java b/group20/592146505/592146505Learning/src/org/wsc/coding/basic/stack/Stack.java deleted file mode 100644 index 09f83c98b6..0000000000 --- a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/stack/Stack.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.wsc.coding.basic.stack; - -import org.wsc.coding.basic.list.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/group20/592146505/592146505Learning/src/org/wsc/coderising/download/DownloadThread.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/DownloadThread.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/DownloadThread.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/DownloadThread.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/FileDownloader.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/FileDownloader.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/FileDownloader.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/FileDownloader.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/FileDownloaderTest.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/FileDownloaderTest.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/FileDownloaderTest.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/FileDownloaderTest.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/Connection.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/api/Connection.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/Connection.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/api/Connection.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/ConnectionException.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/api/ConnectionException.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/ConnectionException.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/api/ConnectionException.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/ConnectionManager.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/api/ConnectionManager.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/ConnectionManager.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/api/ConnectionManager.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/DownloadListener.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/api/DownloadListener.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/api/DownloadListener.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/api/DownloadListener.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/impl/ConnectionImpl.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/impl/ConnectionImpl.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/impl/ConnectionImpl.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/impl/ConnectionImpl.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/download/impl/ConnectionManagerImpl.java b/group20/592146505/data-structure/src/org/wsc/coderising/download/impl/ConnectionManagerImpl.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/download/impl/ConnectionManagerImpl.java rename to group20/592146505/data-structure/src/org/wsc/coderising/download/impl/ConnectionManagerImpl.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/Action.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/Action.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/Action.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/Action.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/LoginAction.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/LoginAction.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/LoginAction.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/LoginAction.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/Struts.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/Struts.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/Struts.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/Struts.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/StrutsTest.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/StrutsTest.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/StrutsTest.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/StrutsTest.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/View.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/View.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/View.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/View.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/util/DocumentUtil.java b/group20/592146505/data-structure/src/org/wsc/coderising/litestruts/util/DocumentUtil.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coderising/litestruts/util/DocumentUtil.java rename to group20/592146505/data-structure/src/org/wsc/coderising/litestruts/util/DocumentUtil.java diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtil.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..220f88888a --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtil.java @@ -0,0 +1,232 @@ +package org.wsc.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 static void reverseArray(int[] origin) { + // 折半 + for (int i = 0; i < (origin.length >> 1); i++) { + int num = origin[i]; + origin[i] = origin[origin.length - 1 - i]; + origin[origin.length - 1 - i] = num; + } + } + + /** + * 现在有如下的一个数组: 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;// 计数器 + /* + * 利用冒泡,将0元素向后排 {1,3,4,5,0,0,6,6,0,5,4,7,6,7,0,5} + * {1,3,4,5,0,6,6,0,5,4,7,6,7,0,5,0} {1,3,4,5,6,6,0,5,4,7,6,7,0,5,0,0} + * .... + */ + for (int i = 0; i < oldArray.length - count; i++) { + // 索引为i的元素为0,则依次将索引i的元素与i+1的元素对换 + if (oldArray[i] == 0) { + for (int j = i; j < oldArray.length - 1 - count; j++) { + int num = oldArray[j]; + oldArray[j] = oldArray[j + 1]; + oldArray[j + 1] = num; + } + count++;// 计数器+1 + i--;// 防止原索引i+1位置的元素为0, + } + } + // 创建新数组 + int[] newArray = new int[oldArray.length - count]; + System.arraycopy(oldArray, 0, newArray, 0, newArray.length); + return newArray; + } + + /** + * 现在有如下的一个数组: 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[] removeZero2(int[] oldArray) { + int count = 0;// 计数器 + for (int i = 0; i < oldArray.length; i++) { + if (oldArray[i] == 0) + count++;// 计数器+1 + } + // 创建新数组 + int[] newArray = new int[oldArray.length - count]; + for (int i = 0, j = 0; i < oldArray.length; i++) { + if (oldArray[i] != 0) { + newArray[j] = oldArray[i]; + j++; + } + } + 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) { + int[] newArray = new int[array1.length + array2.length]; + int i = 0, j = 0, k = 0; + while (i < array1.length && j < array2.length) { + // <= 都取 array1 + if (array1[i] <= array2[j]) { + // 等于时,将array2下标++ + if (array1[i] == array2[j]) + j++; + newArray[k++] = array1[i++]; + } else + newArray[k++] = array2[j++]; + + } + // 将没有循环完毕的元素插入 + while (i < array1.length) + newArray[k++] = array1[i++]; + while (j < array2.length) + newArray[k++] = array2[j++]; + int[] result = newArray; + // 长度缩短则新建数组 + if (k < newArray.length) { + result = new int[k]; + for (int l = 0; l < result.length; l++) + result[l] = newArray[l]; + } + return result; + } + + /** + * 把一个已经存满数据的数组 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[] {}; + int[] nums = new int[max]; + nums[0] = nums[1] = 1; + int flag; + for (flag = 0; (flag < max - 2 && nums[flag] + nums[flag + 1] < max); flag++) { + nums[flag + 2] = nums[flag] + nums[flag + 1]; + } + // 创建新数组 + int[] newArray = nums; + if (newArray.length != flag + 2) { + newArray = new int[flag + 2]; + for (int i = 0; i < newArray.length; i++) { + newArray[i] = nums[i]; + } + } + return newArray; + } + + /** + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public static int[] getPrimes(int max) { + int[] array = new int[max>>1]; + int flag = 0; + for (int i = 2; i < max; i++) { + int j; + for (j = 2; j <= (i >> 1); j++) { + if (i % j == 0) + break; + + } + //如果大于,则证明j++有运行,已经完整对比 + if(j > i>>1) + array[flag++] = i; + + } + int[] newArray = array; + if(flag < array.length){ + newArray = new int[flag]; + for (int i = 0; i < newArray.length; i++) { + newArray[i] = array[i]; + } + } + return newArray; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public static int[] getPerfectNumbers(int max) { + int[] array = new int[max]; + int flag = 0; + for (int i = 1; i < max; i++) { + int sum = 0; + for (int j = 1; j < i; j++) { + if (i % j == 0) + sum+=j; + } + //如果大于,则证明j++有运行,已经完整对比 + if(sum == i) + array[flag++] = i; + + } + int[] newArray = array; + if(flag < array.length){ + newArray = new int[flag]; + for (int i = 0; i < newArray.length; i++) { + newArray[i] = array[i]; + } + } + return newArray; + } + + /** + * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * + * @param array + * @param s + * @return + */ + public static String join(int[] array, String seperator) { + String str = ""; + for (int i = 0; i < array.length; i++) + str += i != array.length - 1 ? array[i] + seperator : array[i]; + return str; + } +} diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtilTest.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtilTest.java new file mode 100644 index 0000000000..cc2641eb14 --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/array/ArrayUtilTest.java @@ -0,0 +1,98 @@ +package org.wsc.coding.basic.array; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class ArrayUtilTest { + + @Test + public void testReverseArray() { + int[] nums = new int[]{7, 9 , 30, 3, 5}; + ArrayUtil.reverseArray(nums); + assertArrayEquals(nums, new int[]{5, 3 ,30, 9, 7}); + } + + /** + * 删除0 + */ + @Test + public void testRemoveZero() { + int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; + nums = ArrayUtil.removeZero(nums); + assertArrayEquals(nums, new int[]{7, 9 ,30, 3, 5}); + } + + /** + * 删除0 + */ + @Test + public void testRemoveZero2() { + int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; + nums = ArrayUtil.removeZero2(nums); + assertArrayEquals(nums, new int[]{7, 9 ,30, 3, 5}); + } + + /** + * 拼接 + */ + @Test + public void testJoin() { + int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5,0}; + String str = ArrayUtil.join(nums,"-"); + assertEquals(str, "0-7-9-0-0-30-0-3-5-0"); + } + + /** + * 扩容 + */ + @Test + public void testGrow() { + int[] nums = new int[]{0,7, 9 , 0,0,30,0, 3, 5}; + nums = ArrayUtil.grow(nums,3); + assertTrue(nums.length==12); + } + + /** + * 合并 + */ + @Test + public void testMerge() { + int[] nums = new int[]{3, 5, 7,8}; + int[] nums2 = new int[]{4, 5, 6,7,8}; + nums = ArrayUtil.merge(nums,nums2); + assertTrue(nums.length==6); + assertArrayEquals(nums, new int[]{3, 4 ,5, 6, 7,8}); + } + + /** + *斐波那契数列 + */ + @Test + public void testFibonacci() { + int[] nums = ArrayUtil.fibonacci(15); + assertTrue(nums.length==7); + assertArrayEquals(nums, new int[]{1,1,2,3,5,8,13}); + } + + /** + * 素数 + */ + @Test + public void testGetPrimes() { + int[] nums = ArrayUtil.getPrimes(23); + assertTrue(nums.length==8); + assertArrayEquals(nums, new int[]{2,3,5,7,11,13,17,19}); + } + + /** + * 完数 + */ + @Test + public void testGetPerfectNumbers() { + int[] nums = ArrayUtil.getPerfectNumbers(10000); + assertTrue(nums.length==4); + assertArrayEquals(nums, new int[]{6,28,496,8128}); + } + +} diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/exception/NullElementException.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/exception/NullElementException.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/exception/NullElementException.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/exception/NullElementException.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/exception/RepeatingElementException.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/exception/RepeatingElementException.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/exception/RepeatingElementException.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/exception/RepeatingElementException.java diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrame.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..44ae0e3d05 --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrame.java @@ -0,0 +1,139 @@ +package org.wsc.coding.basic.linklist; + +/** + *

LRU算法

+ *

+ * 最近最少使用 + *

+ * + * @author Administrator + * @date 2017年3月28日上午10:56:33 + * @version v1.0 + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + int pageNum; + Node next; + + Node() { + } + + Node(Node prev, int pageNum, Node next) { + super(); + this.prev = prev; + this.pageNum = pageNum; + this.next = next; + } + + } + + private int capacity; + private Node first;// 链表头 + private Node last;// 链表尾 + private int size;// 长度 + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + * + * @param key + * @return + */ + public void access(int pageNum) { + // 首先检查链表中是否已存在改页码 + Node node = find(pageNum); + if (node == null) { + // 满则删除尾部后插入 + if (isFull()) + unlinkLast(); + put(pageNum); + } else { + Node prev = node.prev; + Node next = node.next; + Node oldFirst = first; + if(prev != null){ + first = node; + prev.next = next; + node.prev = null; + node.next = oldFirst; + oldFirst.prev = node; + if(next == null) + last = prev; + else + next.prev = prev; + + } + } + + } + + /** + * 添加至头节点 + * + * @param pageNum + */ + void put(int pageNum) { + Node oldFirst = first; + Node newNode = new Node(null, pageNum, oldFirst); + first = newNode; + if (oldFirst == null) { + last = newNode; + } else { + oldFirst.prev = newNode; + } + size++; + } + + /** + * 删除尾节点 + */ + void unlinkLast() { + Node oldLast = last; + Node prev = oldLast.prev; + if (oldLast != null) { + if (prev == null) + first = null; + else { + prev.next = null; + } + last = prev; + } + size--; + } + + Node find(int pageNum) { + Node node = last; + while (node != null) { + if (node.pageNum == pageNum) + return node; + node = node.prev; + } + return node; + } + + boolean isFull() { + return size == capacity ? true : false; + + } + + 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/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrameTest.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..c496b6c023 --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,29 @@ +package org.wsc.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/group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/ArrayList.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/ArrayList.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/ArrayList.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/list/ArrayList.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/Iterator.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/Iterator.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/Iterator.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/list/Iterator.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/LinkedList.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/LinkedList.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/LinkedList.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/list/LinkedList.java diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/List.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/List.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/List.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/list/List.java diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/list/MyLinkedList.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/MyLinkedList.java new file mode 100644 index 0000000000..3d2b1ff83a --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/MyLinkedList.java @@ -0,0 +1,298 @@ +package org.wsc.coding.basic.list; + +public class MyLinkedList implements List { + private int size; + private Node head; + + private static class Node { + E data; + Node next; + + Node(E data) { + super(); + this.data = data; + } + + Node(E data, Node next) { + super(); + this.data = data; + this.next = next; + } + + } + + public boolean add(E e) { + linkLast(e); + return true; + } + + public boolean add(int index, E e) { + checkPositionIndex(index); + if (index == 0) + linkFirst(e); + else if (index == size) + linkLast(e); + else + linkAfter(e, node(index - 1)); + return false; + } + + /** + * 向头部添加元素 + * + * @param e + */ + private void linkFirst(E e) { + Node oldHead = head; + Node newHead = new Node(e); + head = newHead; + // 将原头节点作为新头节点的下一个节点 + head.next = oldHead; + size++; + } + + /** + * 向尾部添加元素 + * + * @param e + */ + void linkLast(E e) { + Node newNode = new Node(e); + if (head == null) { + head = newNode; + } else { + Node node = head; + while (true) { + if (node.next == null) { + node.next = newNode; + break; + } + node = node.next; + } + } + size++; + } + + /** + * 在指定节点之后插入新节点 + * + * @param e + * @param node + */ + void linkAfter(E e, Node node) { + Node oldNext = head; + node.next = new Node(e, oldNext); + size++; + } + + public E get(int index) { + checkElementIndex(index); + return node(index).data; + } + + /** + * 获取指定索引处元素,调用此方法请确保索引范围正确 + * + * @param index + * @return + */ + Node node(int index) { + Node node = head; + for (int i = 0; i < index; i++) { + node = node.next; + } + return node; + } + + public E remove(int index) { + checkElementIndex(index); + Node node = null; + if(index == 0){ + node = head; + head = node.next; + node.next = null; + }else{ + node = unlinkNext(node(index-1)); + } + return node == null?null:node.data; + } + + /** + * 删除此节点的下一个节点 + * @param node + * @return + */ + Node unlinkNext(Node node){ + Node nextNode = node.next; + node.next = nextNode.next; + nextNode.next = null; + size--; + return nextNode; + } + + public int size() { + return size; + } + + public void addFirst(E e) { + linkFirst(e); + } + + public void addLast(E e) { + linkLast(e); + } + + public Object removeFirst() { + return null; + } + + public Object removeLast() { + return null; + } + + public Iterator iterator() { + return null; + } + + /** + * 现有节点索引范围 + * + * @param index + * @return + */ + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + /** + * 可插入索引范围 + * + * @param index + * @return + */ + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + + private String outOfBoundsMsg(int index) { + return "Index: " + index + ", Size: " + size; + } + + /** + * 现有节点索引范围检查 + * + * @param index + */ + private void checkElementIndex(int index) { + if (!isElementIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + /** + * 可插入索引范围检查 + * + * @param index + */ + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + /** + * 把该链表逆置 例如链表为 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; + } + + @Override + public boolean isEmpty() { + // TODO Auto-generated method stub + return false; + } + + @Override + public Object[] toArray() { + // TODO Auto-generated method stub + return null; + } + + @Override + public T[] toArray(T[] a) { + // TODO Auto-generated method stub + return null; + } + + @Override + public E set(int index, E e) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/Queue.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/list/Queue.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/list/Queue.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/list/Queue.java diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/Stack.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..b72a46008a --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/Stack.java @@ -0,0 +1,76 @@ +package org.wsc.coding.basic.stack; + +import org.wsc.coding.basic.list.ArrayList; + +/** + * 栈 + * + * @author Administrator + * @date 2017年4月7日下午3:06:06 + * @version v1.0 + * + * @param + */ +public class Stack { + private ArrayList elementData = new ArrayList(); + + /** + * 将元素压入栈顶 + * + * @param e + */ + public void push(E e) { + elementData.add(e); + } + + /** + * 弹出栈顶元素 + * + * @return + */ + public E pop() { + return elementData.remove(elementData.size() - 1); + } + + /** + * 观察栈顶元素 + * + * @return + */ + public E peek() { + return elementData.get(elementData.size() - 1); + } + + /** + * 是否为空 + * + * @return + */ + public boolean isEmpty() { + return elementData.isEmpty(); + } + + /** + * 栈深度 + * + * @return + */ + public int size() { + return elementData.size(); + } + + @Override + public String toString() { + StringBuffer str = new StringBuffer(); + str.append("["); + for (int i = 0; i < elementData.size(); i++) { + str.append(elementData.get(i)); + if(i < elementData.size()-1) + str.append(", "); + } + str.append("]"); + return str.toString(); + } + + +} diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtil.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..1ced8606bd --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtil.java @@ -0,0 +1,90 @@ +package org.wsc.coding.basic.stack; + +/** + * @author Administrator + * @date 2017年4月10日下午4:55:34 + * @version v1.0 + * + */ +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()){ + Object top = s.pop(); + reverse(s); + toTop(s,top); + } + + } + private static void toTop(Stack s,Object t){ + if(s.isEmpty()){ + s.push(t); + return; + } + Object top = s.pop(); + toTop(s,t); + s.push(top); + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + //递归 + if (!s.isEmpty()) { + Object ob = s.pop(); + remove(s,o); + if(ob !=o) + s.push(ob); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + Object[] tops = new Object[len]; + getTop(s,len,tops); + return tops; + } + + private static void getTop(Stack s, int len,Object[] tops) { + //递归 + if (!s.isEmpty()&&len>0) { + Object ob = s.pop(); + getTop(s,--len,tops); + tops[tops.length-1-len] = ob; + s.push(ob); + } + } + + /** + * 字符串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++) { + stack.push(chars[i]); + } + + return false; + } + +} diff --git a/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtilTest.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..d4e508ad2f --- /dev/null +++ b/group20/592146505/data-structure/src/org/wsc/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,77 @@ +package org.wsc.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 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/group20/592146505/592146505Learning/src/org/wsc/coding/basic/tree_node/BinaryTreeNode.java b/group20/592146505/data-structure/src/org/wsc/coding/basic/tree_node/BinaryTreeNode.java similarity index 100% rename from group20/592146505/592146505Learning/src/org/wsc/coding/basic/tree_node/BinaryTreeNode.java rename to group20/592146505/data-structure/src/org/wsc/coding/basic/tree_node/BinaryTreeNode.java diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/AccessFlag.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..27b7e219f6 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,42 @@ +package org.wsc.coderising.jvm.clz; + +/** + * + * 访问标志 + * @author Administrator + * @date 2017年4月9日下午2:24:21 + * @version v1.0 + * + */ +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 + * @return + */ + public boolean isPublicClass() { + return (this.flagValue & 0x0001) != 0; + } + + /** + * 是final + * @return + */ + public boolean isFinalClass() { + return (this.flagValue & 0x0010) != 0; + } +} diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassFile.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..8684930f96 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,81 @@ +package org.wsc.coderising.jvm.clz; + +import org.wsc.coderising.jvm.constant.ClassInfo; +import org.wsc.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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassIndex.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..153cacd76d --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,32 @@ +package org.wsc.coderising.jvm.clz; + +/** + * + * 类及父类索引 + * @author Administrator + * @date 2017年4月9日下午2:39:45 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ClassInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..1976fa4d14 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,37 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 类描述符 + * @author Administrator + * @date 2017年4月9日下午2:45:38 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..236e058d7d --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,46 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 描述符 + * @author Administrator + * @date 2017年4月9日下午2:46:19 + * @version v1.0 + * + */ +public abstract class ConstantInfo { + /** UTF-8编码的字符串 */ + 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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantPool.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..69ef091503 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,38 @@ +package org.wsc.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * 常量池 + * @author Administrator + * @date 2017年4月9日下午2:53:16 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/FieldRefInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..b4066363e5 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,67 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 字段描述符 + * @author Administrator + * @date 2017年4月9日下午2:53:27 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/MethodRefInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..f7e298cac1 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,65 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 类中方法描述符 + * @author Administrator + * @date 2017年4月9日下午2:53:39 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NameAndTypeInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..24cde05109 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,57 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 字段或方法部分描述符 + * @author Administrator + * @date 2017年4月9日下午2:53:59 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NullConstantInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..0772bc0eb6 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,22 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 空描述符 + * @author Administrator + * @date 2017年4月9日下午2:54:21 + * @version v1.0 + * + */ +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo() { + + } + + @Override + public int getType() { + return -1; + } + +} diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/StringInfo.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..69f36a300f --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,35 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * 字符串描述符 + * @author Administrator + * @date 2017年4月9日下午2:54:31 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/UTF8Info.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..b2ae869de8 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,45 @@ +package org.wsc.coderising.jvm.constant; + +/** + * + * utf-8编码的字符串 + * @author Administrator + * @date 2017年4月9日下午2:54:41 + * @version v1.0 + * + */ +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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ByteCodeIterator.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..431ea1b891 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,59 @@ +package org.wsc.coderising.jvm.loader; + +import java.util.ConcurrentModificationException; + +import org.wsc.coderising.jvm.util.Util; + +/** + * + * 字节迭代器 + * @author Administrator + * @date 2017年4月12日下午1:16:39 + * @version v1.0 + * + */ +public class ByteCodeIterator{ + + private byte[] codes; + + private int cursor=0; + + ByteCodeIterator(byte[] byteCodes) { + super(); + this.codes = byteCodes; + } + + public boolean hasNext() { + return cursor != codes.length; + } + + public byte next() { + if(cursor > codes.length) + throw new ConcurrentModificationException(); + return codes[cursor++]; + } + + public byte[] getBytes(int count) { + byte[] bytes = new byte[count]; + for (int i = 0; i < count; i++) { + bytes[i] = next(); + } + return bytes; + } + + public int nextU1ToInt(){ + return Util.byteToInt(getBytes(1)); + } + + public int nextU2ToInt(){ + return Util.byteToInt(getBytes(2)); + } + + public int nextU4ToInt(){ + return Util.byteToInt(getBytes(4)); + } + + public String nextU4ToHexString(){ + return Util.byteToHexString(getBytes(4)); + } +} diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileLoader.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..ed5bfb4149 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,89 @@ +package org.wsc.coderising.jvm.loader; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.wsc.coderising.jvm.clz.ClassFile; + +public class ClassFileLoader { + + private List clzPaths = new ArrayList(); + /** 默认缓冲大小 */ + private final static int DEFAULT_SIZE = 32; + DataInputStream dis; + private ByteArrayOutputStream baos; + + public byte[] readBinaryCode(String className) throws ClassNotFoundException { + byte[] buffer = null; + File file = null; + for (String clzPath : clzPaths) { + clzPath += "/" + className.replace(".", "/") + ".class"; + file = new File(clzPath); + if (file.exists()) + try { + buffer = getFileToByte(new File(clzPath)); + if(buffer != null && buffer.length > 0) + break; + } catch (IOException e) { + throw new ClassNotFoundException(); + } + close(); + } + + if (buffer == null || buffer.length == 0) + throw new ClassNotFoundException(); + return buffer; + + } + + public void addClassPath(String path) { + clzPaths.add(path); + } + + public String getClassPath() { + StringBuffer clzPath = new StringBuffer(); + for (int i = 0; i < clzPaths.size(); i++) { + clzPath.append(clzPaths.get(i)); + if (i < clzPaths.size() - 1) + clzPath.append(";"); + } + return clzPath.toString(); + } + + private byte[] getFileToByte(File file) throws IOException { + byte[] buffer = new byte[DEFAULT_SIZE]; + dis = new DataInputStream(new FileInputStream(file)); + baos = new ByteArrayOutputStream(); + int lenth; + // 读取 + while ((lenth = dis.read(buffer)) != -1) { + baos.write(buffer, 0, lenth); + } + return baos.toByteArray(); + } + + public ClassFile loadClass(String className) throws ClassNotFoundException { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + } + + private void close() { + try { + if (dis != null) { + dis.close(); + } + if (baos != null) { + baos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileParser.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..13a99b1a63 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,107 @@ +package org.wsc.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import org.wsc.coderising.jvm.clz.AccessFlag; +import org.wsc.coderising.jvm.clz.ClassFile; +import org.wsc.coderising.jvm.clz.ClassIndex; +import org.wsc.coderising.jvm.constant.ClassInfo; +import org.wsc.coderising.jvm.constant.ConstantPool; +import org.wsc.coderising.jvm.constant.FieldRefInfo; +import org.wsc.coderising.jvm.constant.MethodRefInfo; +import org.wsc.coderising.jvm.constant.NameAndTypeInfo; +import org.wsc.coderising.jvm.constant.NullConstantInfo; +import org.wsc.coderising.jvm.constant.StringInfo; +import org.wsc.coderising.jvm.constant.UTF8Info; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magicNumber = iter.nextU4ToHexString(); + if (!"cafebabe".equals(magicNumber)) + return null; + classFile.setMinorVersion(iter.nextU2ToInt());// 次版本 + classFile.setMajorVersion(iter.nextU2ToInt());// 主版本 + //解析常量池 + ConstantPool pool = parseConstantPool(iter); + classFile.setConstPool(pool); + //访问标识 + classFile.setAccessFlag(parseAccessFlag(iter)); + //类及其父类 + classFile.setClassIndex(parseClassIndex(iter)); + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.nextU2ToInt()); + } + + private ClassIndex parseClassIndex(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(); + System.out.println("constant pool count:" + constantPoolCount); + // 常量池 + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo());// 常量池索引从1开始 + for (int i = 1; i < constantPoolCount; i++) { + int tag = iter.nextU1ToInt(); + switch (tag) { + case 1://UTF-8 String + int length = iter.nextU2ToInt(); + String utf8Str = null; + try { + utf8Str = new String(iter.getBytes(length),"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setValue(utf8Str); + utf8Info.setLength(length); + pool.addConstantInfo(utf8Info); + break; + case 7://类或接口的符号引用 + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.nextU2ToInt()); + pool.addConstantInfo(classInfo); + break; + case 8://字符串类型字面量 + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.nextU2ToInt()); + pool.addConstantInfo(stringInfo); + break; + case 9://字段的符号引用 + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(fieldRefInfo); + break; + case 10://类中方法的符号引用 + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.nextU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2ToInt()); + pool.addConstantInfo(methodRefInfo); + break; + case 12://字段或方法的部门符号引用 + NameAndTypeInfo nameAndType = new NameAndTypeInfo(pool); + nameAndType.setIndex1(iter.nextU2ToInt()); + nameAndType.setIndex2(iter.nextU2ToInt()); + pool.addConstantInfo(nameAndType); + break; + default: + throw new RuntimeException("the constant pool tag:" + tag + " is not implements"); + } + } + return pool; + } + +} diff --git a/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/ClassFileloaderTest.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..a326f7f467 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,194 @@ +package org.wsc.coderising.jvm.test; + +import java.io.IOException; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.wsc.coderising.jvm.clz.ClassFile; +import org.wsc.coderising.jvm.clz.ClassIndex; +import org.wsc.coderising.jvm.constant.ClassInfo; +import org.wsc.coderising.jvm.constant.ConstantPool; +import org.wsc.coderising.jvm.constant.MethodRefInfo; +import org.wsc.coderising.jvm.constant.NameAndTypeInfo; +import org.wsc.coderising.jvm.constant.UTF8Info; +import org.wsc.coderising.jvm.loader.ClassFileLoader; + +public class ClassFileloaderTest { +private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "e:/desktop"; + static String path2 = "./bin"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + + try { + clzFile = loader.loadClass(className); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + 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() throws ClassNotFoundException, IOException { + + 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() throws ClassNotFoundException, IOException { + 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 < 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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/EmployeeV1.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..13f562506b --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/test/EmployeeV1.java @@ -0,0 +1,30 @@ +package org.wsc.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/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/util/Util.java b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..f39e6be4b5 --- /dev/null +++ b/group20/592146505/mini-jvm/src/org/wsc/coderising/jvm/util/Util.java @@ -0,0 +1,22 @@ +package org.wsc.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 < 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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/LoginAction.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/LoginAction.java" new file mode 100644 index 0000000000..40b5de161a --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/LoginAction.java" @@ -0,0 +1,34 @@ +package com.coderising.litestruts; + +public class LoginAction { + + private String name; + private String passWord; + private String message; + 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 message; + } + public void setMessage(String message) { + this.message = 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"; + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/ReadXml.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/ReadXml.java" new file mode 100644 index 0000000000..e971e779b6 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/ReadXml.java" @@ -0,0 +1,71 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; + +public class ReadXml { + + private Document document = null; + private HashMap hashMap; + + public ReadXml(String filename) { + try { + document = new SAXReader().read((filename)); + hashMap = new HashMap(); + } catch (DocumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public String parseXml(String actionName) { + + // List actions = document.selectNodes("//struts/action"); + String className = null; + Element root = document.getRootElement(); + List actions = root.elements("action"); + if (actions.isEmpty()) { + return null; + } + for (Iterator iter = actions.iterator(); iter.hasNext();) { + Element element = (Element) iter.next(); + Attribute attr1 = element.attribute("name"); + if (attr1.getValue().equals(actionName)) { + Attribute attr2 = element.attribute("class"); + className = attr2.getValue(); + //ȡԪصĵֵ + for (Iterator iterator = element.elementIterator(); iterator + .hasNext();) { + Element childElement = (Element) iterator.next(); + Attribute childAttribute = childElement.attribute("name"); + hashMap.put(childAttribute.getValue(), + childElement.getText()); + } + } + + } + return className; + } + + public String getJsp(String result) { + if (result == null) { + return null; + } + String string_jsp = null; + if (!hashMap.isEmpty()) { + for (String string : hashMap.keySet()) { + if (result.equals(string)) { + string_jsp = hashMap.get(string); + } + } + } + return string_jsp; + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutTEST.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutTEST.java" new file mode 100644 index 0000000000..7921041560 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutTEST.java" @@ -0,0 +1,37 @@ +package com.coderising.litestruts; + +import java.util.HashMap; + +import org.junit.Assert; +import org.junit.Test; + +public class StrutTEST { + + @Test + public void runActionSuccess() { + String action = "login"; + + HashMap hashMap = new HashMap(); + hashMap.put("name", "test"); + hashMap.put("password", "1234"); + + View view = Struts.runAction(action, hashMap); + Assert.assertEquals("login successful", view.getParameters().get("message")); + Assert.assertEquals("/jsp/homepage.jsp", view.getJsp()); + } + + @Test + public void runActionFail(){ +String action = "login"; + + HashMap hashMap = new HashMap(); + hashMap.put("name", "test"); + hashMap.put("password", "12345"); + + View view = Struts.runAction(action, hashMap); + Assert.assertEquals("login failed,please check your user/pwd", view.getParameters().get("message")); + Assert.assertEquals("/jsp/showLogin.jsp", view.getJsp()); + + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/Struts.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/Struts.java" new file mode 100644 index 0000000000..2892617845 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/Struts.java" @@ -0,0 +1,93 @@ +package com.coderising.litestruts; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class Struts { + + private static final String NAME = "name"; + private static final String PASSWORD = "password"; + private static String excuteString; + private static Object object = null;// طʵ + private static Class actionClass = null;// ȡ + + @SuppressWarnings("unchecked") + public static View runAction(String actionName, + Map parameters) { + // ȡļstruts.xml + View view = new View(); + ReadXml readXml = new ReadXml("E:\\struts.xml"); + String classNameString = readXml.parseXml(actionName);//ȡxml + object = initAction(classNameString);//ͨʼ + + excuteMethod(parameters);//ִsetterexcute + + view.setParameterMap(setMapParameter());//ȡеgetterִк󽫷ͽ浽view + String jspResult = readXml.getJsp(excuteString);//ȡjsp + view.setJsp(jspResult); + + return view; + } + + public static Object initAction(String classNameString) { + System.out.println(classNameString); + try { + actionClass = Class.forName(classNameString); + } catch (ClassNotFoundException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + Object newObject = null; + try { + newObject = actionClass.newInstance(); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return newObject; + } + + public static void excuteMethod(Map parameters) { + + try { + Method methodOfName = actionClass + .getMethod("setName", String.class); + methodOfName.invoke(object, parameters.get(NAME)); + // + Method methodOfPassword = actionClass.getMethod("setPassWord", + String.class); + methodOfPassword.invoke(object, parameters.get(PASSWORD)); + + Method excuteMethod = actionClass.getMethod("execute"); + excuteString = (String) excuteMethod.invoke(object); + + } catch (Exception e) { + // TODO: handle exception + } + } + + public static Map setMapParameter() { + + Method[] getterMethods = actionClass.getMethods(); + HashMap hashMap = new HashMap<>(); + + for (int i = 0; i < getterMethods.length; i++) { + String getterName = getterMethods[i].getName(); + if (getterName.startsWith("get")) { + try { + String value = (String) getterMethods[i].invoke(object); + hashMap.put(getterName.substring(3).toLowerCase(), value); + //System.out.println("----" + getterName.substring(2)); + } catch (Exception e) { + // TODO: handle exception + } + + } + } + return hashMap; + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutsTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutsTest.java" new file mode 100644 index 0000000000..b7f0884f41 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/StrutsTest.java" @@ -0,0 +1,40 @@ +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"); //ԤIJһ + + 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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/View.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/View.java" new file mode 100644 index 0000000000..bda8419e5f --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/View.java" @@ -0,0 +1,28 @@ +package com.coderising.litestruts; + +import java.util.Map; + +public class View { + + private String jsp; + private Map parameter; + + public String getJsp() { + return jsp; + } + + public View setJsp(String jsp) { + this.jsp = jsp; + return this; + } + + public Map getParameters() { + return parameter; + } + + public View setParameterMap(Map parameter) { + this.parameter = parameter; + return this; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/xmlTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/xmlTest.java" new file mode 100644 index 0000000000..cd5edf1143 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/coderising/litestruts/xmlTest.java" @@ -0,0 +1,24 @@ +package com.coderising.litestruts; + +import java.util.HashMap; +import java.util.Map; + +public class xmlTest { + + /** + * @param args + */ + public static void main(String[] args) { + // TODO Auto-generated method stub + String actionName = "login"; + + Map params = new HashMap(); + params.put("name","test"); + params.put("password","1234"); + + View view = Struts.runAction(actionName,params); + String str = view.getJsp(); + System.out.println(str); + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/LinkedListTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/LinkedListTest.java" new file mode 100644 index 0000000000..4a800335e5 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/LinkedListTest.java" @@ -0,0 +1,46 @@ +package com.ralf.linkedlist; + +import BasicData.MyIterator; + +public class LinkedListTest { + + /** + * @param args + */ + @SuppressWarnings("unchecked") + public static void main(String[] args) { + // TODO Auto-generated method stub + MyLinkedList list = new MyLinkedList<>(); + + MyLinkedList listB = new MyLinkedList<>(); + MyLinkedList listC = new MyLinkedList<>(); + list.add(11); + list.add(12); + list.add(13); + list.add(14); + list.add(15); + list.add(17); + list.add(18); + + listB.add(10); + listB.add(12); + listB.add(14); + listB.add(15); + listB.add(18); + + + listC = (MyLinkedList) list.intersection(listB); + + + System.out.println(listC.size()); + + MyIterator iterator = listC.iterator(); + while(iterator.hasNext()){ + Integer integer = iterator.Next(); + System.out.println(integer); + } + + + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/MyLinkedList.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/MyLinkedList.java" new file mode 100644 index 0000000000..7ae0787ed0 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/linkedlist/MyLinkedList.java" @@ -0,0 +1,528 @@ +package com.ralf.linkedlist; + +import java.util.Arrays; +import java.util.Objects; +import java.util.TreeSet; + +import BasicData.MyArrayList; +import BasicData.MyIterator; +import BasicData.MyList; + +public class MyLinkedList> implements MyList { + + private Node head;// ָͷʼΪ + // private Node tail;// ָβĽڵ + private int size; + + public MyLinkedList() { + this.head = new Node(null); + this.size = 0; + } + + private static class Node { + Node next = null; + T item = null; + + public Node(T t) { + item = t; + } + + } + + @Override + public boolean add(T t) { + // TODO Auto-generated method stub + return addLast(t); + } + + @Override + public void add(int index, T t) { + // TODO Auto-generated method stub + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(); + } + Node newNode = new Node(t); + if (index == 0) { + Node oldNode = head.next; + head.next = newNode; + newNode.next = oldNode; + size++; + } + + else { + Node current = getNode(index - 1); + newNode.next = current.next; + current.next = newNode; + size++; + } + + } + + @Override + public int size() { + // TODO Auto-generated method stub + return size; + } + + @Override + public T remove(int index) { + // TODO Auto-generated method stub + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(); + } else if (index == 0) { + return removeFirst(); + } else if (index == size - 1) { + return removeLast(); + } else { + Node current = getNode(index - 1); + T data = current.next.item; + current.next.item = null; + current.next = current.next.next; + size--; + return data; + } + } + + @Override + public T set(int index, T t) { + // TODO Auto-generated method stub + Node current = getNode(index); + T data = current.item; + current.item = t; + return data; + } + + @Override + public T get(int index) { + // TODO Auto-generated method stub + T data = getNode(index).item; + return data; + } + + public int indexOf(T t) { + Node current = this.head; + int index = 0; + while (current.next != null) { + current = current.next; + if (Objects.equals(current.item, t)) { + return index; + } + index++; + } + return -1; + } + + private Node getNode(int index) { + + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(); + } + Node current = this.head; + int m_size = 0; + while (current.next != null && m_size <= index) { + current = current.next; + m_size++; + } + return current; + } + + public boolean addFirst(T t) { + + if (head.next == null) { + Node current = new Node(t); + head.next = current; + current = null; + size++; + return true; + } else { + Node current = new Node(t); + current.next = head.next; + head.next = current; + size++; + return true; + } + } + + public boolean addLast(T t) { + + if (head.next == null) { + Node current = new Node(t); + head.next = current; + current.next = null; + size++; + return true; + } else { + Node current = new Node(t); + Node oldNode = getNode(size - 1); + oldNode.next = current; + current.next = null; + size++; + return true; + } + + } + + public T removeFirst() { + if (head.next == null) { + return null; + } else if (head.next.next == null) { + T data = head.next.item; + head.next.item = null; + head = null; + size--; + return data; + } else { + T data = head.next.item; + Node current = head.next.next; + head.next.item = null; + head.next = current; + size--; + return data; + } + } + + public T removeLast() { + if (head.next == null) { + return null; + } else if (head.next.next == null) { + T data = head.next.item; + head.next.item = null; + size--; + return data; + } else { + Node current = getNode(size - 2); + T data = current.next.item; + current.next.item = null; + current.next = null; + size--; + return data; + } + } + + public boolean isContain(T t){ + + if (head.next == null) { + return false; + } + Node current = head; + while(current.next != null){ + current = current.next; + if (Objects.equals(t, current.item)) { + return true; + } + } + return false; + } + + /** + * Ѹ Ϊ 3->7->10 , úΪ 10->7->3 + */ + public void reverse() { + this.head.next = reverseList(head.next); + } + + private Node reverseList(Node mhead) { + + if (mhead == null || mhead.next == null) { + return mhead; + } + Node reHead = reverseList(mhead.next); + mhead.next.next = mhead; + mhead.next = null; + return reHead; + } + + /** + * ɾһĺ벿 磺list = 2->5->7->8 , ɾԺֵΪ 2->5 list = 2->5->7->8->10 + * ,ɾԺֵΪ2,5,7 + */ + public void removeLastHalf() { + + if (size < 2) { + return; + } + int index = (size - 1) / 2 + 1; + Node current = getNode(index - 1); + Node temp = current; + while (index < size) { + temp = temp.next; + temp.item = null; + index++; + } + size = (size - 1) / 2 + 1; + current.next = null; + } + + /** + * ɾһǰ벿 磺list = 2->5->7->8 , ɾԺֵΪ 7->8 list = 2->5->7->8->10 + * ,ɾԺֵΪ7,8,10 + */ + public void removeFirstHalf() { + + if (size < 2) { + return; + } + int maxIndex = size/ 2; + int index = 0; + Node current = head; + while (index < maxIndex) { + current = current.next; + current.item = null; + index++; + size--; + } + //size = (size - 1) / 2 + 1; + head.next = current.next; + } + + /** + * ӵiԪؿʼ ɾlength Ԫ עi0ʼ + * + * @param i + * @param length + */ + public void remove(int i, int length) { + + if (i < 0 || i >= size || (i + length - 1) > size) { + throw new IndexOutOfBoundsException(); + } + int index = 0; + Node current; + if (i == 0) { + current = head; + } else { + current = getNode(i - 1); + } + Node temp = current; + while (index < length) { + current = current.next; + current.item = null; + index++; + } + if (current.next == null) { + if (i == 0) { + head.next = null; + } else { + temp.next = null; + } + } else { + if (i == 0) { + head.next = current.next; + } else { + temp.next = current.next; + } + } + size = size - length; + + } + + /** + * ٶǰlistе ӵǰȡЩlistָԪ 統ǰ = + * 11->101->201->301->401->501->601->701 listB = 1->3->4->6 + * صĽӦ[101,301,401,601] + * + * @param list + */ + @SuppressWarnings("unchecked") + public int[] getElements(MyLinkedList list) { + int[] elements = new int[list.size]; + int i = 0; + MyIterator iterator = (MyIterator) list.iterator(); + while (iterator.hasNext()) { + int index = iterator.Next(); + if (index < this.size) { + Node current = getNode(index); + elements[i++] = (Integer) current.item; + } else { + elements[i++] = 0;// ûиԪʱֵΪ㣬intͣʱΪnull + } + } + return Arrays.copyOf(elements, i); + } + + /** + * ֪еԪֵУԵ洢ṹ ӵǰɾlistгֵԪ + * + * @param list + */ + + public void subtract(MyLinkedList list) { + + if (list.size == 0) { + return; + } + MyIterator iterator = list.iterator(); + + while (iterator.hasNext()) { + T element = iterator.Next(); + int index = indexOf(element);// ǰ + if (index != -1) { + remove(index); + } + } + } + + /** + * ɾֵͬĶԪأʹòԱԪصֵͬ + */ + public void removeRepeatValues() { + if (head.next == null || head.next.next == null) { + return; + } + // ԼMyArrayList + MyArrayList list = new MyArrayList<>(); + // + Node current = head; + T obj = null; + while (current.next != null) { + current = current.next; + obj = current.item; + if (list.isContain(obj)) { + // int index = indexOf(obj); + remove(indexOf(obj)); // remove(T t) + + } else { + list.add(obj); + } + } + } + + /** + * ֪ǰеԪֵУԵ洢ṹ ɾֵͬĶԪأʹòԱԪصֵͬ + */ + public void removeDuplicateValues() { + + if (head.next == null || head.next.next == null) { + return; + } + Node current = head; + T obj = null; + while (current.next != null) { + current = current.next; + obj = current.item; + if (current.next != null && Objects.equals(obj, current.next.item)) { + // int index = indexOf(obj); + remove(indexOf(obj)); // remove(T t) + } + } + } + + /** + * ֪еԪֵУԵ洢ṹ дһЧ㷨ɾֵminСmaxԪأдԪأ + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + + if (head.next == null) { + return; + } + Node current = head; + Integer integer;// ĿǰֻȽ͵ģӦͣҪʵComparableӿ + while (current.next != null) { + current = current.next; + integer = (Integer) current.item; + if (integer.intValue() > min && integer.intValue() < max) { + remove(indexOf(current.item)); + } + } + } + + /** + * 赱ǰͲlistָԪֵУͬһеԪֵͬ + * ҪCԪΪǰlistԪصĽұCеԪֵ + * + * @param list + */ + public MyLinkedList intersection(MyLinkedList list) { + + if (list.size == 0 || head.next == null) { + return null; + } + MyLinkedList newLinked = new MyLinkedList(); + MyIterator iterator = list.iterator(); + //MyArrayList arrayList = new MyArrayList<>();//û + //ArrayList arrayList = new ArrayList<>(); + TreeSet treeSet = new TreeSet<>(); + + while (iterator.hasNext()) { + T element = iterator.Next(); + if (isContain(element)) { + treeSet.add(element); + } + } + + for(T t : treeSet){ + newLinked.add(t); + } + return newLinked; + + } + /* + @SuppressWarnings("unchecked") + public MyLinkedList union(MyLinkedList list) { + + if (head.next == null) { + + if (list.size == 0) { + return null; + } else { + return list; + } + } else { + if (list.size == 0) { + return this; + } else { + + MyLinkedList newList = new MyLinkedList(); + TreeSet treeSet = new TreeSet<>();// MyArrayListװвͬԪأӵlinkedlist + + Node current = head; + while (current.next != null) { + current = current.next; + treeSet.add(current.item); + } + MyIterator iterator = (MyIterator) list.iterator(); + while (iterator.hasNext()) { + treeSet.add(iterator.Next()); + } + for (T t : treeSet) { + newList.add(t); + } + return newList; + } + } + + } + + */ + public MyIterator iterator() { + + return new LinkedListIterator(); + } + + private class LinkedListIterator implements MyIterator { + + private int current = 0; + T data = null; + + @Override + public boolean hasNext() { + // TODO Auto-generated method stub + return (current < size); + } + + @Override + public T Next() { + // TODO Auto-generated method stub + if (hasNext()) { + data = getNode(current).item; + current++; + return data; + } + return null; + } + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrame.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrame.java" new file mode 100644 index 0000000000..47fdbbe85c --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrame.java" @@ -0,0 +1,122 @@ +package com.ralf.lru; + +/** + * ˫ʵLRU㷨 + * @author Ralf + * + */ +public class LRUPageFrame { + + private static class Node { + private Node prev; + private Node next; + int pageNum; + + public Node(int pageNum) { + this.pageNum = pageNum; + } + } + + private int capacity; + private Node head; + private Node tail; + private int size; + + private void addFirst(int PageNum) { + Node node = new Node(PageNum); + if (head == null) { + node.next = null; + node.prev = null; + head = node; + tail = node; + this.size++; + } else { + node.next = head; + node.prev = null; + head.prev = node; + head = node; + this.size++; + } + } + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + this.head = null; + this.tail = null; + } + + /** + * ȡ + * @param PageNum + */ + public void access(int PageNum) { + + Node node = getNode(PageNum); + if (node == null) { + if (size < capacity) { + addFirst(PageNum); + } else { + removeLast(); + addFirst(PageNum); + } + } else if (this.head.pageNum == PageNum) { + return; + } + else { + moveToHead(node); + } + } + + private void moveToHead(Node node) { + Node current = node; + if (node.pageNum == this.tail.pageNum) { + node.prev.next = null; + tail = node.prev; + + } else { + node.prev.next = node.next; + node.next.prev = node.prev; + } + current.next = head; + current.prev = null; + this.head = current; + + } + + private void removeLast() { + + Node preNode = tail.prev; + tail.prev.next = null; + tail.prev = null; + tail = preNode; + this.size--; + } + + private Node getNode(int PageNum) { + Node current = this.head; + while (current != null) { + if (current.pageNum == PageNum) { + return current; + } + current = current.next; + } + return null; + } + + public String toString() { + if (this.head == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + Node current = this.head; + while (current != null) { + stringBuilder.append(current.pageNum); + if (current.next != null) { + stringBuilder.append(","); + } + current = current.next; + + } + return stringBuilder.toString(); + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrameTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrameTest.java" new file mode 100644 index 0000000000..b024277905 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/lru/LRUPageFrameTest.java" @@ -0,0 +1,37 @@ +package com.ralf.lru; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LRUPageFrameTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + + 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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" new file mode 100644 index 0000000000..63c81812e3 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" @@ -0,0 +1,44 @@ +package com.ralf.stack; + +import java.util.LinkedList; +import java.util.NoSuchElementException; + +/** + * ʵֻݽṹջ + * + * @author Ralf + * + */ +public class MyStack { + + private LinkedList linkedList; + + public MyStack() { + if (null == linkedList) { + linkedList = new LinkedList(); + } + } + + 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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" new file mode 100644 index 0000000000..e2757af444 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" @@ -0,0 +1,159 @@ +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]); + } + + } + + /** + * ɾջе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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" new file mode 100644 index 0000000000..3782d490c4 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" @@ -0,0 +1,87 @@ +package com.ralf.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class StackUtilsTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testReverse() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.reverse(stack); + Assert.assertEquals(5, stack.size()); + + Assert.assertEquals(1, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(3, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(5, stack.pop().intValue()); + } + + @Test + public void testRemove() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.remove(stack, 3); + + Assert.assertEquals(4, stack.size()); + + Assert.assertEquals(5, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(1, stack.pop().intValue()); + } + + public void testGetTop() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + Integer[] integerReal = StackUtil.getTop(stack, 3); + int[] intExpeted = { 1, 2, 3 }; + int[] intReal = new int[integerReal.length]; + for (int i = 0; i < integerReal.length; i++) { + intReal[i] = integerReal[i]; + } + Assert.assertEquals(5, stack.size()); + Assert.assertArrayEquals(intExpeted, intReal); + + } + + @Test + public void testIsValidPair(){ + + String stringTrue = "([e{d}f])"; + String stringFalse = "([b{x]y})"; + + Assert.assertTrue(StackUtil.isValidPairs(stringTrue)); + Assert.assertFalse(StackUtil.isValidPairs(stringFalse)); + + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/AccessFlag.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/AccessFlag.java" new file mode 100644 index 0000000000..b1d40c20ff --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/AccessFlag.java" @@ -0,0 +1,22 @@ +package com.coderising.jvm.clasfile; + +public class AccessFlag { + + private int flag; + + public int getFlag() { + return flag; + } + + public void setFlag(int flag) { + this.flag = flag; + } + + public boolean isPublic(){ + return (this.flag & 0x0001) != 0; + } + + public boolean isFinalClass(){ + return (this.flag & 0x0010) != 0; + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassFile.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassFile.java" new file mode 100644 index 0000000000..01e63c1328 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassFile.java" @@ -0,0 +1,67 @@ +package com.coderising.jvm.clasfile; + +import com.coderising.jvm.constant.ConstantPool; + +public class ClassFile { + + private int MinorVersion; + private int MajorVersion; + private String MagicNumer; + private ConstantPool pool; + private ClassIndex classIndex; + private AccessFlag accessFlag; + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public String getMagicNumer() { + return MagicNumer; + } + + public void setMagicNumer(String magicNumer) { + this.MagicNumer = magicNumer; + } + + public int getMinorVersion() { + return MinorVersion; + } + + public int getMajorVersion() { + return MajorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.MinorVersion = minorVersion; + } + + public void setMajorVersion(int majorVersion) { + this.MajorVersion = majorVersion; + } + + public ConstantPool getConstantPool() { + + return this.pool; + } + + public ClassIndex getClassIndex() { + return classIndex; + } + + public void setClassIndex(ClassIndex classIndex) { + this.classIndex = classIndex; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassIndex.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassIndex.java" new file mode 100644 index 0000000000..c98eae755f --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/clasfile/ClassIndex.java" @@ -0,0 +1,21 @@ +package com.coderising.jvm.clasfile; + +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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ClassInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ClassInfo.java" new file mode 100644 index 0000000000..4f9077cbb6 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ClassInfo.java" @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo{ + + private int type = ConstantInfo.CLASS_INFO; + private int Utf8Index; + + public ClassInfo(ConstantPool constantPool){ + super(constantPool); + } + public int getUtf8Index() { + return Utf8Index; + } + + public void setUtf8Index(int utf8Index) { + Utf8Index = utf8Index; + } + + public String getClassName(){ + Utf8Info utf8Info = (Utf8Info) this.constantPool.getConstantInfo(Utf8Index); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return this.type; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantInfo.java" new file mode 100644 index 0000000000..bc2acc7c6e --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantInfo.java" @@ -0,0 +1,26 @@ +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 constantPool){ + this.constantPool = constantPool; + } + + public ConstantPool getConstantPool(){ + return this.constantPool; + } + public abstract int getType(); + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantPool.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantPool.java" new file mode 100644 index 0000000000..283e93d95a --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/ConstantPool.java" @@ -0,0 +1,22 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + public int getConstantNumber() { + return this.constantInfos.size() - 1; + } + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public Object getConstantInfo(int index) { + + return this.constantInfos.get(index); + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/FieldRefInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/FieldRefInfo.java" new file mode 100644 index 0000000000..22a7b5c5f7 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/FieldRefInfo.java" @@ -0,0 +1,63 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo { + + private int tag = ConstantInfo.FIELD_INFO; + private int Index_ClassInfo; + private int Index_NameAndType; + + public FieldRefInfo(ConstantPool constantPool) { + super(constantPool); + } + + public int getIndex_ClassInfo() { + return Index_ClassInfo; + } + + public void setIndex_ClassInfo(int index_ClassInfo) { + Index_ClassInfo = index_ClassInfo; + } + + public int getIndex_NameAndType() { + return Index_NameAndType; + } + + public void setIndex_NameAndType(int index_NameAndType) { + Index_NameAndType = index_NameAndType; + } + + public String getClassName() { + + ConstantPool pool = this.getConstantPool(); + + ClassInfo classInfo = (ClassInfo) pool + .getConstantInfo(getIndex_ClassInfo()); + return classInfo.getClassName(); + } + + public String getParameterAndTypeString() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getDescribeInfo(); + } + + public String getMethodName() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getNameInfo(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/MethodInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/MethodInfo.java" new file mode 100644 index 0000000000..81cd6c3347 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/MethodInfo.java" @@ -0,0 +1,63 @@ +package com.coderising.jvm.constant; + +public class MethodInfo extends ConstantInfo { + + private int tag = ConstantInfo.METHOD_INFO; + private int Index_ClassInfo; + private int Index_NameAndType; + + public MethodInfo(ConstantPool constantPool) { + super(constantPool); + } + + public int getIndex_ClassInfo() { + return Index_ClassInfo; + } + + public void setIndex_ClassInfo(int index_ClassInfo) { + Index_ClassInfo = index_ClassInfo; + } + + public int getIndex_NameAndType() { + return Index_NameAndType; + } + + public void setIndex_NameAndType(int index_NameAndType) { + Index_NameAndType = index_NameAndType; + } + + public String getClassName() { + + ConstantPool pool = this.getConstantPool(); + + ClassInfo classInfo = (ClassInfo) pool + .getConstantInfo(getIndex_ClassInfo()); + return classInfo.getClassName(); + } + + public String getParameterAndTypeString() { + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getDescribeInfo(); + + } + + public String getMethodName() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getNameInfo(); + } + + @Override + public int getType() { + return this.tag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" new file mode 100644 index 0000000000..c8731e9216 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" @@ -0,0 +1,46 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo { + + private int tag = ConstantInfo.NAME_AND_TYPE_INFO; + private int Index_Name; + private int Index_Describe; + + public NameAndTypeInfo(ConstantPool constantPool){ + super(constantPool); + } + public int getIndex_Name() { + return Index_Name; + } + + public void setIndex_Name(int index_Name) { + Index_Name = index_Name; + } + + public int getIndex_Describe() { + return Index_Describe; + } + + public void setIndex_Describe(int index_Describe) { + Index_Describe = index_Describe; + } + + public String getNameInfo(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(Index_Name); + return utf8Info.getValue(); + } + public String getDescribeInfo(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(Index_Describe); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NullConstantInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NullConstantInfo.java" new file mode 100644 index 0000000000..3428c1ea65 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/NullConstantInfo.java" @@ -0,0 +1,11 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){} + @Override + public int getType() { + return -1; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/StringInfo.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/StringInfo.java" new file mode 100644 index 0000000000..83339240f5 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/StringInfo.java" @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo { + + private int tag = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool constantPool){ + super(constantPool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getStringName(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(getIndex()); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/Utf8Info.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/Utf8Info.java" new file mode 100644 index 0000000000..35b28cdafc --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/constant/Utf8Info.java" @@ -0,0 +1,31 @@ +package com.coderising.jvm.constant; + +public class Utf8Info extends ConstantInfo{ + + private int tag = ConstantInfo.UTF8_INFO; + private int length; + private String value; + + public Utf8Info(ConstantPool constantPool){ + super(constantPool); + } + public String getValue() { + + return value; + } + public void setValue(String value) { + this.value = value; + } + + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ByteCodeIterator.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ByteCodeIterator.java" new file mode 100644 index 0000000000..761a8db37e --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ByteCodeIterator.java" @@ -0,0 +1,48 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.utils.Util; + +public class ByteCodeIterator { + + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + pos = 0; + } + public int nextByteToInt(){ + if (pos < this.codes.length) { + return Util.bytesToInt(new byte[]{codes[pos++]}); + } + return -1; + } + public int next2BytesToInt(){ + if (pos < this.codes.length) { + return Util.bytesToInt(new byte[]{codes[pos++],codes[pos++]}); + } + return -1; + } + public String next2BytesToHexString(){ + if (pos < this.codes.length) { + return Util.bytesToHexString(new byte[]{codes[pos++],codes[pos++]}); + } + return null; + } + public String next4BytesToString(){ + if (pos < this.codes.length) { + return Util.bytesToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + return null; + } + public byte[] getBytes(int length) { + if ((pos + length) < this.codes.length) { + byte[] by = new byte[length]; + for (int i = 0; i < by.length; i++) { + by[i] = this.codes[pos++]; + } + return by; + } + return null; + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileLoader.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileLoader.java" new file mode 100644 index 0000000000..96b3905428 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileLoader.java" @@ -0,0 +1,97 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clasfile.ClassFile; + +public class ClassFileLoader { + + private List list = new ArrayList(); + + public ClassFileLoader() { + + } + + public void addClassPath(String path) { + if (list.contains(path)) { + return; + } + list.add(path); + } + + public String getClassPath() { + if (list.size() == 0 || list == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + if (i == list.size() - 1) { + stringBuilder.append(list.get(i)); + } else { + stringBuilder.append(list.get(i)).append(";"); + } + + } + return stringBuilder.toString(); + } + + public byte[] readBinaryCode(String className){ + + String clzName = className.replace(".", File.separator) + ".class";; + + for(String path : list){ + String fileName = path + File.separator + clzName; + byte[] codes = loadClassFile(fileName); + if (codes != null) { + return codes; + } + } + return null; + } + + private byte[] loadClassFile(String fileName){ + + BufferedInputStream bis = null; + File classFile = new File(fileName); + try { + bis = new BufferedInputStream(new FileInputStream(classFile)); + byte[] bytes_code = new byte[1024]; + int len = 0; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while((len = bis.read(bytes_code)) != -1){ + baos.write(bytes_code, 0, len); + } + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } + finally{ + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + public ClassFile loadClass(String className) { + + byte[] codes = this.readBinaryCode(className); + ClassFileParser clzPaser = new ClassFileParser(); + return clzPaser.parse(codes); + } + + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileParser.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileParser.java" new file mode 100644 index 0000000000..5341bbc7c3 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/loader/ClassFileParser.java" @@ -0,0 +1,134 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clasfile.AccessFlag; +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.clasfile.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodInfo; +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 clzFile = new ClassFile(); + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + + // Magic Number + String Magic = iterator.next4BytesToString(); + clzFile.setMagicNumer(Magic); + + // Version Number + int MinorVersion = iterator.next2BytesToInt(); + int MajorVersion = iterator.next2BytesToInt(); + clzFile.setMinorVersion(MinorVersion); + clzFile.setMajorVersion(MajorVersion); + + clzFile.setPool(parseConstantPool(iterator)); + clzFile.setAccessFlag(parseAccessFlag(iterator)); + clzFile.setClassIndex(parseClassIndex(iterator)); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iterator) { + AccessFlag accessFlag = new AccessFlag(); + int flagValue = iterator.next2BytesToInt(); + accessFlag.setFlag(flagValue); + + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iterator) { + + ClassIndex classIndex = new ClassIndex(); + int thisClassIndex = iterator.next2BytesToInt(); + int superClassIndex = iterator.next2BytesToInt(); + classIndex.setThisClassIndex(thisClassIndex); + classIndex.setSuperClassIndex(superClassIndex); + + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iterator) { + + ConstantPool pool = new ConstantPool(); + int ConstantNumber = iterator.next2BytesToInt(); + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= ConstantNumber - 1; i++) { + int tag = iterator.nextByteToInt(); + + if (tag == 7) { + ClassInfo clzInfo = new ClassInfo(pool); + int utf8Index = iterator.next2BytesToInt(); + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + } + else if(tag == 1){ + Utf8Info utf8Info = new Utf8Info(pool); + int length = iterator.next2BytesToInt(); + utf8Info.setLength(length); + byte[] utf8Bytes = iterator.getBytes(length); + String value = null; + try { + value = new String(utf8Bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + } + else if(tag == 12){ + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + + int Index_Name = iterator.next2BytesToInt(); + int Index_Describe = iterator.next2BytesToInt(); + + nameAndTypeInfo.setIndex_Name(Index_Name); + nameAndTypeInfo.setIndex_Describe(Index_Describe); + pool.addConstantInfo(nameAndTypeInfo); + } + + else if(tag == 10){ + MethodInfo methofInfo = new MethodInfo(pool); + int Index_ClassInfo = iterator.next2BytesToInt(); + int Index_NameAndType = iterator.next2BytesToInt(); + + methofInfo.setIndex_ClassInfo(Index_ClassInfo); + methofInfo.setIndex_NameAndType(Index_NameAndType); + pool.addConstantInfo(methofInfo); + + } + + else if (tag == 9) { + + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + int Index_ClassInfo = iterator.next2BytesToInt(); + int Index_NameAndType = iterator.next2BytesToInt(); + + fieldRefInfo.setIndex_ClassInfo(Index_ClassInfo); + fieldRefInfo.setIndex_NameAndType(Index_NameAndType); + pool.addConstantInfo(fieldRefInfo); + } + else if (tag == 8) { + + StringInfo stringInfo = new StringInfo(pool); + int index = iterator.next2BytesToInt(); + + stringInfo.setIndex(index); + pool.addConstantInfo(stringInfo); + } + } + return pool; + + } +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" new file mode 100644 index 0000000000..550e0cacd9 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" @@ -0,0 +1,197 @@ +package com.coderising.jvm.test; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.clasfile.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.Utf8Info; +import com.coderising.jvm.loader.ClassFileLoader; + +public class ClassFileLoaderTest { + + private static String path1 = "D:\\MyTest\\mini-jvm\\bin"; + private static String path2 = "C:\\temp"; + private final static String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + private 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 { + } + + @Test + public void test() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); + } + + @Test + public void ClassFileLengthTest(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] bytes = loader.readBinaryCode(className); + + Assert.assertEquals(1056, bytes.length); + } + + @Test + public void MagicNumberTest(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + + byte[] bytes = { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; + String actualString = byteToHexString(bytes); + Assert.assertEquals("cafebabe", actualString); + } + + private String byteToHexString(byte[] bytes) { + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[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(51, clzFile.getMajorVersion()); + } + + @Test + public void testConstantool(){ + + ConstantPool pool = clzFile.getConstantPool(); + + Assert.assertEquals(53, pool.getConstantNumber()); + + { + 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()); + } + + { + MethodInfo methodRef = (MethodInfo)pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getIndex_ClassInfo()); + Assert.assertEquals(13, methodRef.getIndex_NameAndType()); + } + + { + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool.getConstantInfo(13); + Assert.assertEquals(9, nameAndTypeInfo.getIndex_Name()); + Assert.assertEquals(14, nameAndTypeInfo.getIndex_Describe()); + } + + { + MethodInfo methodRef = (MethodInfo)pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getIndex_ClassInfo()); + Assert.assertEquals(46, methodRef.getIndex_NameAndType()); + } + + { + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + + { + FieldRefInfo fieldRefInfo = (FieldRefInfo) pool.getConstantInfo(28); + Assert.assertEquals(29, fieldRefInfo.getIndex_ClassInfo()); + Assert.assertEquals(31, fieldRefInfo.getIndex_NameAndType()); + + } + + } + + + @Test + public void testClassIndex(){ + + ClassIndex clzIndex = clzFile.getClassIndex(); + 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/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/EmployeeV1.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/EmployeeV1.java" new file mode 100644 index 0000000000..39af3b3d32 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/test/EmployeeV1.java" @@ -0,0 +1,32 @@ +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(); + } + +} diff --git "a/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/utils/Util.java" "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/utils/Util.java" new file mode 100644 index 0000000000..56648f5db9 --- /dev/null +++ "b/group20/925290009/\347\254\254\344\272\224\346\254\241\344\275\234\344\270\232/jvm/com/coderising/jvm/utils/Util.java" @@ -0,0 +1,22 @@ +package com.coderising.jvm.utils; + +public class Util { + + public static int bytesToInt(byte[] by){ + String hexString = bytesToHexString(by); + return Integer.valueOf(hexString, 16).intValue(); + } + + public static String bytesToHexString(byte[] by){ + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < by.length; i++) { + int value = by[i] & 0xFF; + String strHex = Integer.toHexString(value); + if(strHex.length()< 2){ + strHex = "0" + strHex; + } + stringBuilder.append(strHex); + } + return stringBuilder.toString(); + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" new file mode 100644 index 0000000000..147ee9e15f --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/MyStack.java" @@ -0,0 +1,42 @@ +package com.ralf.stack; + +import java.util.LinkedList; +import java.util.NoSuchElementException; + +/** + * ʵֻݽṹջ + * + * @author Ralf + * + */ +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/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtil.java" new file mode 100644 index 0000000000..758178131c --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/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/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" new file mode 100644 index 0000000000..f547c5e0c1 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/StackUtilsTest.java" @@ -0,0 +1,87 @@ +package com.ralf.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class StackUtilsTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testReverse() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.reverse(stack); + //Assert.assertEquals(5, stack.size()); + + Assert.assertEquals(1, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(3, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(5, stack.pop().intValue()); + } + + @Test + public void testRemove() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + StackUtil.remove(stack, 3); + + Assert.assertEquals(4, stack.size()); + + Assert.assertEquals(5, stack.pop().intValue()); + Assert.assertEquals(4, stack.pop().intValue()); + Assert.assertEquals(2, stack.pop().intValue()); + Assert.assertEquals(1, stack.pop().intValue()); + } + + public void testGetTop() { + + MyStack stack = new MyStack<>(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + stack.push(5); + Assert.assertEquals(5, stack.size()); + + Integer[] integerReal = StackUtil.getTop(stack, 3); + int[] intExpeted = { 1, 2, 3 }; + int[] intReal = new int[integerReal.length]; + for (int i = 0; i < integerReal.length; i++) { + intReal[i] = integerReal[i]; + } + Assert.assertEquals(5, stack.size()); + Assert.assertArrayEquals(intExpeted, intReal); + + } + + @Test + public void testIsValidPair(){ + + String stringTrue = "([e{d}f])"; + String stringFalse = "([b{x]y})"; + + Assert.assertTrue(StackUtil.isValidPairs(stringTrue)); + Assert.assertFalse(StackUtil.isValidPairs(stringFalse)); + + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/ExprIterator.java" new file mode 100644 index 0000000000..d82db3e915 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/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/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" new file mode 100644 index 0000000000..46422db77f --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExpr.java" @@ -0,0 +1,112 @@ +package com.ralf.stack.expr; + +import com.ralf.stack.MyStack; + +public class InfixExpr { + + String expr = null; + private MyStack operateStack = new MyStack<>(); + private MyStack numStack = new MyStack<>(); + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + ExprIterator iterator = new ExprIterator(expr); + + while (iterator.hasNextOperate()) { + String operateString = iterator.nextOperateString(); + if (numStack.isEmpty()) { + + numStack.push(iterator.nextNumString()); + numStack.push(iterator.nextNumString()); + operateStack.push(operateString); + + } else if (operateStack.peek().equals("*") + || operateStack.peek().equals("/")) { + + getOperatorAndNum(); + operateStack.push(operateString); + numStack.push(iterator.nextNumString()); + + } else { + if (operateString.equals("+") + || operateString.equals("-")) { + + getOperatorAndNum(); + operateStack.push(operateString); + numStack.push(iterator.nextNumString()); + + } + else { + + numStack.push(iterator.nextNumString()); + operateStack.push(operateString); + + } + } + + } + + return getFinalResult(numStack,operateStack); + } + + private void getOperatorAndNum() { + + String oper = operateStack.pop(); + int secondNum = numStack.pop(); + int firstNum = numStack.pop(); + numStack.push(calculate(firstNum, secondNum, oper)); + } + + private int getFinalResult(MyStack numStack, + MyStack operateStack) { + + if (operateStack.isEmpty()) { + return numStack.pop(); + } + + getOperatorAndNum(); + return getFinalResult(numStack, operateStack); + + } + + private int calculate(int firstNum, int secondNum, String oper) { + + int result; + switch (oper) { + case "+": + result = firstNum + secondNum; + break; + + case "-": + result = firstNum - secondNum; + break; + case "*": + result = firstNum * secondNum; + break; + case "/": + result = firstNum / secondNum; + break; + + default: + result = 0; + break; + } + return result; + } + + public void getString() { + + ExprIterator iterator = new ExprIterator(expr); + while (iterator.hasNextNum()) { + System.out.print(iterator.nextNumString()); + } + while (iterator.hasNextOperate()) { + System.out.print(iterator.nextOperateString()); + } + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" new file mode 100644 index 0000000000..50af62dcea --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/data-struct/com/ralf/stack/expr/InfixExprTest.java" @@ -0,0 +1,49 @@ +package com.ralf.stack.expr; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class InfixExprTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testToString() { + InfixExpr expr = new InfixExpr("2+3*4+5"); + + expr.getString(); + } + + @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); + } + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/AttributeInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/AttributeInfo.java" new file mode 100644 index 0000000000..1df3a72c73 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/AttributeInfo.java" @@ -0,0 +1,20 @@ +package com.coderising.jvm.attribute; + +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/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/CodeAttr.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/CodeAttr.java" new file mode 100644 index 0000000000..9a715c5d65 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/CodeAttr.java" @@ -0,0 +1,87 @@ +package com.coderising.jvm.attribute; + +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.constant.Utf8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class CodeAttr extends AttributeInfo{ + + private int attrLen; + private int maxStack; + private int maxLocals; + private int codeLen; + private String code; + + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + + public CodeAttr(int attrNameIndex, int attrLen, int maxStack, int maxLocals, int codeLen,String code) { + super(attrNameIndex, attrLen); + this.maxLocals = maxLocals; + this.maxStack = maxStack; + this.code = code; + this.codeLen = codeLen; + } + + public String getCodeString(){ + return this.code; + } + + public static CodeAttr parse(ClassFile classFile, ByteCodeIterator iterator) { + + iterator.back(2); + int attrNameIndex = iterator.next2BytesToInt(); + int attrLen = iterator.next4BytesToInt(); + int maxstack = iterator.next2BytesToInt(); + int maxlocals = iterator.next2BytesToInt(); + int codelen = iterator.next4BytesToInt(); + String code = iterator.nextXBytesToString(codelen); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxstack, maxlocals, codelen, code); + + int exceptionCount = iterator.next2BytesToInt(); + if (exceptionCount > 0) { + throw new RuntimeException("Exception is null." + exceptionCount); + } + int childCount = iterator.next2BytesToInt(); + if (childCount > 0) { + for (int i = 0; i < childCount; i++) { + + int childIndex = iterator.next2BytesToInt(); + String attrName = classFile.getPool().getUtf8String(childIndex); + + if (AttributeInfo.LINE_NUM_TABLE.equals(attrName)) { + LineNumberTable lineNumber = LineNumberTable.parse(iterator); + codeAttr.setLineNumTable(lineNumber); + } + else if(AttributeInfo.LOCAL_VAR_TABLE.equals(attrName)){ + LocalVariableTable localVarTable = LocalVariableTable.parse(classFile,iterator); + codeAttr.setLocalVarTable(localVarTable); + } + else if(AttributeInfo.STACK_MAP_TABLE.equals(attrName)){ + StackMapTable stackMapTable = StackMapTable.parse(classFile,iterator); + codeAttr.setStackMapTable(stackMapTable); + } + else { + throw new RuntimeException("This " + attrName +"is not added."); + } + } + } + + return codeAttr; + } + + public void setLineNumTable(LineNumberTable lineNumTable) { + this.lineNumTable = lineNumTable; + } + + public void setLocalVarTable(LocalVariableTable localVarTable) { + this.localVarTable = localVarTable; + } + + public void setStackMapTable(StackMapTable stackMapTable) { + this.stackMapTable = stackMapTable; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LineNumberTable.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LineNumberTable.java" new file mode 100644 index 0000000000..810111fe33 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LineNumberTable.java" @@ -0,0 +1,62 @@ +package com.coderising.jvm.attribute; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LineNumberTable extends AttributeInfo{ + + private List lineNumberItems = new ArrayList<>(); + + private static class LineNumberItem{ + + private int startPc; + private 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 lineNumberItem){ + this.lineNumberItems.add(lineNumberItem); + } + + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + public static LineNumberTable parse(ByteCodeIterator iterator) { + iterator.back(2); + int attrIndex = iterator.next2BytesToInt(); + int attrlen = iterator.next4BytesToInt(); + LineNumberTable lineNumberTable = new LineNumberTable(attrIndex, attrlen); + int lineNumberCount = iterator.next2BytesToInt(); + + if (lineNumberCount > 0) { + + for (int i = 0; i < lineNumberCount; i++) { + LineNumberItem lItem = new LineNumberItem(); + lItem.setStartPc(iterator.next2BytesToInt()); + lItem.setLineNum(iterator.next2BytesToInt()); + lineNumberTable.addLineNumberItem(lItem); + } + } + + return lineNumberTable; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableItem.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableItem.java" new file mode 100644 index 0000000000..2d2b117e68 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableItem.java" @@ -0,0 +1,51 @@ +package com.coderising.jvm.attribute; + +public class LocalVariableItem{ + + private int start; + private int lenth; + private int nameIndex; + private int describeIndex; + private int slotIndex; + + public int getStart() { + return start; + } + + public void setStart(int start) { + this.start = start; + } + + public int getLenth() { + return lenth; + } + + public void setLenth(int lenth) { + this.lenth = lenth; + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getDescribeIndex() { + return describeIndex; + } + + public void setDescribeIndex(int describeIndex) { + this.describeIndex = describeIndex; + } + + public int getSlotIndex() { + return slotIndex; + } + + public void setSlotIndex(int slotIndex) { + this.slotIndex = slotIndex; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableTable.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableTable.java" new file mode 100644 index 0000000000..dbbe83dd07 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/LocalVariableTable.java" @@ -0,0 +1,45 @@ +package com.coderising.jvm.attribute; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class LocalVariableTable extends AttributeInfo{ + + private List localVariableItems = new ArrayList<>(); + + public LocalVariableTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + public void addLocalVaribleItem(LocalVariableItem lItem){ + this.localVariableItems.add(lItem); + } + + public static LocalVariableTable parse(ClassFile classFile, + ByteCodeIterator iterator) { + iterator.back(2); + int attrIndex = iterator.next2BytesToInt(); + int attrlen = iterator.next4BytesToInt(); + int localVariCount = iterator.next2BytesToInt(); + LocalVariableTable lTable = new LocalVariableTable(attrIndex, attrlen); + + if(localVariCount > 0){ + for (int i = 0; i < localVariCount; i++) { + LocalVariableItem lItem = new LocalVariableItem(); + lItem.setStart(iterator.next2BytesToInt()); + lItem.setLenth(iterator.next2BytesToInt()); + lItem.setNameIndex(iterator.next2BytesToInt()); + lItem.setDescribeIndex(iterator.next2BytesToInt()); + lItem.setSlotIndex(iterator.next2BytesToInt()); + + lTable.addLocalVaribleItem(lItem); + } + } + return lTable; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/StackMapTable.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/StackMapTable.java" new file mode 100644 index 0000000000..0559fa60f1 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/attribute/StackMapTable.java" @@ -0,0 +1,36 @@ +package com.coderising.jvm.attribute; + +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class StackMapTable extends AttributeInfo{ + + private String originCode; + + public String getOriginCode() { + return originCode; + } + + public void setOriginCode(String originCode) { + this.originCode = originCode; + } + + public StackMapTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + } + + public static StackMapTable parse(ClassFile classFile, + ByteCodeIterator iterator) { + + iterator.back(2); + int attName_index = iterator.next2BytesToInt(); + int attr_len = iterator.next4BytesToInt(); + StackMapTable stackMapTable = new StackMapTable(attName_index, attr_len); + + String codeString = iterator.nextXBytesToString(attr_len); + stackMapTable.setOriginCode(codeString); + + return stackMapTable; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/AccessFlag.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/AccessFlag.java" new file mode 100644 index 0000000000..b1d40c20ff --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/AccessFlag.java" @@ -0,0 +1,22 @@ +package com.coderising.jvm.clasfile; + +public class AccessFlag { + + private int flag; + + public int getFlag() { + return flag; + } + + public void setFlag(int flag) { + this.flag = flag; + } + + public boolean isPublic(){ + return (this.flag & 0x0001) != 0; + } + + public boolean isFinalClass(){ + return (this.flag & 0x0010) != 0; + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassFile.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassFile.java" new file mode 100644 index 0000000000..708257ddb2 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassFile.java" @@ -0,0 +1,85 @@ +package com.coderising.jvm.clasfile; + +import java.util.ArrayList; +import java.util.List; + +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.field.JField; +import com.coderising.jvm.method.JMethod; + +public class ClassFile { + + private int MinorVersion; + private int MajorVersion; + private String MagicNumer; + private ConstantPool pool; + private ClassIndex classIndex; + private AccessFlag accessFlag; + private List fields = new ArrayList<>(); + private List jMethods = new ArrayList<>(); + + public ConstantPool getPool() { + return pool; + } + + public void setPool(ConstantPool pool) { + this.pool = pool; + } + + public String getMagicNumer() { + return MagicNumer; + } + + public void setMagicNumer(String magicNumer) { + this.MagicNumer = magicNumer; + } + + public int getMinorVersion() { + return MinorVersion; + } + + public int getMajorVersion() { + return MajorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.MinorVersion = minorVersion; + } + + public void setMajorVersion(int majorVersion) { + this.MajorVersion = majorVersion; + } + + public ClassIndex getClassIndex() { + 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 getJFields() { + return this.fields; + } + + public void addJField(JField jField){ + this.fields.add(jField); + } + + public List getMethods() { + return this.jMethods; + } + + public void addJMethod(JMethod jmethod){ + this.jMethods.add(jmethod); + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassIndex.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassIndex.java" new file mode 100644 index 0000000000..c98eae755f --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/clasfile/ClassIndex.java" @@ -0,0 +1,21 @@ +package com.coderising.jvm.clasfile; + +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/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ClassInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ClassInfo.java" new file mode 100644 index 0000000000..4f9077cbb6 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ClassInfo.java" @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +public class ClassInfo extends ConstantInfo{ + + private int type = ConstantInfo.CLASS_INFO; + private int Utf8Index; + + public ClassInfo(ConstantPool constantPool){ + super(constantPool); + } + public int getUtf8Index() { + return Utf8Index; + } + + public void setUtf8Index(int utf8Index) { + Utf8Index = utf8Index; + } + + public String getClassName(){ + Utf8Info utf8Info = (Utf8Info) this.constantPool.getConstantInfo(Utf8Index); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return this.type; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java" new file mode 100644 index 0000000000..bc2acc7c6e --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantInfo.java" @@ -0,0 +1,26 @@ +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 constantPool){ + this.constantPool = constantPool; + } + + public ConstantPool getConstantPool(){ + return this.constantPool; + } + public abstract int getType(); + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantPool.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantPool.java" new file mode 100644 index 0000000000..9e6016915c --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/ConstantPool.java" @@ -0,0 +1,25 @@ +package com.coderising.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new ArrayList(); + + public int getConstantNumber() { + return this.constantInfos.size() - 1; + } + + public void addConstantInfo(ConstantInfo constantInfo){ + this.constantInfos.add(constantInfo); + } + public Object getConstantInfo(int index) { + + return this.constantInfos.get(index); + } + + public String getUtf8String(int index){ + return ((Utf8Info)this.constantInfos.get(index)).getValue(); + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java" new file mode 100644 index 0000000000..22a7b5c5f7 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/FieldRefInfo.java" @@ -0,0 +1,63 @@ +package com.coderising.jvm.constant; + +public class FieldRefInfo extends ConstantInfo { + + private int tag = ConstantInfo.FIELD_INFO; + private int Index_ClassInfo; + private int Index_NameAndType; + + public FieldRefInfo(ConstantPool constantPool) { + super(constantPool); + } + + public int getIndex_ClassInfo() { + return Index_ClassInfo; + } + + public void setIndex_ClassInfo(int index_ClassInfo) { + Index_ClassInfo = index_ClassInfo; + } + + public int getIndex_NameAndType() { + return Index_NameAndType; + } + + public void setIndex_NameAndType(int index_NameAndType) { + Index_NameAndType = index_NameAndType; + } + + public String getClassName() { + + ConstantPool pool = this.getConstantPool(); + + ClassInfo classInfo = (ClassInfo) pool + .getConstantInfo(getIndex_ClassInfo()); + return classInfo.getClassName(); + } + + public String getParameterAndTypeString() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getDescribeInfo(); + } + + public String getMethodName() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getNameInfo(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/MethodInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/MethodInfo.java" new file mode 100644 index 0000000000..1a52212645 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/MethodInfo.java" @@ -0,0 +1,62 @@ +package com.coderising.jvm.constant; + +public class MethodInfo extends ConstantInfo { + + private int tag = ConstantInfo.METHOD_INFO; + private int Index_ClassInfo; + private int Index_NameAndType; + + public MethodInfo(ConstantPool constantPool) { + super(constantPool); + } + + public int getIndex_ClassInfo() { + return Index_ClassInfo; + } + + public void setIndex_ClassInfo(int index_ClassInfo) { + Index_ClassInfo = index_ClassInfo; + } + + public int getIndex_NameAndType() { + return Index_NameAndType; + } + + public void setIndex_NameAndType(int index_NameAndType) { + Index_NameAndType = index_NameAndType; + } + + public String getClassName() { + + ConstantPool pool = this.getConstantPool(); + ClassInfo classInfo = (ClassInfo) pool + .getConstantInfo(getIndex_ClassInfo()); + return classInfo.getClassName(); + } + + public String getParameterAndTypeString() { + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getDescribeInfo(); + + } + + public String getMethodName() { + + int index = getIndex_NameAndType(); + ConstantPool pool = this.getConstantPool(); + + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(index); + return nameAndTypeInfo.getNameInfo(); + } + + @Override + public int getType() { + return this.tag; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" new file mode 100644 index 0000000000..c8731e9216 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NameAndTypeInfo.java" @@ -0,0 +1,46 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo { + + private int tag = ConstantInfo.NAME_AND_TYPE_INFO; + private int Index_Name; + private int Index_Describe; + + public NameAndTypeInfo(ConstantPool constantPool){ + super(constantPool); + } + public int getIndex_Name() { + return Index_Name; + } + + public void setIndex_Name(int index_Name) { + Index_Name = index_Name; + } + + public int getIndex_Describe() { + return Index_Describe; + } + + public void setIndex_Describe(int index_Describe) { + Index_Describe = index_Describe; + } + + public String getNameInfo(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(Index_Name); + return utf8Info.getValue(); + } + public String getDescribeInfo(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(Index_Describe); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java" new file mode 100644 index 0000000000..3428c1ea65 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/NullConstantInfo.java" @@ -0,0 +1,11 @@ +package com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){} + @Override + public int getType() { + return -1; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/StringInfo.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/StringInfo.java" new file mode 100644 index 0000000000..83339240f5 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/StringInfo.java" @@ -0,0 +1,32 @@ +package com.coderising.jvm.constant; + +public class StringInfo extends ConstantInfo { + + private int tag = ConstantInfo.STRING_INFO; + private int index; + + public StringInfo(ConstantPool constantPool){ + super(constantPool); + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getStringName(){ + + ConstantPool pool = this.getConstantPool(); + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(getIndex()); + return utf8Info.getValue(); + } + + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/Utf8Info.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/Utf8Info.java" new file mode 100644 index 0000000000..da82973e87 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/constant/Utf8Info.java" @@ -0,0 +1,30 @@ +package com.coderising.jvm.constant; + +public class Utf8Info extends ConstantInfo{ + + private int tag = ConstantInfo.UTF8_INFO; + private int length; + private String value; + + public Utf8Info(ConstantPool constantPool){ + super(constantPool); + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + public int getLength() { + return length; + } + public void setLength(int length) { + this.length = length; + } + @Override + public int getType() { + return tag; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/field/JField.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/field/JField.java" new file mode 100644 index 0000000000..005dc0da6d --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/field/JField.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 JField { + + private int access_flags; + private int name_index; + private int descriptor_index; + private ConstantPool pool; + + public JField(int access_flags, int name_index, int descriptor_index, + ConstantPool pool) { + this.access_flags = access_flags; + this.name_index = name_index; + this.descriptor_index = descriptor_index; + this.pool = pool; + + } + + public static JField parse(ConstantPool pool, ByteCodeIterator iterator){ + + int accessflag = iterator.next2BytesToInt(); + int nameindex = iterator.next2BytesToInt(); + int descripindex = iterator.next2BytesToInt(); + + int attribute_count = iterator.next2BytesToInt(); + if (attribute_count > 0) { + throw new RuntimeException("Field attribute_info is not added."); + } + JField field = new JField(accessflag, nameindex, descripindex, pool); + return field; + } + + public String toString(){ + + String name = ((Utf8Info)this.pool.getConstantInfo(name_index)).getValue(); + String descriptor = ((Utf8Info) this.pool.getConstantInfo(descriptor_index)).getValue(); + + return name + ":" + descriptor; + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java" new file mode 100644 index 0000000000..2ae06411ce --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ByteCodeIterator.java" @@ -0,0 +1,67 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.utils.Util; + +public class ByteCodeIterator { + + private byte[] codes; + private int pos; + + public ByteCodeIterator(byte[] codes){ + this.codes = codes; + pos = 0; + } + public int nextByteToInt(){ + if (pos < this.codes.length) { + return Util.bytesToInt(new byte[]{codes[pos++]}); + } + return -1; + } + public int next2BytesToInt(){ + if (pos < this.codes.length) { + return Util.bytesToInt(new byte[]{codes[pos++],codes[pos++]}); + } + return -1; + } + public int next4BytesToInt(){ + if (pos < this.codes.length) { + return Util.bytesToInt(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + return -1; + } + public String next2BytesToHexString(){ + if (pos < this.codes.length) { + return Util.bytesToHexString(new byte[]{codes[pos++],codes[pos++]}); + } + return null; + } + public String next4BytesToString(){ + if (pos < this.codes.length) { + return Util.bytesToHexString(new byte[]{codes[pos++],codes[pos++],codes[pos++],codes[pos++]}); + } + return null; + } + public byte[] getBytes(int length) { + if ((pos + length) < this.codes.length) { + byte[] by = new byte[length]; + for (int i = 0; i < by.length; i++) { + by[i] = this.codes[pos++]; + } + return by; + } + return null; + } + public String nextXBytesToString(int len){ + + byte[] temp = new byte[len]; + for (int i = 0; i < temp.length; i++) { + temp[i] = codes[pos++]; + } + + return Util.bytesToHexString(temp).toLowerCase(); + } + + public void back(int n){ + this.pos -= n; + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" new file mode 100644 index 0000000000..0c9c290cca --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" @@ -0,0 +1,96 @@ +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 com.coderising.jvm.clasfile.ClassFile; + +public class ClassFileLoader { + + private List list = new ArrayList(); + + public ClassFileLoader() { + + } + + public void addClassPath(String path) { + if (list.contains(path)) { + return; + } + list.add(path); + } + + public String getClassPath() { + if (list.size() == 0 || list == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + if (i == list.size() - 1) { + stringBuilder.append(list.get(i)); + } else { + stringBuilder.append(list.get(i)).append(";"); + } + + } + return stringBuilder.toString(); + } + + public byte[] readBinaryCode(String className){ + + String clzName = className.replace(".", File.separator) + ".class"; + + for(String path : list){ + String fileName = path + File.separator + clzName; + byte[] codes = loadClassFile(fileName); + if (codes != null) { + return codes; + } + } + return null; + } + + private byte[] loadClassFile(String fileName){ + + BufferedInputStream bis = null; + File classFile = new File(fileName); + try { + bis = new BufferedInputStream(new FileInputStream(classFile)); + byte[] bytes_code = new byte[1024]; + int len = 0; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while((len = bis.read(bytes_code)) != -1){ + baos.write(bytes_code, 0, len); + } + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } + finally{ + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + public ClassFile loadClass(String className) { + + byte[] codes = this.readBinaryCode(className); + ClassFileParser clzPaser = new ClassFileParser(); + return clzPaser.parse(codes); + } + + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java" new file mode 100644 index 0000000000..07b8f11cbe --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileParser.java" @@ -0,0 +1,169 @@ +package com.coderising.jvm.loader; + +import java.io.UnsupportedEncodingException; + +import com.coderising.jvm.clasfile.AccessFlag; +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.clasfile.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodInfo; +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.JField; +import com.coderising.jvm.method.JMethod; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ClassFile clzFile = new ClassFile(); + + ByteCodeIterator iterator = new ByteCodeIterator(codes); + + // Magic Number + String Magic = iterator.next4BytesToString(); + if (!(Magic.equals("cafebabe"))) { + return null; + } + clzFile.setMagicNumer(Magic); + // Version Number + int MinorVersion = iterator.next2BytesToInt(); + int MajorVersion = iterator.next2BytesToInt(); + clzFile.setMinorVersion(MinorVersion); + clzFile.setMajorVersion(MajorVersion); + + clzFile.setPool(parseConstantPool(iterator)); + clzFile.setAccessFlag(parseAccessFlag(iterator)); + clzFile.setClassIndex(parseClassIndex(iterator)); + + parseInterface(iterator); + parseJFields(clzFile, iterator); + parseJMethods(clzFile, iterator); + + return clzFile; + } + + private void parseJMethods(ClassFile classFile, ByteCodeIterator iterator){ + + int jmethodCount = iterator.next2BytesToInt(); + System.out.println("JMethod Count:" + jmethodCount); + for (int i = 0; i < jmethodCount; i++) { + JMethod jMethod = JMethod.parse(classFile, iterator); + classFile.addJMethod(jMethod); + } + } + private void parseJFields(ClassFile classFile, ByteCodeIterator iterator){ + + int jfieldCount = iterator.next2BytesToInt(); + System.out.println("JField Count :" + jfieldCount); + + for (int i = 0; i < jfieldCount; i++) { + classFile.addJField(JField.parse(classFile.getPool(), iterator)); + } + + } + private void parseInterface(ByteCodeIterator iterator) { + int interfaceCount = iterator.next2BytesToInt(); + System.out.println("InterfaceCount:" + interfaceCount); + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iterator) { + AccessFlag accessFlag = new AccessFlag(); + int flagValue = iterator.next2BytesToInt(); + accessFlag.setFlag(flagValue); + + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iterator) { + + ClassIndex classIndex = new ClassIndex(); + int thisClassIndex = iterator.next2BytesToInt(); + int superClassIndex = iterator.next2BytesToInt(); + classIndex.setThisClassIndex(thisClassIndex); + classIndex.setSuperClassIndex(superClassIndex); + + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iterator) { + + ConstantPool pool = new ConstantPool(); + int ConstantNumber = iterator.next2BytesToInt(); + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i <= ConstantNumber - 1; i++) { + int tag = iterator.nextByteToInt(); + + if (tag == 7) { + + ClassInfo clzInfo = new ClassInfo(pool); + int utf8Index = iterator.next2BytesToInt(); + clzInfo.setUtf8Index(utf8Index); + pool.addConstantInfo(clzInfo); + + } else if (tag == 1) { + Utf8Info utf8Info = new Utf8Info(pool); + int length = iterator.next2BytesToInt(); + utf8Info.setLength(length); + byte[] utf8Bytes = iterator.getBytes(length); + String value = null; + try { + value = new String(utf8Bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + + } else if (tag == 12) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + + int Index_Name = iterator.next2BytesToInt(); + int Index_Describe = iterator.next2BytesToInt(); + + nameAndTypeInfo.setIndex_Name(Index_Name); + nameAndTypeInfo.setIndex_Describe(Index_Describe); + pool.addConstantInfo(nameAndTypeInfo); + } + + else if (tag == 10) { + MethodInfo methofInfo = new MethodInfo(pool); + int Index_ClassInfo = iterator.next2BytesToInt(); + int Index_NameAndType = iterator.next2BytesToInt(); + + methofInfo.setIndex_ClassInfo(Index_ClassInfo); + methofInfo.setIndex_NameAndType(Index_NameAndType); + pool.addConstantInfo(methofInfo); + + } + + else if (tag == 9) { + + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + int Index_ClassInfo = iterator.next2BytesToInt(); + int Index_NameAndType = iterator.next2BytesToInt(); + + fieldRefInfo.setIndex_ClassInfo(Index_ClassInfo); + fieldRefInfo.setIndex_NameAndType(Index_NameAndType); + pool.addConstantInfo(fieldRefInfo); + } else if (tag == 8) { + + StringInfo stringInfo = new StringInfo(pool); + int index = iterator.next2BytesToInt(); + + stringInfo.setIndex(index); + pool.addConstantInfo(stringInfo); + } + else { + throw new RuntimeException("the constant pool tag " + tag + "has been not immplemented yet!"); + } + } + return pool; + + } +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/method/JMethod.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/method/JMethod.java" new file mode 100644 index 0000000000..7c33d89e57 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/method/JMethod.java" @@ -0,0 +1,81 @@ +package com.coderising.jvm.method; + +import com.coderising.jvm.attribute.AttributeInfo; +import com.coderising.jvm.attribute.CodeAttr; +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.constant.Utf8Info; +import com.coderising.jvm.loader.ByteCodeIterator; + +public class JMethod { + + private int access_flags; + private int name_index; + private int descriptor_index; + private ClassFile clzFile; + + private CodeAttr codeAttr; + + public int getAccess_flags() { + return access_flags; + } + + public int getName_index() { + return name_index; + } + + public int getDescriptor_index() { + return descriptor_index; + } + + public ClassFile getClzFile() { + return clzFile; + } + + + public CodeAttr getCodeAttr() { + return codeAttr; + } + + public void setCodeAttr(CodeAttr codeAttr) { + this.codeAttr = codeAttr; + } + + public JMethod(ClassFile clzFile, int access_flags, int name_index, int descriptor_index) { + this.access_flags = access_flags; + this.name_index = name_index; + this.descriptor_index = descriptor_index; + } + + public static JMethod parse(ClassFile classFile, ByteCodeIterator iterator) { + + int accessFlag = iterator.next2BytesToInt(); + int nameIndex = iterator.next2BytesToInt(); + int descripIndex = iterator.next2BytesToInt(); + JMethod jMethod = new JMethod(classFile, accessFlag, nameIndex, descripIndex); + + int attribute_count = iterator.next2BytesToInt(); + if (attribute_count > 0) { + for (int i = 0; i < attribute_count; i++) { + + int attrIndex = iterator.next2BytesToInt(); + String attrName = classFile.getPool().getUtf8String(attrIndex); + + if (AttributeInfo.CODE.equals(attrName)) { + CodeAttr codeAttr = CodeAttr.parse(classFile,iterator); + jMethod.setCodeAttr(codeAttr); + } + else { + throw new RuntimeException("Attribute has not been added." + attrName); + } + } + } + + + + + + + return jMethod; + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" new file mode 100644 index 0000000000..dd7b271663 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" @@ -0,0 +1,266 @@ +package com.coderising.jvm.test; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.attribute.CodeAttr; +import com.coderising.jvm.clasfile.ClassFile; +import com.coderising.jvm.clasfile.ClassIndex; +import com.coderising.jvm.constant.ClassInfo; +import com.coderising.jvm.constant.ConstantPool; +import com.coderising.jvm.constant.FieldRefInfo; +import com.coderising.jvm.constant.MethodInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.Utf8Info; +import com.coderising.jvm.field.JField; +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.method.JMethod; + +public class ClassFileLoaderTest { + + private static String path1 = "D:\\MyTest\\mini-jvm\\bin"; + private static String path2 = "C:\\temp"; + private final static String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + private 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 { + } + + @Test + public void test() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); + } + + @Test + public void ClassFileLengthTest() { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] bytes = loader.readBinaryCode(className); + + Assert.assertEquals(1056, bytes.length); + } + + @Test + public void MagicNumberTest() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + + byte[] bytes = { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; + String actualString = byteToHexString(bytes); + Assert.assertEquals("cafebabe", actualString); + } + + private String byteToHexString(byte[] bytes) { + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[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(51, clzFile.getMajorVersion()); + } + + @Test + public void testConstantool() { + + ConstantPool pool = clzFile.getPool(); + + Assert.assertEquals(53, pool.getConstantNumber()); + + { + 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()); + } + + { + MethodInfo methodRef = (MethodInfo) pool.getConstantInfo(12); + Assert.assertEquals(3, methodRef.getIndex_ClassInfo()); + Assert.assertEquals(13, methodRef.getIndex_NameAndType()); + } + + { + NameAndTypeInfo nameAndTypeInfo = (NameAndTypeInfo) pool + .getConstantInfo(13); + Assert.assertEquals(9, nameAndTypeInfo.getIndex_Name()); + Assert.assertEquals(14, nameAndTypeInfo.getIndex_Describe()); + } + + { + MethodInfo methodRef = (MethodInfo) pool.getConstantInfo(45); + Assert.assertEquals(1, methodRef.getIndex_ClassInfo()); + Assert.assertEquals(46, methodRef.getIndex_NameAndType()); + } + + { + Utf8Info utf8Info = (Utf8Info) pool.getConstantInfo(53); + Assert.assertEquals("EmployeeV1.java", utf8Info.getValue()); + } + + { + FieldRefInfo fieldRefInfo = (FieldRefInfo) pool.getConstantInfo(28); + Assert.assertEquals(29, fieldRefInfo.getIndex_ClassInfo()); + Assert.assertEquals(31, fieldRefInfo.getIndex_NameAndType()); + + } + + } + + @Test + public void testClassIndex() { + + ClassIndex clzIndex = clzFile.getClassIndex(); + ClassInfo thisClassInfo = (ClassInfo) clzFile.getPool() + .getConstantInfo(clzIndex.getThisClassIndex()); + ClassInfo superClassInfo = (ClassInfo) clzFile.getPool() + .getConstantInfo(clzIndex.getSuperClassIndex()); + + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, + thisClassInfo.getClassName()); + Assert.assertEquals("java/lang/Object", superClassInfo.getClassName()); + } + + /** + * JVMʵֲ + */ + @Test + public void testReadFields() { + + List jfields = clzFile.getJFields(); + + Assert.assertEquals(2, jfields.size()); + { + JField jfield = jfields.get(0); + Assert.assertEquals("name:Ljava/lang/String;", jfield.toString()); + } + { + JField jfield = jfields.get(1); + Assert.assertEquals("age:I", jfield.toString()); + } + + } + + + @Test + public void testMethod() { + + List jMethods = clzFile.getMethods(); + ConstantPool pool = clzFile.getPool(); + + { + JMethod jMethod = jMethods.get(0); + assertJMethodEquals(pool, jMethod, "", + "(Ljava/lang/String;I)V", "2ab7000c2a2bb5000f2a1cb50011b1"); + } + { + JMethod jMethod = jMethods.get(1); + assertJMethodEquals(pool,jMethod, + "setName", + "(Ljava/lang/String;)V", + "2a2bb5000fb1"); + + } + { + JMethod jMethod = jMethods.get(2); + assertJMethodEquals(pool,jMethod, + "setAge", + "(I)V", + "2a1bb50011b1"); + } + { + JMethod jMethod = jMethods.get(3); + assertJMethodEquals(pool,jMethod, + "sayHello", + "()V", + "b2001c1222b60024b1"); + + } + { + JMethod jMethod = jMethods.get(4); + assertJMethodEquals(pool,jMethod, + "main", + "([Ljava/lang/String;)V", + "bb000159122b101db7002d4c2bb6002fb1"); + } + } + + + private void assertJMethodEquals(ConstantPool pool, JMethod jMethod, + String expectedName, String expectedDescrib, String expectedCode) { + String methodNameString = pool.getUtf8String(jMethod.getName_index()); + String realDescrib = pool.getUtf8String(jMethod.getDescriptor_index()); + String realCode = jMethod.getCodeAttr().getCodeString(); + + Assert.assertEquals(expectedName, methodNameString); + Assert.assertEquals(expectedDescrib, realDescrib); + Assert.assertEquals(expectedCode, realCode); + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" new file mode 100644 index 0000000000..39af3b3d32 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" @@ -0,0 +1,32 @@ +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(); + } + +} diff --git "a/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/utils/Util.java" "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/utils/Util.java" new file mode 100644 index 0000000000..56648f5db9 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\205\255\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/utils/Util.java" @@ -0,0 +1,22 @@ +package com.coderising.jvm.utils; + +public class Util { + + public static int bytesToInt(byte[] by){ + String hexString = bytesToHexString(by); + return Integer.valueOf(hexString, 16).intValue(); + } + + public static String bytesToHexString(byte[] by){ + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < by.length; i++) { + int value = by[i] & 0xFF; + String strHex = Integer.toHexString(value); + if(strHex.length()< 2){ + strHex = "0" + strHex; + } + stringBuilder.append(strHex); + } + return stringBuilder.toString(); + } +} diff --git "a/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrame.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrame.java" new file mode 100644 index 0000000000..47fdbbe85c --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrame.java" @@ -0,0 +1,122 @@ +package com.ralf.lru; + +/** + * ˫ʵLRU㷨 + * @author Ralf + * + */ +public class LRUPageFrame { + + private static class Node { + private Node prev; + private Node next; + int pageNum; + + public Node(int pageNum) { + this.pageNum = pageNum; + } + } + + private int capacity; + private Node head; + private Node tail; + private int size; + + private void addFirst(int PageNum) { + Node node = new Node(PageNum); + if (head == null) { + node.next = null; + node.prev = null; + head = node; + tail = node; + this.size++; + } else { + node.next = head; + node.prev = null; + head.prev = node; + head = node; + this.size++; + } + } + + public LRUPageFrame(int capacity) { + this.capacity = capacity; + this.head = null; + this.tail = null; + } + + /** + * ȡ + * @param PageNum + */ + public void access(int PageNum) { + + Node node = getNode(PageNum); + if (node == null) { + if (size < capacity) { + addFirst(PageNum); + } else { + removeLast(); + addFirst(PageNum); + } + } else if (this.head.pageNum == PageNum) { + return; + } + else { + moveToHead(node); + } + } + + private void moveToHead(Node node) { + Node current = node; + if (node.pageNum == this.tail.pageNum) { + node.prev.next = null; + tail = node.prev; + + } else { + node.prev.next = node.next; + node.next.prev = node.prev; + } + current.next = head; + current.prev = null; + this.head = current; + + } + + private void removeLast() { + + Node preNode = tail.prev; + tail.prev.next = null; + tail.prev = null; + tail = preNode; + this.size--; + } + + private Node getNode(int PageNum) { + Node current = this.head; + while (current != null) { + if (current.pageNum == PageNum) { + return current; + } + current = current.next; + } + return null; + } + + public String toString() { + if (this.head == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + Node current = this.head; + while (current != null) { + stringBuilder.append(current.pageNum); + if (current.next != null) { + stringBuilder.append(","); + } + current = current.next; + + } + return stringBuilder.toString(); + } +} diff --git "a/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrameTest.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrameTest.java" new file mode 100644 index 0000000000..b024277905 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/LRU/LRUPageFrameTest.java" @@ -0,0 +1,37 @@ +package com.ralf.lru; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class LRUPageFrameTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + + 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/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" new file mode 100644 index 0000000000..c6739db459 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoader.java" @@ -0,0 +1,79 @@ +package com.coderising.jvm.loader; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class ClassFileLoader { + + private List list = new ArrayList(); + + public ClassFileLoader() { + + } + + public void addClassPath(String path) { + list.add(path); + } + + public String getClassPath() { + if (list.size() == 0 || list == null) { + return null; + } + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < list.size(); i++) { + if (i == list.size() - 1) { + stringBuilder.append(list.get(i)); + } else { + stringBuilder.append(list.get(i)).append(";"); + } + + } + return stringBuilder.toString(); + } + + public byte[] readBinaryCode(String className) throws ClassFileLoaderException { + + String fileName = getFileName(className); + BufferedInputStream bis = null; + try { + bis = new BufferedInputStream(new FileInputStream(fileName)); + byte[] bytes_code = new byte[1024]; + int len = 0; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while((len = bis.read(bytes_code)) != -1){ + baos.write(bytes_code, 0, len); + } + return baos.toByteArray(); + } catch (FileNotFoundException e) { + throw new ClassFileLoaderException(e); + } catch (IOException e) { + throw new ClassFileLoaderException(e); + } + finally{ + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + throw new ClassFileLoaderException(e); + } + } + } + } + + private String getFileName(String className) { + StringBuilder stringBuilder = new StringBuilder(); + String folder = getClassPath(); + String packgeName = className.replace(".", "\\"); + + stringBuilder.append(folder).append('\\').append(packgeName).append(".class"); + return stringBuilder.toString(); + } + +} diff --git "a/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoaderException.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoaderException.java" new file mode 100644 index 0000000000..cb70b2d88f --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/loader/ClassFileLoaderException.java" @@ -0,0 +1,25 @@ +package com.coderising.jvm.loader; + +import java.io.FileNotFoundException; +import java.io.IOException; + +public class ClassFileLoaderException extends Exception{ + + /** + * + */ + private static final long serialVersionUID = 1L; + + public ClassFileLoaderException(String msg){ + super(msg); + } + + public ClassFileLoaderException(FileNotFoundException e){ + super(e); + } + + public ClassFileLoaderException(IOException e){ + super(e); + } + +} diff --git "a/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" new file mode 100644 index 0000000000..4585119f98 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/ClassFileLoaderTest.java" @@ -0,0 +1,75 @@ +package com.coderising.jvm.test; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.coderising.jvm.loader.ClassFileLoader; +import com.coderising.jvm.loader.ClassFileLoaderException; + +public class ClassFileLoaderTest { + + static String path1 = "D:\\MyTest\\mini-jvm\\bin"; + static String path2 = "C:\\temp"; + + @Before + public void setUp() throws Exception { + } + + @Test + public void test() { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + loader.addClassPath(path2); + + String clzPath = loader.getClassPath(); + + Assert.assertEquals(path1 + ";" + path2, clzPath); + } + + @Test + public void ClassFileLengthTest() throws ClassFileLoaderException { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] bytes = loader.readBinaryCode(className); + + Assert.assertEquals(1056, bytes.length); + } + + @Test + public void MagicNumberTest() throws ClassFileLoaderException { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + + byte[] bytes = { byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3] }; + String actualString = byteToHexString(bytes); + Assert.assertEquals("cafebabe", actualString); + } + + private String byteToHexString(byte[] bytes) { + + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < bytes.length; i++) { + byte b = bytes[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/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" new file mode 100644 index 0000000000..39af3b3d32 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/mini-jvm/com/coderising/jvm/test/EmployeeV1.java" @@ -0,0 +1,32 @@ +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(); + } + +} diff --git "a/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/\346\226\207\347\253\240\351\223\276\346\216\245.txt" "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/\346\226\207\347\253\240\351\223\276\346\216\245.txt" new file mode 100644 index 0000000000..5516f95009 --- /dev/null +++ "b/group20/925290009/\347\254\254\345\233\233\346\254\241\344\275\234\344\270\232/\346\226\207\347\253\240\351\223\276\346\216\245.txt" @@ -0,0 +1 @@ +http://blog.csdn.net/u011371324/article/details/68946779 diff --git a/group24/1148285693/.gitignore b/group24/1148285693/.gitignore index 23f75414d3..f41f37aecb 100644 --- a/group24/1148285693/.gitignore +++ b/group24/1148285693/.gitignore @@ -35,4 +35,6 @@ logs .directory .DS_Store -Test.java \ No newline at end of file + +Test.java +example \ No newline at end of file diff --git a/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/ByteUtils.java b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/ByteUtils.java new file mode 100644 index 0000000000..f6586ce761 --- /dev/null +++ b/group24/1148285693/learning2017/common/src/main/java/me/lzb/common/utils/ByteUtils.java @@ -0,0 +1,26 @@ +package me.lzb.common.utils; + +/** + * Created by LZB on 2017/4/14. + */ +public class ByteUtils { + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i + + me.lzb + common + 1.0 +
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 new file mode 100644 index 0000000000..af897cd58f --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayList.java @@ -0,0 +1,97 @@ +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 new file mode 100644 index 0000000000..eab32c80cc --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/ArrayUtil.java @@ -0,0 +1,337 @@ +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 new file mode 100644 index 0000000000..88395e3010 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/BinaryTreeNode.java @@ -0,0 +1,53 @@ +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/InfixExpr.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java new file mode 100644 index 0000000000..e30cc00cc2 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/InfixExpr.java @@ -0,0 +1,161 @@ +package me.lzb.basic; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * Created by LZB on 2017/4/15. + */ +public class InfixExpr { + + + private String expr; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + List list = processExpr(); + + Stack symbolStack = new Stack<>(); + Stack numberStack = new Stack<>(); + + boolean calLevel2 = false; + for (Node n : list) { + if (n.isNumber) { + numberStack.push(n.number); + if (calLevel2) { + calculate(symbolStack, numberStack, false); + calLevel2 = false; + } + } else { + symbolStack.push(n.symbol); + + if (n.isLevel2()) { + calLevel2 = true; + } + } + } + + + Stack tn = new Stack<>(); + int nsize = numberStack.size(); + for (int i = 0; i < nsize; i++) { + tn.push(numberStack.pop()); + } + + numberStack = tn; + + + Stack ts = new Stack<>(); + int ssize = symbolStack.size(); + for (int i = 0; i < ssize; i++) { + ts.push(symbolStack.pop()); + } + + symbolStack = ts; + + + while (!symbolStack.isEmpty()) { + calculate(symbolStack, numberStack, true); + } + + + return numberStack.pop(); + } + + + + private List processExpr() { + List list = new ArrayList<>(); + char[] array = this.expr.toCharArray(); + String number = ""; + for (int i = 0; i < array.length; i++) { + if (Character.isDigit(array[i])) { + number = number + String.valueOf(array[i]); + } else { + Node num = new Node(Float.valueOf(number), null, true, -1); + number = ""; + int calLevel = "+-".indexOf(array[i]) >= 0 ? 1 : 2; + Node sym = new Node(0, String.valueOf(array[i]), false, calLevel); + list.add(num); + list.add(sym); + } + } + + Node num = new Node(Float.valueOf(number), null, true, -1); + list.add(num); + return list; + } + + + private void calculate(Stack symbolStack, Stack numberStack, boolean isRe) { + if (symbolStack.isEmpty()) { + return; + } + + + String symbole = symbolStack.pop(); + + float right; + float left; + + if(isRe){ + left = numberStack.pop(); + right = numberStack.pop(); + }else { + right = numberStack.pop(); + left = numberStack.pop(); + } + + + + float r = calculate(symbole, left, right); + + numberStack.push(r); + } + + + private float calculate(String symbol, float left, float right) { + if ("+".equals(symbol)) { + return left + right; + } + + if ("-".equals(symbol)) { + return left - right; + } + + if ("*".equals(symbol)) { + return left * right; + } + + if ("/".equals(symbol)) { + return left / right; + } + + return 0; + } + + + private class Node { + float number; + String symbol; + boolean isNumber; + int calLevel;//加减1,乘除2 + + public Node(float number, String symbol, boolean isNumber, int calLevel) { + this.number = number; + this.symbol = symbol; + this.isNumber = isNumber; + this.calLevel = calLevel; + } + + private boolean isLevel2() { + return calLevel == 2; + } + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java new file mode 100644 index 0000000000..86e8cae942 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/Iterator.java @@ -0,0 +1,10 @@ +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/LRUPageFrame.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LRUPageFrame.java new file mode 100644 index 0000000000..6e0e570ce6 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LRUPageFrame.java @@ -0,0 +1,173 @@ +package me.lzb.basic; + +/** + * 用双向链表实现LRU算法 + * @author lzb + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node(Node prev, Node next, int pageNum) { + this.prev = prev; + this.next = next; + this.pageNum = pageNum; + } + } + + private int capacity; + + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + if(capacity < 1){ +// throw new Exception("capacity boom"); + } + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @return + */ + public void access(int pageNum) { + if(capacity == 1){ + first = last = new Node(null, null, pageNum); + return; + } + + + if(first == null){ + first = last = new Node(null, null, pageNum); + return; + } + + if(first.pageNum == pageNum){ + return; + } + + Node tmp = first; + int size = 0; + for (int i = 0; i < capacity; i++) { + size = size + 1; + //如果发现一样的,把这个挪到最前面 + if(tmp.pageNum == pageNum){ + moveToFirst(tmp); + return; + } + //链表已经循环结束,但是个数还没满,更新last + if(tmp.next == null){ + last = tmp; + break; + } + tmp = tmp.next; + } + + + //没有相同的,在最顶端插入 + Node f = new Node(null, first, pageNum); + addAsFirst(f); + + //已经放满,更新last + if(size >= capacity){ + removeLastOne(); + } + + } + + /** + * 删除最后一个节点 + */ + private void removeLastOne(){ + last = last.prev; + //使GC ROOT 不可达 + last.next.prev = null; + last.next = null; + } + + /** + * 把某节点移动到最顶部 + * @param tmp 在链表中的任意节点 + */ + private void moveToFirst(Node tmp){ + if(tmp == first){ + return; + } + + if (tmp.next != null){ + tmp.next.prev = tmp.prev; + tmp.prev.next = tmp.next; + }else { + tmp.prev.next = null; + //当这个节点是last的时候,更新last + last = tmp.prev; + } + + tmp.next = first; + tmp.prev = null; + + first.prev = tmp; + first = tmp; + } + + /** + * 在顶部增加一个节点 + * @param node node + */ + private void addAsFirst(Node node){ + first.prev = node; + first = node; + } + + + + /** + * ASC + * @return + */ + 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(); + } + + + /** + * DESC + * @return + */ + public String toStringDESC(){ + + StringBuilder buffer = new StringBuilder(); + Node node = last; + while(node != null){ + buffer.append(node.pageNum); + + node = node.prev; + if(node != null){ + buffer.append(","); + } + } + return buffer.toString(); + } + +} 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 new file mode 100644 index 0000000000..268b69bf50 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/basic/LinkedList.java @@ -0,0 +1,510 @@ +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/download/DownloadThread.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/DownloadThread.java new file mode 100644 index 0000000000..9db5e9fc86 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/DownloadThread.java @@ -0,0 +1,45 @@ +package me.lzb.download; + +import me.lzb.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() { + + System.out.println("开始读取:" + startPos + "-" + endPos); + + try { + byte[] data = conn.read(startPos, endPos); + RandomAccessFile file = new RandomAccessFile(localFile, "rw"); + file.seek(startPos); + file.write(data); + file.close(); + conn.close(); + barrier.await(); + + } catch (Exception e) { + + } + + + System.out.println("读取结束:" + startPos + "-" + endPos); + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/FileDownloader.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/FileDownloader.java new file mode 100644 index 0000000000..b64ddebd9c --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/FileDownloader.java @@ -0,0 +1,127 @@ +package me.lzb.download; + +import me.lzb.download.api.Connection; +import me.lzb.download.api.ConnectionManager; +import me.lzb.download.api.DownloadListener; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class FileDownloader { + //"https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-499994.png" + String url; + private String localFile; + + + DownloadListener listener; + + ConnectionManager cm; + + private static final int DOWNLOAD_TRHEAD_NUM = 3; + + + 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_TRHEAD_NUM, new Runnable() { + public void run() { + listener.notifyFinished(); + } + }); + + Connection conn = null; + try { + conn = cm.open(this.url); + int length = conn.getContentLength(); + createEmptyFile(localFile, length); + + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); + for (int i = 0; i < DOWNLOAD_TRHEAD_NUM; i++) { + DownloadThread thread = new DownloadThread( + cm.open(url), + ranges[i][0], + ranges[i][1], + localFile, + barrier); + + thread.start(); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + + } + + + } + + + private void createEmptyFile(String fileName, int contentLen) throws IOException { + RandomAccessFile file = new RandomAccessFile(fileName, "rw"); + + for (int i = 0; i < contentLen; i++) { + file.write(0); + } + + file.close(); + } + + + private int[][] allocateDownloadRange(int threadNum, int contentLen) { + int[][] ranges = new int[threadNum][2]; + + int eachThreadSize = contentLen / threadNum;// 每个线程需要下载的文件大小 + + for (int i = 0; i < threadNum; i++) { + + int startPos = i * eachThreadSize; + + int endPos = (i + 1) * eachThreadSize - 1; + + ranges[i][0] = startPos; + ranges[i][1] = endPos; + + } + + //剩下的交给最后一个线程 + int left = contentLen % threadNum; + ranges[threadNum - 1][1] = ranges[threadNum - 1][1] + left; + + 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/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/Connection.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/Connection.java new file mode 100644 index 0000000000..17413ca23b --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/Connection.java @@ -0,0 +1,23 @@ +package me.lzb.download.api; + +import java.io.IOException; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + int getContentLength(); + + /** + * 关闭连接 + */ + void close(); +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionException.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionException.java new file mode 100644 index 0000000000..6c1f4defbe --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionException.java @@ -0,0 +1,9 @@ +package me.lzb.download.api; + +public class ConnectionException extends Exception { + + public ConnectionException(Exception e) { + super(e); + } + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionManager.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionManager.java new file mode 100644 index 0000000000..abec231748 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package me.lzb.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + Connection open(String url) throws ConnectionException; +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/DownloadListener.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/DownloadListener.java new file mode 100644 index 0000000000..3131ec9966 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package me.lzb.download.api; + +public interface DownloadListener { + void notifyFinished(); +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionImpl.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..6fc42341db --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionImpl.java @@ -0,0 +1,92 @@ +package me.lzb.download.impl; + +import me.lzb.download.api.Connection; +import me.lzb.download.api.ConnectionException; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + + +class ConnectionImpl implements Connection { + + + static final int BUFFER_SIZE = 1024; + + HttpGet httpget; + + CloseableHttpClient httpClient; + + + + public ConnectionImpl(String url) throws ConnectionException{ + httpget = new HttpGet(url); + httpget.setHeader("Accept-Encoding", "identity"); + httpClient = HttpClients.createDefault(); + } + + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + + httpget.removeHeaders("Range"); + httpget.addHeader("Range", "bytes=" + startPos + "-" + endPos); + + CloseableHttpResponse response = httpClient.execute(httpget); + InputStream inputStream = response.getEntity().getContent(); + + byte[] buff = new byte[BUFFER_SIZE]; + + int lenth = endPos - startPos + 1; + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while(baos.size() < lenth){ + + int len = inputStream.read(buff); + if (len < 0) { + break; + } + baos.write(buff,0, len); + } + + if(baos.size() > lenth){ + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, lenth); + } + + return baos.toByteArray(); + } + + @Override + public int getContentLength() { + + CloseableHttpResponse response; + try { + response = httpClient.execute(httpget); + } catch (IOException e) { + e.printStackTrace(); + + return -1; + } + + HttpEntity httpEntity = response.getEntity(); + return (int) httpEntity.getContentLength(); + } + + @Override + public void close() { + + } + + + + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionManagerImpl.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..d450f5aa92 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,17 @@ +package me.lzb.download.impl; + + +import me.lzb.download.api.Connection; +import me.lzb.download.api.ConnectionException; +import me.lzb.download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + + +} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/ArrayList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/ArrayList.java deleted file mode 100644 index 6fde63911f..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/ArrayList.java +++ /dev/null @@ -1,97 +0,0 @@ -package me.lzb.homework0312.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/homework0312/basic/BinaryTreeNode.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/BinaryTreeNode.java deleted file mode 100644 index 053baad0d4..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/BinaryTreeNode.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.lzb.homework0312.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/homework0312/basic/Iterator.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/Iterator.java deleted file mode 100644 index 138e090126..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/Iterator.java +++ /dev/null @@ -1,10 +0,0 @@ -package me.lzb.homework0312.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/homework0312/basic/LinkedList.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/LinkedList.java deleted file mode 100644 index e3cd7e9fa1..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0312/basic/LinkedList.java +++ /dev/null @@ -1,510 +0,0 @@ -package me.lzb.homework0312.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= 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/homework0319/litestruts/LoginAction.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0319/litestruts/LoginAction.java deleted file mode 100644 index 4c4ca22187..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0319/litestruts/LoginAction.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.lzb.homework0319.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/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0319/litestruts/Struts.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0319/litestruts/Struts.java deleted file mode 100644 index aea8d1105d..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0319/litestruts/Struts.java +++ /dev/null @@ -1,113 +0,0 @@ -package me.lzb.homework0319.litestruts; - -import org.apache.commons.lang3.StringUtils; -import org.dom4j.DocumentException; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - - -/* - -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字段中。 - -*/ - - -public class Struts { - - private static final String XML = "struts.xml"; - - private static final XmlUtil resource = createResource(XML); - - private static XmlUtil createResource(String xml){ - try { - return new XmlUtil(xml); - } catch (DocumentException e) { - e.printStackTrace(); - } - return null; - } - - - public static View runAction(String actionName, Map parameters) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { - - Object loginAction = getAuctionByName(actionName); - - invokeSetMethods(loginAction, parameters); - - String resultName = invokeExecute(loginAction).toString(); - - View view = new View(); - view.setJsp(resource.getResultJsp(actionName, resultName)); - view.setParameters(invokeGetMethods(loginAction)); - - return view; - } - - private static Object getAuctionByName(String auctionName) throws ClassNotFoundException, IllegalAccessException, InstantiationException { - Class c = Class.forName(resource.getAuctionPathByName(auctionName)); - return c.newInstance(); - } - - - private static Object invokeExecute(Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class c = o.getClass(); - Method mExectue = c.getDeclaredMethod("execute"); - return mExectue.invoke(o); - } - - - private static void invokeSetMethods(Object o, Map parameteMap) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - Class c = o.getClass(); - Method[] methods = c.getDeclaredMethods(); - for (int i = 0; i< methods.length; i++) { - String name = methods[i].getName(); - if(StringUtils.startsWith(name, "set")){ - String key = name.replaceAll("^set", "").toLowerCase(); - if(parameteMap.containsKey(key)){ - methods[i].invoke(o, parameteMap.get(key)); - } - } - } - -// //这样参数类型不固定的话不好搞 -// for (Map.Entry entry : parameteMap.entrySet()) { -// Method mSetter = c.getDeclaredMethod("set" + StringUtils.capitalize(entry.getKey()), String.class); -// mSetter.invoke(o, entry.getValue()); -// } - } - - - private static Map invokeGetMethods(Object o) throws InvocationTargetException, IllegalAccessException { - Map resultMap = new HashMap(); - Class c = o.getClass(); - Method[] methods = c.getDeclaredMethods(); - for(int i =0 ;i lenth){ - byte[] data = baos.toByteArray(); - return Arrays.copyOf(data, lenth); - } - - return baos.toByteArray(); - } - - @Override - public int getContentLength() { - - CloseableHttpResponse response; - try { - response = httpClient.execute(httpget); - } catch (IOException e) { - e.printStackTrace(); - - return -1; - } - - HttpEntity httpEntity = response.getEntity(); - return (int) httpEntity.getContentLength(); - } - - @Override - public void close() { - - } - - - - - -} diff --git a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0326/download/impl/ConnectionManagerImpl.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0326/download/impl/ConnectionManagerImpl.java deleted file mode 100644 index e341546897..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/homework0326/download/impl/ConnectionManagerImpl.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.lzb.homework0326.download.impl; - - -import me.lzb.homework0326.download.api.Connection; -import me.lzb.homework0326.download.api.ConnectionException; -import me.lzb.homework0326.download.api.ConnectionManager; - -public class ConnectionManagerImpl implements ConnectionManager { - - - @Override - public Connection open(String url) throws ConnectionException { - return new ConnectionImpl(url); - } - - -} 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 new file mode 100644 index 0000000000..5ea923c5b4 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package me.lzb.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/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/Struts.java b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/Struts.java new file mode 100644 index 0000000000..7841100872 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/main/java/me/lzb/litestruts/Struts.java @@ -0,0 +1,113 @@ +package me.lzb.litestruts; + +import org.apache.commons.lang3.StringUtils; +import org.dom4j.DocumentException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + + +/* + +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字段中。 + +*/ + + +public class Struts { + + private static final String XML = "struts.xml"; + + private static final XmlUtil resource = createResource(XML); + + private static XmlUtil createResource(String xml){ + try { + return new XmlUtil(xml); + } catch (DocumentException e) { + e.printStackTrace(); + } + return null; + } + + + public static View runAction(String actionName, Map parameters) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { + + Object loginAction = getAuctionByName(actionName); + + invokeSetMethods(loginAction, parameters); + + String resultName = invokeExecute(loginAction).toString(); + + View view = new View(); + view.setJsp(resource.getResultJsp(actionName, resultName)); + view.setParameters(invokeGetMethods(loginAction)); + + return view; + } + + private static Object getAuctionByName(String auctionName) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + Class c = Class.forName(resource.getAuctionPathByName(auctionName)); + return c.newInstance(); + } + + + private static Object invokeExecute(Object o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class c = o.getClass(); + Method mExectue = c.getDeclaredMethod("execute"); + return mExectue.invoke(o); + } + + + private static void invokeSetMethods(Object o, Map parameteMap) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class c = o.getClass(); + Method[] methods = c.getDeclaredMethods(); + for (int i = 0; i< methods.length; i++) { + String name = methods[i].getName(); + if(StringUtils.startsWith(name, "set")){ + String key = name.replaceAll("^set", "").toLowerCase(); + if(parameteMap.containsKey(key)){ + methods[i].invoke(o, parameteMap.get(key)); + } + } + } + +// //这样参数类型不固定的话不好搞 +// for (Map.Entry entry : parameteMap.entrySet()) { +// Method mSetter = c.getDeclaredMethod("set" + StringUtils.capitalize(entry.getKey()), String.class); +// mSetter.invoke(o, entry.getValue()); +// } + } + + + private static Map invokeGetMethods(Object o) throws InvocationTargetException, IllegalAccessException { + Map resultMap = new HashMap(); + Class c = o.getClass(); + Method[] methods = c.getDeclaredMethods(); + for(int i =0 ;i - + /jsp/homepage.jsp /jsp/showLogin.jsp - + /jsp/welcome.jsp /jsp/error.jsp 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 new file mode 100644 index 0000000000..efcfdbae1d --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/ArrayListTest.java @@ -0,0 +1,107 @@ +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/InfixExprTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/InfixExprTest.java new file mode 100644 index 0000000000..5ca7621354 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/InfixExprTest.java @@ -0,0 +1,48 @@ +package me.lzb.basic; + +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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LRUPageFrameTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LRUPageFrameTest.java new file mode 100644 index 0000000000..828eab0881 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LRUPageFrameTest.java @@ -0,0 +1,42 @@ +package me.lzb.basic; + +import me.lzb.basic.LRUPageFrame; +import org.junit.Assert; +import org.junit.Test; + + +public class LRUPageFrameTest { + + @Test + public void testAccess() { + LRUPageFrame frame = new LRUPageFrame(3); + frame.access(7); + Assert.assertEquals("7", frame.toString()); + Assert.assertEquals("7", frame.toStringDESC()); + frame.access(0); + Assert.assertEquals("0,7", frame.toString()); + Assert.assertEquals("7,0", frame.toStringDESC()); + frame.access(1); + Assert.assertEquals("1,0,7", frame.toString()); + Assert.assertEquals("7,0,1", frame.toStringDESC()); + frame.access(2); + Assert.assertEquals("2,1,0", frame.toString()); + Assert.assertEquals("0,1,2", frame.toStringDESC()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + Assert.assertEquals("1,2,0", frame.toStringDESC()); + frame.access(0); + Assert.assertEquals("0,2,1", frame.toString()); + Assert.assertEquals("1,2,0", frame.toStringDESC()); + frame.access(3); + Assert.assertEquals("3,0,2", frame.toString()); + Assert.assertEquals("2,0,3", frame.toStringDESC()); + frame.access(0); + Assert.assertEquals("0,3,2", frame.toString()); + Assert.assertEquals("2,3,0", frame.toStringDESC()); + frame.access(4); + Assert.assertEquals("4,0,3", frame.toString()); + Assert.assertEquals("3,0,4", frame.toStringDESC()); + } + +} 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 new file mode 100644 index 0000000000..6f02328060 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/LinkedListTest.java @@ -0,0 +1,260 @@ +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 new file mode 100644 index 0000000000..48589f57d3 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/basic/StackUtilTest.java @@ -0,0 +1,78 @@ +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/download/ConnectionTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/download/ConnectionTest.java new file mode 100644 index 0000000000..884c309765 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/download/ConnectionTest.java @@ -0,0 +1,57 @@ +package me.lzb.download; + +import me.lzb.download.api.Connection; +import me.lzb.download.api.ConnectionManager; +import me.lzb.download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by LZB on 2017/3/27. + */ +public class ConnectionTest { + + private static final String imageUrl = "https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-499994.png"; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testContentLength() throws Exception{ + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open(imageUrl); + Assert.assertEquals(3440179, conn.getContentLength()); + conn.close(); + } + + @Test + public void testRead() throws Exception{ + + ConnectionManager connMan = new ConnectionManagerImpl(); + Connection conn = connMan.open(imageUrl); + + byte[] data = conn.read(0, 35469); + + Assert.assertEquals(35470, data.length); + + data = conn.read(0, 1023); + + Assert.assertEquals(1024, data.length); + + //TODO 这个地方会一直卡住不执行 + data = conn.read(1024, 2023); + + Assert.assertEquals(1000, data.length); + + + // 测试不充分,没有断言内容是否正确 + } +} diff --git a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/download/FileDownloaderTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/download/FileDownloaderTest.java new file mode 100644 index 0000000000..76c3edf432 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/download/FileDownloaderTest.java @@ -0,0 +1,60 @@ +package me.lzb.download; + +import me.lzb.download.api.ConnectionManager; +import me.lzb.download.api.DownloadListener; +import me.lzb.download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class FileDownloaderTest { + + private static final String imageUrl = "https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-499994.png"; + + boolean downloadFinished = false; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testDownload() { + + + FileDownloader downloader = new FileDownloader(imageUrl, "D:\\code\\learning\\tmp\\test.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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0312/basic/ArrayListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0312/basic/ArrayListTest.java deleted file mode 100644 index 4938e6a8ac..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0312/basic/ArrayListTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package me.lzb.homework0312.basic; - -import me.lzb.homework0312.basic.ArrayList; -import me.lzb.homework0312.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/homework0312/basic/LinkedListTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0312/basic/LinkedListTest.java deleted file mode 100644 index ef0e043a11..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0312/basic/LinkedListTest.java +++ /dev/null @@ -1,258 +0,0 @@ -package me.lzb.homework0312.basic; - -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/homework0319/litestruts/StrutsTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0319/litestruts/StrutsTest.java deleted file mode 100644 index 027c33eba9..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0319/litestruts/StrutsTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.lzb.homework0319.litestruts; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - - - -public class StrutsTest { - - @Test - public void testLoginActionSuccess() throws Exception{ - - 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() throws Exception{ - 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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/ConnectionTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/ConnectionTest.java deleted file mode 100644 index 10eb296623..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/ConnectionTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.lzb.homework0326.download; - -import me.lzb.homework0326.download.api.Connection; -import me.lzb.homework0326.download.api.ConnectionManager; -import me.lzb.homework0326.download.impl.ConnectionManagerImpl; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by LZB on 2017/3/27. - */ -public class ConnectionTest { - - private static final String imageUrl = "https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-499994.png"; - - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testContentLength() throws Exception{ - ConnectionManager connMan = new ConnectionManagerImpl(); - Connection conn = connMan.open(imageUrl); - Assert.assertEquals(35470, conn.getContentLength()); - } - - @Test - public void testRead() throws Exception{ - - ConnectionManager connMan = new ConnectionManagerImpl(); - Connection conn = connMan.open(imageUrl); - - byte[] data = conn.read(0, 35469); - - 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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/FileDownloaderTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/FileDownloaderTest.java deleted file mode 100644 index c1c459184f..0000000000 --- a/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/homework0326/download/FileDownloaderTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package me.lzb.homework0326.download; - -import me.lzb.homework0326.download.api.ConnectionManager; -import me.lzb.homework0326.download.api.DownloadListener; -import me.lzb.homework0326.download.impl.ConnectionManagerImpl; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class FileDownloaderTest { - - private static final String imageUrl = "https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-499994.png"; - - boolean downloadFinished = false; - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - @Test - public void testDownload() { - - - FileDownloader downloader = new FileDownloader(imageUrl, "D:\\code\\learning\\tmp\\test.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/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/litestruts/StrutsTest.java b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/litestruts/StrutsTest.java new file mode 100644 index 0000000000..a970d742b4 --- /dev/null +++ b/group24/1148285693/learning2017/learning-basic/src/test/java/me/lzb/litestruts/StrutsTest.java @@ -0,0 +1,41 @@ +package me.lzb.litestruts; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + + + +public class StrutsTest { + + @Test + public void testLoginActionSuccess() throws Exception{ + + 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() throws Exception{ + 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/group24/1148285693/learning2017/learning-basic/src/test/resources/litestruts/struts.xml b/group24/1148285693/learning2017/learning-basic/src/test/resources/litestruts/struts.xml index 81c153757c..a4859a04b2 100644 --- a/group24/1148285693/learning2017/learning-basic/src/test/resources/litestruts/struts.xml +++ b/group24/1148285693/learning2017/learning-basic/src/test/resources/litestruts/struts.xml @@ -1,10 +1,10 @@ - + /jsp/homepage.jsp /jsp/showLogin.jsp - + /jsp/welcome.jsp /jsp/error.jsp diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/AttributeInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..fd000bdcb3 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/AttributeInfo.java @@ -0,0 +1,22 @@ +package me.lzb.jvm.attr; + +/** + * Created by LZB on 2017/4/15. + */ +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/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..2addebeb39 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/CodeAttr.java @@ -0,0 +1,52 @@ +package me.lzb.jvm.attr; + +/** + * Created by LZB on 2017/4/15. + */ +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; + + 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 getCode() { + return code; + } + + public LineNumberTable getLineNumTable() { + return lineNumTable; + } + + public void setLineNumTable(LineNumberTable lineNumTable) { + this.lineNumTable = lineNumTable; + } + + public LocalVariableTable getLocalVarTable() { + return localVarTable; + } + + public void setLocalVarTable(LocalVariableTable localVarTable) { + this.localVarTable = localVarTable; + } + + public StackMapTable getStackMapTable() { + return stackMapTable; + } + + public void setStackMapTable(StackMapTable stackMapTable) { + this.stackMapTable = stackMapTable; + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberItem.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberItem.java new file mode 100644 index 0000000000..e621cf925a --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberItem.java @@ -0,0 +1,31 @@ +package me.lzb.jvm.attr; + +/** + * Created by LZB on 2017/4/16. + */ +public 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; +// } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberTable.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..5bf7b4759b --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LineNumberTable.java @@ -0,0 +1,23 @@ +package me.lzb.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LZB on 2017/4/15. + */ +public class LineNumberTable extends AttributeInfo { + List items = new ArrayList<>(); + + + public void addLineNumberItem(LineNumberItem item) { + this.items.add(item); + } + + public LineNumberTable(int attrNameIndex, int attrLen) { + super(attrNameIndex, attrLen); + + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableItem.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..decef772a3 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableItem.java @@ -0,0 +1,62 @@ +package me.lzb.jvm.attr; + +/** + * Created by LZB on 2017/4/15. + */ +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){ + 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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableTable.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..9dca129d71 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/LocalVariableTable.java @@ -0,0 +1,20 @@ +package me.lzb.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LZB on 2017/4/15. + */ +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); + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/StackMapTable.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..0b8947bdf8 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/attr/StackMapTable.java @@ -0,0 +1,15 @@ +package me.lzb.jvm.attr; + +/** + * Created by LZB on 2017/4/15. + */ +public class StackMapTable extends AttributeInfo { + private String originalCode; + + public StackMapTable(int attrNameIndex, int attrLen, String code) { + super(attrNameIndex, attrLen); + this.originalCode = code; + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..224714a010 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/AccessFlag.java @@ -0,0 +1,29 @@ +package me.lzb.jvm.clz; + +/** + * Created by LZB on 2017/4/14. + */ +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/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 new file mode 100644 index 0000000000..c5de9be5ce --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassFile.java @@ -0,0 +1,131 @@ +package me.lzb.jvm.clz; + +import me.lzb.jvm.constant.ConstantPool; +import me.lzb.jvm.field.Field; +import me.lzb.jvm.method.Method; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LZB on 2017/4/14. + */ +public class ClassFile { + + private String magicNumber; + + private int minorVersion; + + private int majorVersion; + + private AccessFlag accessFlag; + + private ClassIndex clzIndex; + + + private ConstantPool constantPool; + + private List fields = new ArrayList<>(); + + private List methods = new ArrayList<>(); + + + public String getMagicNumber() { + return magicNumber; + } + + public void setMagicNumber(String magicNumber) { + this.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 AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + + + + 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 void setClzIndex(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 int getConstantPoolCount() { + return constantPool.getSize(); + } + + public void addField(Field f){ + this.fields.add(f); + } + + public void addMethod(Method m){ + this.methods.add(m); + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassIndex.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..8916290057 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/clz/ClassIndex.java @@ -0,0 +1,25 @@ +package me.lzb.jvm.clz; + +/** + * Created by LZB on 2017/4/14. + */ +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/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..200e59834a --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ClassInfo.java @@ -0,0 +1,33 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/14. + */ +public class ClassInfo extends ConstantInfo{ + private int type = ConstantInfo.Class_info; + private int utf8Index; + + public ClassInfo(ConstantPool pool) { + super(pool); + } + + @Override + public int getType() { + return type; + } + + public int getUtf8Index() { + return utf8Index; + } + + public void setUtf8Index(int utf8Index) { + this.utf8Index = utf8Index; + } + + + public String getClassName() { + int index = getUtf8Index(); + UTF8Info utf8Info = (UTF8Info)constantPool.getConstantInfo(index); + return utf8Info.getValue(); + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..3bbabf2180 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantInfo.java @@ -0,0 +1,44 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/14. + */ +public abstract class ConstantInfo { + + public static final String MAGIC_NUMBER = "cafebabe"; + + public static final int Class_info = 7; + + public static final int Fieldref_info = 9; + + public static final int Methodref_info = 10; + + public static final int String_info = 8; + + public static final int NameAndType_info = 12; + + public static final int Utf8_info = 1; + + + + protected ConstantPool constantPool; + + + public ConstantInfo(){ + + } + + public ConstantInfo(ConstantPool pool) { + this.constantPool = pool; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + + + public abstract int getType(); +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantPool.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..d78f0a71f4 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/ConstantPool.java @@ -0,0 +1,32 @@ +package me.lzb.jvm.constant; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LZB on 2017/4/14. + */ +public class ConstantPool { + + private List constantInfoList = new ArrayList<>(); + + + + public void addConstantInfo(ConstantInfo constantInfo){ + constantInfoList.add(constantInfo); + } + + + public int getSize(){ + return constantInfoList.size() > 1 ? constantInfoList.size() - 1 : 0; + } + + public ConstantInfo getConstantInfo(int index){ + return constantInfoList.get(index); + } + + public String getUTF8String(int index){ + return ((UTF8Info)this.constantInfoList.get(index)).getValue(); + } + +} 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 new file mode 100644 index 0000000000..0ebab33b39 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/FieldRefInfo.java @@ -0,0 +1,35 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/15. + */ +public class FieldRefInfo extends ConstantInfo{ + private int type = ConstantInfo.Fieldref_info; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool pool) { + super(pool); + } + @Override + 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; + } +} 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 new file mode 100644 index 0000000000..263c185af5 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/MethodRefInfo.java @@ -0,0 +1,36 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/15. + */ +public class MethodRefInfo extends ConstantInfo { + private int type = ConstantInfo.Methodref_info; + + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + @Override + 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; + } +} 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 new file mode 100644 index 0000000000..bdf158ec37 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,36 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/15. + */ +public class NameAndTypeInfo extends ConstantInfo { + private int type = ConstantInfo.NameAndType_info; + + private int index1; + private int index2; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + @Override + 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; + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..7f9debba3b --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/NullConstantInfo.java @@ -0,0 +1,12 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/14. + */ +public class NullConstantInfo extends ConstantInfo{ + + @Override + public int getType() { + return -1; + } +} 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 new file mode 100644 index 0000000000..8ba36d8cfc --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/15. + */ +public class StringInfo extends ConstantInfo { + private int type = ConstantInfo.String_info; + + private int index; + + public StringInfo(ConstantPool pool) { + super(pool); + } + @Override + public int getType() { + return type; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..d3f35c2fd7 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/constant/UTF8Info.java @@ -0,0 +1,38 @@ +package me.lzb.jvm.constant; + +/** + * Created by LZB on 2017/4/15. + */ +public class UTF8Info extends ConstantInfo { + private int type = ConstantInfo.Class_info; + + private String value; + + private int length; + + public UTF8Info(ConstantPool pool) { + super(pool); + } + + + @Override + public int getType() { + return type; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/field/Field.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/field/Field.java new file mode 100644 index 0000000000..f388fd01bf --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/field/Field.java @@ -0,0 +1,30 @@ +package me.lzb.jvm.field; + +import me.lzb.jvm.constant.ConstantPool; + +/** + * Created by LZB on 2017/4/15. + */ +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; + } + + + @Override + public String toString() { + String key = pool.getUTF8String(nameIndex); + String value = pool.getUTF8String(descriptorIndex); + return key + ":" + value; + } +} 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 new file mode 100644 index 0000000000..593694066d --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileLoader.java @@ -0,0 +1,56 @@ +package me.lzb.jvm.loader; + + +import me.lzb.common.utils.FileUtils; +import me.lzb.jvm.clz.ClassFile; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + +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); + if (data != null) { + return data; + } + } + + throw new IOException(className + "is not exist"); + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + public String getClassPath() { + StringBuilder buffer = new StringBuilder(); + for (Iterator iterator = clzPaths.iterator(); iterator.hasNext(); ) { + buffer.append(iterator.next() + (iterator.hasNext() ? ";" : "")); + } + return buffer.toString(); + } + + + public ClassFile loadClass(String className) throws IOException { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(codes); + return parser.parse(); + } + + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..bfd3cbc2c0 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/loader/ClassFileParser.java @@ -0,0 +1,331 @@ +package me.lzb.jvm.loader; + +import me.lzb.common.utils.ByteUtils; +import me.lzb.common.utils.StringUtils; +import me.lzb.jvm.attr.*; +import me.lzb.jvm.clz.AccessFlag; +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.clz.ClassIndex; +import me.lzb.jvm.constant.*; +import me.lzb.jvm.field.Field; +import me.lzb.jvm.method.Method; + +import java.io.UnsupportedEncodingException; + +/** + * 处理字class文件字节流 + * Created by LZB on 2017/4/14. + */ +public class ClassFileParser { + + + private final byte[] data; + + private int index; + + public ClassFileParser(byte[] data) { + this.data = data; + } + + + public ClassFile parse() { + ClassFile classFile = new ClassFile(); + parserMagicNumber(classFile); + + if (!StringUtils.equals(classFile.getMagicNumber(), ConstantInfo.MAGIC_NUMBER)) { + throw new RuntimeException("It is not a java class file."); + } + + parserVersion(classFile); + + parserConstantPool(classFile); + + parserAccessFlag(classFile); + + parserClassIndex(classFile); + + parserInterface(classFile); + + parserField(classFile); + + parserMethod(classFile); + + return classFile; + } + + + private byte[] nextBytes(int nextLength) { + byte[] target = new byte[nextLength]; + System.arraycopy(data, index, target, 0, nextLength); + index = index + nextLength; + return target; + } + + private int nextBytesToInt(int nextLength) { + return ByteUtils.byteToInt(nextBytes(nextLength)); + } + + private String nextBytesToString(int nextLength) { + return ByteUtils.byteToHexString(nextBytes(nextLength)); + } + + + private void parserMagicNumber(ClassFile classFile) { + this.index = 0; + classFile.setMagicNumber(nextBytesToString(4)); + } + + private void parserVersion(ClassFile classFile) { + classFile.setMinorVersion(nextBytesToInt(2)); + classFile.setMajorVersion(nextBytesToInt(2)); + } + + private void parserConstantPool(ClassFile classFile) { + int count = nextBytesToInt(2); + + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + + for (int i = 1; i < count; i++) { + + int tag = nextBytesToInt(1); + + if (tag == ConstantInfo.Class_info) { + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(nextBytesToInt(2)); + + pool.addConstantInfo(classInfo); + continue; + } + + if (tag == ConstantInfo.Fieldref_info) { + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(nextBytesToInt(2)); + fieldRefInfo.setNameAndTypeIndex(nextBytesToInt(2)); + + pool.addConstantInfo(fieldRefInfo); + continue; + } + + if (tag == ConstantInfo.Methodref_info) { + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(nextBytesToInt(2)); + methodRefInfo.setNameAndTypeIndex(nextBytesToInt(2)); + + pool.addConstantInfo(methodRefInfo); + continue; + } + + if (tag == ConstantInfo.NameAndType_info) { + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setIndex1(nextBytesToInt(2)); + nameAndTypeInfo.setIndex2(nextBytesToInt(2)); + + pool.addConstantInfo(nameAndTypeInfo); + continue; + } + + if (tag == ConstantInfo.String_info) { + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(nextBytesToInt(2)); + + pool.addConstantInfo(stringInfo); + continue; + } + + if (tag == ConstantInfo.Utf8_info) { + UTF8Info utf8Info = new UTF8Info(pool); + int len = nextBytesToInt(2); + byte[] data = nextBytes(len); + String value = null; + try { + value = new String(data, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + utf8Info.setLength(len); + utf8Info.setValue(value); + + pool.addConstantInfo(utf8Info); + continue; + } + + + throw new RuntimeException("the constant pool tag " + tag + " has not been implemented yet." + i); + } + + + classFile.setConstantPool(pool); + } + + + private void parserAccessFlag(ClassFile classFile) { + AccessFlag flag = new AccessFlag(nextBytesToInt(2)); + classFile.setAccessFlag(flag); + } + + + private void parserClassIndex(ClassFile classFile) { + ClassIndex clzIndex = new ClassIndex(); + + int thisClassIndex = nextBytesToInt(2); + int superClassIndex = nextBytesToInt(2); + clzIndex.setThisClassIndex(thisClassIndex); + clzIndex.setSuperClassIndex(superClassIndex); + + classFile.setClzIndex(clzIndex); + } + + private void parserInterface(ClassFile classFile) { + int count = nextBytesToInt(2); + //TODO 实现interface + } + + + private void parserField(ClassFile classFile) { + int count = nextBytesToInt(2); + for (int i = 1; i <= count; i++) { + int accessFlags = nextBytesToInt(2); + int nameIndex = nextBytesToInt(2); + int descriptorIndex = nextBytesToInt(2); + int attributesCount = nextBytesToInt(2); + + if (attributesCount > 0) { + throw new RuntimeException("Field Attribute has not been implement"); + } + + Field field = new Field(accessFlags, nameIndex, descriptorIndex, classFile.getConstantPool()); + classFile.addField(field); + } + } + + private void parserMethod(ClassFile classFile) { + int count = nextBytesToInt(2); + for (int i = 1; i <= count; i++) { + int accessFlags = nextBytesToInt(2); + int nameIndex = nextBytesToInt(2); + int descriptorIndex = nextBytesToInt(2); + int attributesCount = nextBytesToInt(2); + + + Method method = new Method(accessFlags, nameIndex, descriptorIndex); + + + for (int j = 1; j <= attributesCount; j++) { + + int attributeNameIndex = nextBytesToInt(2); + + String attributeName = classFile.getConstantPool().getUTF8String(attributeNameIndex); + + if (StringUtils.equalsIgnoreCase(attributeName, AttributeInfo.CODE)) { + parserCodeAttr(attributeNameIndex, method, classFile); + continue; + } + + + throw new RuntimeException("only CODE attribute is implemented."); + } + + classFile.addMethod(method); + + } + } + + + private void parserCodeAttr(int attributeNameIndex, Method method, ClassFile classFile) { + int attributeLength = nextBytesToInt(4); + int maxStack = nextBytesToInt(2); + int maxLocals = nextBytesToInt(2); + int codeLength = nextBytesToInt(4); + + String code = nextBytesToString(codeLength); + CodeAttr codeAttr = new CodeAttr(attributeNameIndex, attributeLength, maxStack, maxLocals, codeLength, code); + + int exceptionTableLength = nextBytesToInt(2); + if (exceptionTableLength > 0) { + String exceptionTable = nextBytesToString(exceptionTableLength); + //TODO 异常 + } + + + int subAttrCount = nextBytesToInt(2); + for (int k = 1; k <= subAttrCount; k++) { + int subAttrIndex = nextBytesToInt(2); + + String subAttrName = classFile.getConstantPool().getUTF8String(subAttrIndex); + + if (StringUtils.equalsIgnoreCase(subAttrName, AttributeInfo.LINE_NUM_TABLE)) { + + parserLineNumberTable(codeAttr, subAttrIndex); + continue; + } + + if (StringUtils.equalsIgnoreCase(subAttrName, AttributeInfo.LOCAL_VAR_TABLE)) { + parserLocalVariableTable(codeAttr, subAttrIndex); + continue; + } + + if (StringUtils.equalsIgnoreCase(subAttrName, AttributeInfo.STACK_MAP_TABLE)) { + parserStackMapTable(codeAttr, subAttrIndex); + continue; + } + + + throw new RuntimeException("Need code to process" + subAttrName); + } + + + method.setCodeAttr(codeAttr); + } + + + private void parserLineNumberTable(CodeAttr codeAttr, int attributeNameIndex) { +// int attributeNameIndex = nextBytesToInt(2); + int attributeLength = nextBytesToInt(4); + + int lineNumberTableLength = nextBytesToInt(2); + + LineNumberTable table = new LineNumberTable(attributeNameIndex, attributeLength); + + for (int l = 1; l <= lineNumberTableLength; l++) { + int startPc = nextBytesToInt(2); + int lineNumber = nextBytesToInt(2); + LineNumberItem item = new LineNumberItem(startPc, lineNumber); + table.addLineNumberItem(item); + } + + codeAttr.setLineNumTable(table); + } + + + private void parserLocalVariableTable(CodeAttr codeAttr, int attributeNameIndex) { +// int attributeNameIndex = nextBytesToInt(2); + int attributeLength = nextBytesToInt(4); + + int localVariableTableLength = nextBytesToInt(2); + + LocalVariableTable table = new LocalVariableTable(attributeNameIndex, attributeLength); + + for (int l = 1; l <= localVariableTableLength; l++) { + int startPc = nextBytesToInt(2); + int lineNumber = nextBytesToInt(2); + int nameIndex = nextBytesToInt(2); + int descriptorIndex = nextBytesToInt(2); + int index = nextBytesToInt(2); + LocalVariableItem item = new LocalVariableItem(startPc, lineNumber, nameIndex, descriptorIndex, index); + table.addLocalVariableItem(item); + } + + codeAttr.setLocalVarTable(table); + } + + private void parserStackMapTable(CodeAttr codeAttr, int attributeNameIndex) { +// int attributeNameIndex = nextBytesToInt(2); + int attributeLength = nextBytesToInt(4); + String code = nextBytesToString(attributeLength); + StackMapTable table = new StackMapTable(attributeNameIndex, attributeLength, code); + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + codeAttr.setStackMapTable(table); + } + +} 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 new file mode 100644 index 0000000000..9c3e9ad984 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/main/java/me/lzb/jvm/method/Method.java @@ -0,0 +1,65 @@ +package me.lzb.jvm.method; + +import me.lzb.jvm.attr.CodeAttr; + +/** + * Created by LZB on 2017/4/15. + */ +public class Method { + private int accessFlag; + private int nameIndex; + private int descriptorIndex; + + private CodeAttr codeAttr; + +// private ClassFile clzFile; + + + public Method(/*ClassFile clzFile,*/ int accessFlag, int nameIndex, int descriptorIndex) { +// this.clzFile = clzFile; + this.accessFlag = accessFlag; + this.nameIndex = nameIndex; + this.descriptorIndex = descriptorIndex; + } + + + 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; + } + +// public ClassFile getClzFile() { +// return clzFile; +// } +// +// public void setClzFile(ClassFile clzFile) { +// this.clzFile = clzFile; +// } +} 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 new file mode 100644 index 0000000000..f41b313c97 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/ClassFileloaderTest.java @@ -0,0 +1,269 @@ +package me.lzb.jvm; + +import me.lzb.common.utils.ByteUtils; +import me.lzb.jvm.clz.ClassFile; +import me.lzb.jvm.clz.ClassIndex; +import me.lzb.jvm.constant.*; +import me.lzb.jvm.field.Field; +import me.lzb.jvm.loader.ClassFileLoader; +import me.lzb.jvm.method.Method; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + + +public class ClassFileloaderTest { + + + static String path1 = EmployeeV1.class.getResource("/").getPath(); +// static String path1 = "D:\\code\\learning\\coding2017\\group24\\1148285693\\learning2017\\mini-jvm\\target\\test-classes\\"; + static String path2 = "C:\\temp"; + + static String className = "me.lzb.jvm.EmployeeV1"; + + private static final String FULL_QUALIFIED_CLASS_NAME = "me/lzb/jvm/EmployeeV1"; +// private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testPath() { + + String s = EmployeeV1.class.getResource("/").getPath(); + String s2 = EmployeeV1.class.getResource("").getPath(); + System.out.println(s); + System.out.println(s2); + + } + + + @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() throws Exception { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + + byte[] byteCodes = loader.readBinaryCode(className); + + Assert.assertEquals(1030, byteCodes.length); + + } + + + @Test + public void testMagicNumber() throws Exception { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + byte[] byteCodes = loader.readBinaryCode(className); + byte[] codes = new byte[]{byteCodes[0], byteCodes[1], byteCodes[2], byteCodes[3]}; + + String acctualValue = ByteUtils.byteToHexString(codes); + + Assert.assertEquals("cafebabe", acctualValue); + } + + + static ClassFile clzFile = null; + + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + try { + clzFile = loader.loadClass(className); + } catch (IOException e) { + e.printStackTrace(); + } + clzFile.print(); + } + + + @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(7); + Assert.assertEquals(44, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(44); + Assert.assertEquals(FULL_QUALIFIED_CLASS_NAME, utf8Info.getValue()); + } + { + ClassInfo clzInfo = (ClassInfo) pool.getConstantInfo(11); + Assert.assertEquals(48, clzInfo.getUtf8Index()); + + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(48); + Assert.assertEquals("java/lang/Object", utf8Info.getValue()); + } + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(12); + Assert.assertEquals("name", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(13); + Assert.assertEquals("Ljava/lang/String;", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(14); + Assert.assertEquals("age", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(15); + Assert.assertEquals("I", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(16); + Assert.assertEquals("", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(17); + Assert.assertEquals("(Ljava/lang/String;I)V", utf8Info.getValue()); + + utf8Info = (UTF8Info) pool.getConstantInfo(18); + Assert.assertEquals("Code", utf8Info.getValue()); + } + + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(1); + Assert.assertEquals(11, methodRef.getClassInfoIndex()); + Assert.assertEquals(36, methodRef.getNameAndTypeIndex()); + } + + { + NameAndTypeInfo nameAndType = (NameAndTypeInfo) pool.getConstantInfo(36); + Assert.assertEquals(16, nameAndType.getIndex1()); + Assert.assertEquals(28, nameAndType.getIndex2()); + } + //抽查几个吧 + { + MethodRefInfo methodRef = (MethodRefInfo) pool.getConstantInfo(10); + Assert.assertEquals(7, methodRef.getClassInfoIndex()); + Assert.assertEquals(47, methodRef.getNameAndTypeIndex()); + } + + { + UTF8Info utf8Info = (UTF8Info) pool.getConstantInfo(35); + 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", + "2ab700012a2bb500022a1cb50003b1"); + + } + { + Method m = methods.get(1); + assertMethodEquals(pool, m, + "setName", + "(Ljava/lang/String;)V", + "2a2bb50002b1"); + + } + { + Method m = methods.get(2); + assertMethodEquals(pool, m, + "setAge", + "(I)V", + "2a1bb50003b1"); + } + { + Method m = methods.get(3); + assertMethodEquals(pool, m, + "sayHello", + "()V", + "b200041205b60006b1"); + + } + { + Method m = methods.get(4); + assertMethodEquals(pool, m, + "main", + "([Ljava/lang/String;)V", + "bb0007591208101db700094c2bb6000ab1"); + } + } + + 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); + } + +} diff --git a/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/EmployeeV1.java b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/EmployeeV1.java new file mode 100644 index 0000000000..3fa9b0fc85 --- /dev/null +++ b/group24/1148285693/learning2017/mini-jvm/src/test/java/me/lzb/jvm/EmployeeV1.java @@ -0,0 +1,27 @@ +package me.lzb.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/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 new file mode 100644 index 0000000000..5ef6aba81a --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/graph/Graph.java @@ -0,0 +1,366 @@ +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 new file mode 100644 index 0000000000..4b8b3d4ce8 --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest1.java @@ -0,0 +1,27 @@ +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 new file mode 100644 index 0000000000..c630ea9e33 --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/lock/ReentrantTest2.java @@ -0,0 +1,35 @@ +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 new file mode 100644 index 0000000000..d89298c786 --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/MyInvocationHandler.java @@ -0,0 +1,52 @@ +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 new file mode 100644 index 0000000000..d57431acab --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserService.java @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000000..614b60d9c9 --- /dev/null +++ b/group24/1148285693/learning2017/other/src/main/java/me/lzb/other/proxy/UserServiceImpl.java @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000000..0a01679ad3 --- /dev/null +++ b/group24/1148285693/learning2017/other/src/test/java/me/lzb/other/proxy/ProxyTest.java @@ -0,0 +1,25 @@ +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 29ff362b6f..8dc41781ba 100644 --- a/group24/1148285693/learning2017/pom.xml +++ b/group24/1148285693/learning2017/pom.xml @@ -22,7 +22,10 @@ + common learning-basic + mini-jvm + other @@ -101,6 +104,11 @@ commons-codec 1.10 + + org.apache.commons + commons-collections4 + 4.1 + diff --git a/group24/121111914/.classpath b/group24/121111914/.classpath new file mode 100644 index 0000000000..3e9442280c --- /dev/null +++ b/group24/121111914/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/group24/121111914/.project b/group24/121111914/.project new file mode 100644 index 0000000000..5fb6378a67 --- /dev/null +++ b/group24/121111914/.project @@ -0,0 +1,17 @@ + + + JavaImp2017 + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/LinkedList.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/LinkedList.java deleted file mode 100644 index 7afb0e5500..0000000000 --- a/group24/121111914/src/com/github/ipk2015/coding2017/basic/LinkedList.java +++ /dev/null @@ -1,442 +0,0 @@ -package com.github.ipk2015.coding2017.basic; - -import java.util.NoSuchElementException; - -public class LinkedList implements List { - - private Node head; - - public void add(Object o){ - if(null==head){ - head=new Node(); - head.data=o; - }else{ - Node node=head; - while(null!=node.next){ - node=node.next; - } - Node addNode=new Node(); - addNode.data=o; - node.next=addNode; - } - } - public void add(int index , Object o){ - int size=size(); - ListUtils.checkIndexInRange(index, size); - if(index==size){ - add(o); - }else{ - if(size==0){ - head=new Node(); - head.data=o; - }else{ - Node node=head; - Node addNode=new Node(); - addNode.data=o; - for(int i=0;i7->10 , 逆置后变为 10->7->3 - */ - public void reverse(){ - if(null==head){ - return; - } - Node tempNode=new Node(); - Node currentNode=head.next; - head.next=null; - while(null!=currentNode){ - tempNode=currentNode.next; - currentNode.next=head; - head=currentNode; - currentNode=tempNode; - } - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - - */ - public void removeFirstHalf(){ - if(null==head){ - return; - } - Node tempNode; - int size=size(); - size=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[] array=new int[list.size()]; - Iterator iterator = list.iterator(); - int temp=0,next=0,size=0,oriSize=size(); - Node tempNode=head; - while(iterator.hasNext()){ - next = (Integer) iterator.next(); - if(next>=oriSize){ - break; - } - temp=next-temp; - for(int i=0;inext){ - continue; - } - if(currentNode==head){ - head=head.next; - }else{ - preNode.next=currentNode.next; - } - tempNode=currentNode; - currentNode=currentNode.next; - tempNode.next=null; - if(null==currentNode){ - break; - } - tempData=(Integer)currentNode.data; - } - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues(){ - Node currentNode=head; - Node tempNode=head; - int tempData; - while(null!=currentNode && null!=currentNode.next){ - tempData=(Integer)currentNode.data; - if(tempData==(Integer)currentNode.next.data){ - if(null!=currentNode.next.next){ - tempNode=currentNode.next; - currentNode.next=currentNode.next.next; - tempNode.next=null; - }else{ - currentNode.next=null; - } - }else{ - currentNode=currentNode.next; - } - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于等于min且小于等于max的元素(若表中存在这样的元素) - * @param min - * @param max - */ - public void removeRange(int min, int max){ - if(null==head){ - return; - } - int size=size(); - int headData=(Integer)head.data; - int endData=(Integer)get(size-1); - if(headData>=min && endData<=max){ - head=null; - return; - } - if(headData>max || endData=arm){ - return beginIndex; - } - tempData=(Integer)get(endIndex); - if(tempData<=arm){ - return endIndex; - } - int middleIndex=0; - while(beginIndexarm){ - endIndex=middleIndex; - }else{ - break; - } - } - return middleIndex; - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * @param list - */ - public LinkedList rsection( LinkedList list){ - LinkedList armList=new LinkedList(); - Node tempNode=head; - if(null==list || list.size()==0){ - while(null!=tempNode){ - armList.add(tempNode.data); - tempNode=tempNode.next; - } - }else{ - Iterator iterator = list.iterator(); - Integer next; - Integer data; - while(iterator.hasNext()){ - next = (Integer)iterator.next(); - while(null!=tempNode){ - data = (Integer)tempNode.data; - if(data7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + if(null==head){ + return; + } + Node tempNode=new Node(); + Node currentNode=head.next; + head.next=null; + while(null!=currentNode){ + tempNode=currentNode.next; + currentNode.next=head; + head=currentNode; + currentNode=tempNode; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + if(null==head){ + return; + } + Node tempNode; + int size=size(); + size=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[] array=new int[list.size()]; + Iterator iterator = list.iterator(); + int temp=0,next=0,size=0,oriSize=size(); + Node tempNode=head; + while(iterator.hasNext()){ + next = (Integer) iterator.next(); + if(next>=oriSize){ + break; + } + temp=next-temp; + for(int i=0;inext){ + continue; + } + if(currentNode==head){ + head=head.next; + }else{ + preNode.next=currentNode.next; + } + tempNode=currentNode; + currentNode=currentNode.next; + tempNode.next=null; + if(null==currentNode){ + break; + } + tempData=(Integer)currentNode.data; + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + Node currentNode=head; + Node tempNode=head; + int tempData; + while(null!=currentNode && null!=currentNode.next){ + tempData=(Integer)currentNode.data; + if(tempData==(Integer)currentNode.next.data){ + if(null!=currentNode.next.next){ + tempNode=currentNode.next; + currentNode.next=currentNode.next.next; + tempNode.next=null; + }else{ + currentNode.next=null; + } + }else{ + currentNode=currentNode.next; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于等于min且小于等于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + if(null==head){ + return; + } + int size=size(); + int headData=(Integer)head.data; + int endData=(Integer)get(size-1); + if(headData>=min && endData<=max){ + head=null; + return; + } + if(headData>max || endData=arm){ + return beginIndex; + } + tempData=(Integer)get(endIndex); + if(tempData<=arm){ + return endIndex; + } + int middleIndex=0; + while(beginIndexarm){ + endIndex=middleIndex; + }else{ + break; + } + } + return middleIndex; + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList rsection( LinkedList list){ + LinkedList armList=new LinkedList(); + Node tempNode=head; + if(null==list || list.size()==0){ + while(null!=tempNode){ + armList.add(tempNode.data); + tempNode=tempNode.next; + } + }else{ + Iterator iterator = list.iterator(); + Integer next; + Integer data; + while(iterator.hasNext()){ + next = (Integer)iterator.next(); + while(null!=tempNode){ + data = (Integer)tempNode.data; + if(datas.size()){ + throw new RuntimeException("len超出范围"); + } + Stack tempStack=new Stack(); + for(int i=0;i0){ + stack.push(flag); + }else if(flag<0){ + if(stack.size()==0){ + return false; + } + Integer peek = (Integer)stack.peek(); + if(peek+flag==0){ + stack.pop(); + }else{ + return false; + } + } + } + if(stack.size()>0){ + return false; + } + return true; + } + private static int switchChar(char c){ + int result=0; + switch(c){ + case '(': + result=1; + break; + case ')': + result=-1; + break; + case '[': + result=2; + break; + case ']': + result=-2; + break; + case '{': + result=3; + break; + case '}': + result=-3; + break; + default: + break; + } + return result; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..1e597a2b24 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/basic/stack/expr/InfixExpr.java @@ -0,0 +1,83 @@ +package com.github.ipk2015.coding2017.basic.stack.expr; + +import com.github.ipk2015.coding2017.basic.stack.Stack; + +public class InfixExpr { + String expr = null; + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + String[] elements = getElementArray(expr); + + Stack numStack = new Stack(); + Stack operStack = new Stack(); + + manageMultiAndDivOper(elements,numStack,operStack); + + return manageAddAndMinusOper(numStack,operStack); + } + + private void manageMultiAndDivOper(String[] elements,Stack numStack,Stack operStack){ + float preElement,nextElement; + for(int i = 0; i < elements.length;i++){ + if(i%2 == 0){ + numStack.push(Float.valueOf(elements[i])); + }else{ + + if(elements[i].equals("+") || elements[i].equals("-")){ + operStack.push(elements[i]); + }else{ + preElement = (Float)numStack.pop(); + i++; + nextElement = Float.valueOf(elements[i]); + numStack.push(doBaseOper(preElement,nextElement,elements[i-1])); + } + } + } + } + + private float manageAddAndMinusOper(Stack numStack,Stack operStack){ + float result = 0f;; + while(!operStack.isEmpty()){ + result = doBaseOper(result,(Float)numStack.pop(),(String)operStack.pop()); + } + result += (Float)numStack.pop(); + return result; + } + + private float doBaseOper(float preData,float nextData,String oper){ + switch(oper){ + case "+": + return preData+nextData; + case "-": + return preData-nextData; + case "*": + return preData*nextData; + case "/": + return preData/nextData; + default: + throw new RuntimeException("could not recognise oper:"+oper); + } + } + + public String[] getElementArray(String expression){ + char[] charArray = expression.toCharArray(); + StringBuffer stringBuffer = new StringBuffer(); + + 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.nextUNToInt(2); + int attrLength = iter.nextUNToInt(4); + LineNumberTable lineNumberTable = new LineNumberTable(attrNameIndex,attrLength); + int lineNumTableLen = iter.nextUNToInt(2); + for(int i = 0;i < lineNumTableLen;i++){ + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.nextUNToInt(2)); + lineNumberItem.setLineNum(iter.nextUNToInt(2)); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; + } + + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableItem.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..b1c6f61348 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.github.ipk2015.coding2017.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/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableTable.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..d8c3563b2b --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/LocalVariableTable.java @@ -0,0 +1,41 @@ +package com.github.ipk2015.coding2017.minijvm.attr; + + +import java.util.ArrayList; +import java.util.List; + + +import com.github.ipk2015.coding2017.minijvm.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){ + int attrNameIndex = iter.nextUNToInt(2); + int attrLength = iter.nextUNToInt(4); + LocalVariableTable table = new LocalVariableTable(attrNameIndex,attrLength); + int tableLen = iter.nextUNToInt(2); + for(int i = 0;i < tableLen;i++){ + LocalVariableItem item = new LocalVariableItem(); + item.setStartPC(iter.nextUNToInt(2)); + item.setLength(iter.nextUNToInt(2)); + item.setNameIndex(iter.nextUNToInt(2)); + item.setDescIndex(iter.nextUNToInt(2)); + item.setIndex(iter.nextUNToInt(2)); + table.addLocalVariableItem(item); + } + return table; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/StackMapTable.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/StackMapTable.java new file mode 100644 index 0000000000..5d86caa022 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +package com.github.ipk2015.coding2017.minijvm.attr; + +import com.github.ipk2015.coding2017.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.nextUNToInt(2); + int len = iter.nextUNToInt(4); + StackMapTable t = new StackMapTable(index,len); + + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.nextUNToHexString(len); + t.setOriginalCode(code); + + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/AccessFlag.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/AccessFlag.java new file mode 100644 index 0000000000..138f12d2c7 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/AccessFlag.java @@ -0,0 +1,37 @@ +package com.github.ipk2015.coding2017.minijvm.clz; + + + +public class AccessFlag { + public static int ACC_PUBLIC = 0x0001; + public static int ACC_FINAL = 0x0002; + public static int ACC_SUPER = 0x0020; + public static int ACC_INTEERFACE = 0x0200; + public static int ACC_ABSTRACT = 0x0400; + public static int ACC_SYNTHETIC = 0x1000; + public static int ACC_ANNOTATION = 0x2000; + public static int ACC_ENUM = 0x4000; + + 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 & ACC_PUBLIC) != 0; + } + + public boolean isFinalClass(){ + return (this.flagValue & ACC_FINAL) != 0; + } + +} \ No newline at end of file diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java new file mode 100644 index 0000000000..5cecfc3bff --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package com.github.ipk2015.coding2017.minijvm.clz; + +import java.util.ArrayList; +import java.util.List; + +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.field.Field; +import com.github.ipk2015.coding2017.minijvm.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(); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassIndex.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassIndex.java new file mode 100644 index 0000000000..834863c9ee --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/clz/ClassIndex.java @@ -0,0 +1,21 @@ +package com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e2e0f50f61 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ClassInfo.java @@ -0,0 +1,26 @@ +package com.github.ipk2015.coding2017.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(); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..663c493b57 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.github.ipk2015.coding2017.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); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java new file mode 100644 index 0000000000..ea0e135a23 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.github.ipk2015.coding2017.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 Object getSize() { + return this.constantInfos.size() -1; + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..b74fb427ba --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.github.ipk2015.coding2017.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(); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..cc5352db6e --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.github.ipk2015.coding2017.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(); + } + + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..d1cd005111 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.github.ipk2015.coding2017.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()+")"; + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..38eef91f32 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.github.ipk2015.coding2017.minijvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java new file mode 100644 index 0000000000..8f23231e72 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.github.ipk2015.coding2017.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); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java new file mode 100644 index 0000000000..d94a267bbc --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.github.ipk2015.coding2017.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; + } + + + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/field/Field.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/field/Field.java new file mode 100644 index 0000000000..37757878d6 --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/field/Field.java @@ -0,0 +1,41 @@ +package com.github.ipk2015.coding2017.minijvm.field; + +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.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.nextUNToInt(2); + int nameIndex = iter.nextUNToInt(2); + int descriptorIndex = iter.nextUNToInt(2); + int attrCount = iter.nextUNToInt(2); + if(attrCount != 0){ + throw new RuntimeException("字段的属性不为0"); + } + return new Field(accessFlag,nameIndex,descriptorIndex,pool); + } + + public String toString(){ + + return pool.getUTF8String(nameIndex)+":"+pool.getUTF8String(descriptorIndex); + } +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ByteCodeIterator.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..141331fe4b --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ByteCodeIterator.java @@ -0,0 +1,31 @@ +package com.github.ipk2015.coding2017.minijvm.loader; + +import java.util.Arrays; + +import com.github.ipk2015.coding2017.minijvm.util.Util; + +public class ByteCodeIterator { + private byte[] byteArray; + int pos=0; + + public ByteCodeIterator(byte[] codes){ + this.byteArray=codes; + } + + public int nextUNToInt(int n){ + return Util.byteToInt(nextUNToArray(n)); + } + + public String nextUNToHexString(int n){ + return Util.byteToHexString(nextUNToArray(n)); + } + + public byte[] nextUNToArray(int n){ + byte[] bytes=Arrays.copyOfRange(byteArray, pos, pos+n); + pos=pos+n; + return bytes; + } + public void back(int n) { + this.pos -= n; + } +} 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 new file mode 100644 index 0000000000..2f854174dd --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/loader/ClassFileLoader.java @@ -0,0 +1,143 @@ +package com.github.ipk2015.coding2017.minijvm.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.ipk2015.coding2017.minijvm.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 clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) throws IOException { + className=getCompleteClassName(className); + File file=null; + for(String path:clzPaths){ + file=new File(path+"\\"+className); + if(file.exists()){ + break; + } + } + if(null==file){ + throw new FileNotFoundException(className); + } + ByteArrayOutputStream bos=new ByteArrayOutputStream((int)file.length()); + BufferedInputStream in=new BufferedInputStream(new FileInputStream(file)); + int size=1024; + byte[] buffer=new byte[size]; + int length=0; + while((length=in.read(buffer, 0, size))!=-1){ + bos.write(buffer,0,length); + } + return bos.toByteArray(); + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuffer buffer=new StringBuffer(); + for(String path:clzPaths){ + buffer.append(path+";"); + } + buffer.deleteCharAt(buffer.length()-1); + return buffer.toString(); + } + + private String getCompleteClassName(String name){ + if(!name.endsWith(".class")){ + name=name+".class"; + } + int pointPos=name.lastIndexOf(".", name.length()-7); + if(pointPos>-1){ + name=name.substring(pointPos+1); + } + return name; + } + // ------------------------------backup------------------------ + public String getClassPath_V1(){ + + StringBuffer buffer = new StringBuffer(); + for(int i=0;i parseFields = parseFields(constantPool,iterator); + for(Field f:parseFields){ + classFile.addField(f); + } + + List parseMethods = parseMethods(classFile,iterator); + for(Method m:parseMethods){ + classFile.addMethod(m); + } + + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.nextUNToInt(2)); + return flag; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextUNToInt(2)); + classIndex.setSuperClassIndex(iter.nextUNToInt(2)); + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int poolSize = iter.nextUNToInt(2); + + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + + int tag; + for(int i = 1;i < poolSize; i++){ + tag = iter.nextUNToInt(1); + switch(tag){ + case ConstantInfo.CLASS_INFO: + meetClassInfo(pool,iter); + break; + case ConstantInfo.FIELD_INFO: + meetFieldInfo(pool,iter); + break; + case ConstantInfo.METHOD_INFO: + meetMethodInfo(pool,iter); + break; + case ConstantInfo.NAME_AND_TYPE_INFO: + meetNameAndTypeInfo(pool,iter); + break; + case ConstantInfo.STRING_INFO: + meetStringInfo(pool,iter); + break; + case ConstantInfo.UTF8_INFO: + meetUTF8Info(pool,iter); + break; + default: + throw new RuntimeException("还没有关于此的处理,tag:"+tag); + } + } + return pool; + } + + private void meetClassInfo(ConstantPool pool,ByteCodeIterator iter){ + ClassInfo info = new ClassInfo(pool); + info.setUtf8Index(iter.nextUNToInt(2)); + pool.addConstantInfo(info); + } + + private void meetFieldInfo(ConstantPool pool,ByteCodeIterator iter){ + FieldRefInfo info = new FieldRefInfo(pool); + info.setClassInfoIndex(iter.nextUNToInt(2)); + info.setNameAndTypeIndex(iter.nextUNToInt(2)); + pool.addConstantInfo(info); + } + + private void meetMethodInfo(ConstantPool pool,ByteCodeIterator iter){ + MethodRefInfo info = new MethodRefInfo(pool); + info.setClassInfoIndex(iter.nextUNToInt(2)); + info.setNameAndTypeIndex(iter.nextUNToInt(2)); + pool.addConstantInfo(info); + } + + private void meetNameAndTypeInfo(ConstantPool pool,ByteCodeIterator iter){ + NameAndTypeInfo info = new NameAndTypeInfo(pool); + info.setIndex1(iter.nextUNToInt(2)); + info.setIndex2(iter.nextUNToInt(2)); + pool.addConstantInfo(info); + } + + private void meetStringInfo(ConstantPool pool,ByteCodeIterator iter){ + StringInfo info = new StringInfo(pool); + info.setIndex(iter.nextUNToInt(2)); + pool.addConstantInfo(info); + } + + private void meetUTF8Info(ConstantPool pool,ByteCodeIterator iter){ + int length = iter.nextUNToInt(2); + byte[] data = iter.nextUNToArray(length); + String value = null; + try { + value=new String(data,"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + UTF8Info info = new UTF8Info(pool); + info.setLength(length); + info.setValue(value); + pool.addConstantInfo(info); + } + + private void parseInterfaces(ByteCodeIterator iter) { + int interfaceCount = iter.nextUNToInt(2); + + System.out.println("interfaceCount:" + interfaceCount); + + // TODO : 如果实现了interface, 这里需要解析 + } + + private List parseFields(ConstantPool pool,ByteCodeIterator iter){ + List list = new ArrayList(); + int count = iter.nextUNToInt(2); + for(int i = 0;i < count;i++){ + list.add(Field.parse(pool, iter)); + } + return list; + } + + private List parseMethods(ClassFile classFile,ByteCodeIterator iter){ + List list = new ArrayList(); + int count = iter.nextUNToInt(2); + for(int i = 0;i < count;i++){ + list.add(Method.parse(classFile, iter)); + } + return list; + } + +} 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 new file mode 100644 index 0000000000..3298a36d6b --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/method/Method.java @@ -0,0 +1,70 @@ +package com.github.ipk2015.coding2017.minijvm.method; + +import com.github.ipk2015.coding2017.minijvm.attr.AttributeInfo; +import com.github.ipk2015.coding2017.minijvm.attr.CodeAttr; +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.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){ + int accessFlag = iter.nextUNToInt(2); + int nameIndex = iter.nextUNToInt(2); + int descriptorIndex = iter.nextUNToInt(2); + Method method = new Method(clzFile,accessFlag,nameIndex,descriptorIndex); + int attrCount = iter.nextUNToInt(2); + for(int i = 0;i < attrCount;i++){ + addAttr(clzFile,method,iter); + } + return method; + } + private static void addAttr(ClassFile clzFile,Method method,ByteCodeIterator iter){ + int nameIndex = iter.nextUNToInt(2); + iter.back(2); + String attrName = clzFile.getConstantPool().getUTF8String(nameIndex); + if(AttributeInfo.CODE.equalsIgnoreCase(attrName)){ + method.setCodeAttr(CodeAttr.parse(clzFile, iter)); + }else{ + throw new RuntimeException("方法的此属性不存在:"+attrName); + } + } +} 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 new file mode 100644 index 0000000000..0a3979119d --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/ClassFileloaderTest.java @@ -0,0 +1,283 @@ +package com.github.ipk2015.coding2017.minijvm.test; + + + +import java.io.IOException; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.github.ipk2015.coding2017.minijvm.clz.ClassFile; +import com.github.ipk2015.coding2017.minijvm.clz.ClassIndex; +import com.github.ipk2015.coding2017.minijvm.constant.ClassInfo; +import com.github.ipk2015.coding2017.minijvm.constant.ConstantPool; +import com.github.ipk2015.coding2017.minijvm.constant.MethodRefInfo; +import com.github.ipk2015.coding2017.minijvm.constant.NameAndTypeInfo; +import com.github.ipk2015.coding2017.minijvm.constant.UTF8Info; +import com.github.ipk2015.coding2017.minijvm.field.Field; +import com.github.ipk2015.coding2017.minijvm.loader.ClassFileLoader; +import com.github.ipk2015.coding2017.minijvm.loader.ClassFileLoader1; +import com.github.ipk2015.coding2017.minijvm.method.Method; + + + + + + +public class ClassFileloaderTest { + + + static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + static String path2 = "C:\temp"; + static String path3 = "E:\\javaImprove\\git\\group24\\121111914\\src\\com\\github\\ipk2015\\coding2017\\minijvm\\bin"; + + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static ClassFile clzFile = null; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path3); +// String className = "com.coderising.jvm.test.EmployeeV1"; + String className = "EmployeeV1";//老师的class文件单独放在这里,只有类名 + + clzFile = loader.loadClass(className); + clzFile.print(); + } + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testClassPath(){ + + ClassFileLoader1 loader = new ClassFileLoader1(); + 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(path3); + + String className = "EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path3); + String className = "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); + } + +} diff --git a/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/EmployeeV1.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/EmployeeV1.java new file mode 100644 index 0000000000..ab8f3743fb --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/test/EmployeeV1.java @@ -0,0 +1,30 @@ +package com.github.ipk2015.coding2017.minijvm.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/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/util/Util.java b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/util/Util.java new file mode 100644 index 0000000000..b8eaef98ef --- /dev/null +++ b/group24/121111914/src/com/github/ipk2015/coding2017/minijvm/util/Util.java @@ -0,0 +1,26 @@ +package com.github.ipk2015.coding2017.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 clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) throws IOException { + String clzFileName = ""; + byte[] byteCodes = null; + boolean classFound = false; + + for (String path : clzPaths) { + clzFileName = path + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; + + if ((byteCodes = loadClassFile(clzFileName)) != null){ + classFound = true; + return byteCodes; + } + } + + if (classFound == false) { + throw new FileNotFoundException(clzFileName); + } + + return null; + } + + private byte[] loadClassFile(String clzFileName) throws IOException { + + File file = new File(clzFileName); + if(!file.exists()){ +// throw new FileNotFoundException(clzFileName); + return null; + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream((int)file.length()); + BufferedInputStream in = null; + + try { + in = new BufferedInputStream(new FileInputStream(file)); + + int buf_size = 1024; + byte[] buffer = new byte[buf_size]; + int len = 0; + + while ((len = in.read(buffer, 0, buf_size)) != -1) { + bos.write(buffer, 0, len); + } + + return bos.toByteArray(); + + } catch (IOException e) { + e.printStackTrace(); + throw e; + } finally { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + bos.close(); + } + } + + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + public String getClassPath_V1(){ + + return null; + } + + public String getClassPath(){ + String classPath = ""; + for (int i = 0; i < clzPaths.size(); i++) { + classPath += clzPaths.get(i); + if (i != clzPaths.size() - 1) { + classPath += ";"; + } + } + return classPath; + } + + + +} diff --git a/group24/1525619747/homework_20170402/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group24/1525619747/homework_20170402/src/com/coderising/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..3192f6596c --- /dev/null +++ b/group24/1525619747/homework_20170402/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,86 @@ +package com.coderising.jvm.test; + +import java.io.IOException; + +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 = "F:\\Project\\Java_Project\\Java_SE\\coding2017\\group24\\1525619747\\homework_20170402\\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() throws IOException { + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + + String className = "com.coderising.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); +// System.out.println(byteCodes.length); + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1056, byteCodes.length); + + } + + + @Test + public void testMagicNumber() throws IOException{ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coderising.jvm.test.EmployeeV1"; + byte[] byteCodes = loader.readBinaryCode(className); + System.out.println(byteCodes[0] + " " + byteCodes[1] + " " + byteCodes[2] + " " +byteCodes[3]); + byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; + + + String acctualValue = this.byteToHexString(codes); +// System.out.println(acctualValue); + Assert.assertEquals("cafebabe", acctualValue); + } + + + + + private String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i 0) { @@ -167,14 +168,6 @@ public Object[] toArray() { return Arrays.copyOf(elementData, size()); } - /** - * A version of rangeCheck used by add and addAll. - */ - private void rangeCheckForAdd(int index) { - if (index > size() - 1 || index < 0) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - } /** * Constructs an IndexOutOfBoundsException detail message. @@ -192,7 +185,7 @@ private String outOfBoundsMsg(int index) { * which throws an ArrayIndexOutOfBoundsException if index is negative. */ private void rangeCheck(int index) { - if (index >= size()) { + if (index < 0 || index >= size()) { throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } } diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java deleted file mode 100644 index 01ba928128..0000000000 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/LinkedList.java +++ /dev/null @@ -1,484 +0,0 @@ -package com.johnChnia.coding2017.basic; - -import java.util.NoSuchElementException; - -/** - * Created by john on 2017/3/9. - * - * @// TODO: 2017/4/1 支持Iterator - */ - -public class LinkedList implements List { - - private Node first = null; - private int size = 0; - - /** - * Constructs an empty list. - */ - public LinkedList() { - - } - - - private static class Node { - T element; - Node next; - Node prev; - } - - /** - * Appends the specified element to the end of this list. - * - * @param element element to be appended to this list - */ - public void add(E element) { - Node newNode = new Node<>(); - if (first == null) { - addWhenListIsEmpty(newNode, element); - return; - } - Node last = first; - while (last.next != null) - last = last.next; - last.next = newNode; - newNode.prev = last; - newNode.next = null; - newNode.element = element; - size++; - } - - private void addWhenListIsEmpty(Node newNode, E element) { - first = newNode; - first.element = element; - first.next = null; - first.prev = null; - size++; - } - - /** - * Inserts the specified element at the beginning of this list. - * - * @param element the element to add - */ - public void addFirst(E element) { - Node newNode = new Node<>(); - if (first == null) { - addWhenListIsEmpty(newNode, element); - return; - } - newNode.next = first; - newNode.prev = null; - newNode.element = element; - - first.prev = newNode; - first = newNode; - size++; - } - - /** - * Appends the specified element to the end of this list. - * - * @param element element to be appended to this list. - */ - public void addLast(E element) { - add(element); - } - - - /** - * Inserts the specified element at the specified position in this list. - * Shifts the element currently at that position (if any) and any - * subsequent elements to the right (adds one to their indices). - * - * @param index index at which the specified element is to be inserted. - * @param element element to be inserted. - * @throws RuntimeException if list size less than 2. - */ - public void add(int index, E element) { - if (size() < 2) - throw new RuntimeException("list size should greater than or equal to 2"); - isElementIndex(index); - if (index == 0) { - addFirst(element); - return; - } else { - Node temp = new Node<>(); - Node temp2 = first; - for (int i = 0; i < index; i++) { - temp2 = temp2.next; - } - temp2.prev.next = temp; - temp.prev = temp2.prev; - - temp.next = temp2; - temp2.prev = temp; - temp.element = element; - } - size++; - - } - - - /** - * remove last element in the list. - * - * @throws RuntimeException if the list is empty. - */ - public E removeLast() { - if (size == 0) - throw new RuntimeException("linkList size should greater than or equal to 1"); - E element; - Node next = first.next; - if (next == null) { - element = first.element; - - first = null; - } else { - Node last = first; - while (last.next != null) - last = last.next; - last.prev.next = null; - - element = last.element; - - last = null; // help GC - } - size--; - return element; - } - - - /** - * @param index - * @return - * @// TODO: 2018/3/14 if i am happy, i will implement it right now! - */ - public E remove(int index) { - return null; - } - - /** - * Removes and returns the first element from this list. - * - * @return the first element from this list - */ - public E removeFirst() { - Node f = first; - if (f == null) - throw new NoSuchElementException(); - E element = f.element; - Node next = first.next; - first.element = null; - first.next = null; // help GC - - first = next; - if (next != null) { - next.prev = null; - } - size--; - return element; - } - - - /** - * Returns the element at the specified position in this list. - * - * @param index index of the element to return - * @return the element at the specified position in this list - */ - public E get(int index) { - checkElementIndex(index); - Node node = first; - if (index == 0) { - return first.element; - } - for (int i = 0; i < index; i++) { - node = node.next; - } - return node.element; - } - - /** - * Returns the first element in this list. - * - * @return the first element in this list - * @throws NoSuchElementException if this list is empty - */ - public E getFirst() { - final Node f = first; - if (f == null) - throw new NoSuchElementException(); - return f.element; - } - - /** - * Returns the number of elements in this list. - * - * @return the number of elements in this list - */ - public int size() { - return size; - } - - private void checkElementIndex(int index) { - if (!isElementIndex(index)) { - throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); - } - } - - - /** - * Tells if the argument is the index of an existing element. - */ - private boolean isElementIndex(int index) { - return index >= 0 && index < size; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(first.element); - Node temp = first; - while (temp.next != null) { - temp = temp.next; - sb.append("→"); - sb.append(temp.element); - } - return sb.toString(); - } - - /** - * 把该链表逆置 - * 例如链表为 3->7->10 , 逆置后变为 10->7->3 - */ - public void reverse() { - Node next; - Node current = first; - for (int i = 0; i < size; i++) { - next = current.next; - current.next = current.prev; - current.prev = next; - if (next != null) { - current = next; - } - } - first = current; - } - - /** - * 删除一个单链表的前半部分 - * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 - * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 - */ - public void removeFirstHalf() { - int index = size() / 2; - Node current = first; - Node prev; - for (int i = 0; i < index; i++) { - prev = current; - current = current.next; - delete(prev); - } - current.prev = null; - first = current; - size = size - index; - } - - /** - * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 - * - * @param i - * @param length - */ - public void remove(int i, int length) { - checkElementIndex(i); - if (length + i > size()) { - throw new IllegalArgumentException("Length + i should less than or equal " + size()); - } - Node head = first; - Node tail = first; - if (i == 0 && length == size()) { - first = null; - } else if (i == 0 && length < size()) { - for (int j = 0; j < length; j++) { - head = head.next; - } - head.prev = null; - first = head; - } else { - for (int j = 0; j < i; j++) { - head = head.next; - } - head = head.prev; - for (int j = 0; j < length + i; j++) { - tail = tail.next; - } - head.next = tail; - if (tail != null) { - tail.prev = head; - } - } - 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) { - int[] newArray = new int[list.size()]; - Node mapNode = list.first; - Node valueNode = this.first; - int indexOfList = 0; - int indexOfArray = 0; - while (mapNode != null && valueNode != null) { - int mapValue = (int) mapNode.element; - if (mapValue == indexOfList) { - newArray[indexOfArray] = (int) valueNode.element; - mapNode = mapNode.next; - valueNode = valueNode.next; - indexOfArray++; - } else { - mapNode = mapNode.next; - } - indexOfList++; - } - return newArray; - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 从当前链表中中删除在listB中出现的元素 - * - * @param list - */ - - public void subtract(LinkedList list) { - Node pNode = first; - Node qNode = list.first; - Node prev = null; - Node deletedNode; - while (pNode != null && qNode != null) { - if ((int) qNode.element < (int) pNode.element) { - qNode = qNode.next; - } else if ((int) qNode.element > (int) pNode.element) { - prev = pNode; - pNode = pNode.next; - } else { - if (prev == null) { // 头结点 - first = pNode.next; - } else { - prev.next = pNode.next; - } - deletedNode = pNode; - pNode = pNode.next; - qNode = qNode.next; - delete(deletedNode); - size--; - } - } - - } - - private void delete(Node node) { - node.element = null; - node.prev = null; - node.next = null; - } - - /** - * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) - */ - public void removeDuplicateValues() { - Node current = first; - Node next = current.next; - while (next != null) { - if (current.element == next.element) { - current.next = next.next; - if (next.next != null) { - next.next.prev = current; - } - delete(next); - next = current.next; - size--; - } else { - current = current.next; - next = next.next; - } - - } - } - - /** - * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 - * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) - * - * @param min - * @param max - */ - public void removeRange(int min, int max) { - Node current = first; - Node prev = null; - Node deletedNode; - while (current != null) { - if ((int) current.element >= max) { - break; - } - if ((int) current.element > min && (int) current.element < max) { - if (prev == null) { // 头结点 - first = current.next; - } else { - prev.next = current.next; - } - deletedNode = current; - current = current.next; - delete(deletedNode); // help gc - size--; - } else { - prev = current; - current = current.next; - } - } - } - - /** - * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) - * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 - * - * @param list - */ - public LinkedList intersection(LinkedList list) { - LinkedList l = new LinkedList(); - Node pNode = first; - Node qNode = list.first; - while (pNode != null && qNode != null) { - if ((int) pNode.element < (int) qNode.element) { - pNode = pNode.next; - } else if ((int) pNode.element > (int) qNode.element) { - qNode = qNode.next; - } else { - l.add(pNode.element); - pNode = pNode.next; - qNode = qNode.next; - } - } - return l; - } - - - /** - * Constructs an IndexOutOfBoundsException detail message. - * Of the many possible refactorings of the error handling code, - * this "outlining" performs best with both server and client VMs. - */ - private String outOfBoundsMsg(int index) { - return "Index: " + index + ", Size: " + size; - } -} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Stack.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Stack.java deleted file mode 100644 index f43ea52397..0000000000 --- a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/Stack.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.johnChnia.coding2017.basic; - -import java.util.EmptyStackException; - -/** - * Created by john on 2017/3/10. - */ -public class Stack { - private LinkedList linkList; - - /** - * Creates an empty Stack. - */ - public Stack() { - linkList = new LinkedList<>(); - } - - - /** - * Pushes an item onto the top of this stack. - * - * @param element the element to be pushed onto this stack. - */ - public void push(E element) { - linkList.addFirst(element); - } - - /** - * Removes the object at the top of this stack and returns that - * object as the value of this function. - * - * @return The object at the top of this stack. - * @throws EmptyStackException if this stack is empty. - */ - public E pop() { - if (empty()) { - throw new EmptyStackException(); - } - return linkList.removeFirst(); - } - - /** - * Looks at the object at the top of this stack without removing it - * from the stack. - * - * @return the object at the top of this stack. - * @throws EmptyStackException if this stack is empty. - */ - public E peek() { - if (empty()) { - throw new EmptyStackException(); - } - return linkList.getFirst(); - } - - /** - * Tests if this stack is empty. - * - * @return true if and only if this stack contains - * no elements; false otherwise. - */ - public boolean empty() { - return linkList.size() == 0; - } - - public String toString() { - return linkList.toString(); - } - - /** - * Returns the number of elements in this stack. - * - * @return the number of elements in this stack - */ - public int size() { - return linkList.size(); - } -} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrame.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..cdc327fb30 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrame.java @@ -0,0 +1,128 @@ +package com.johnChnia.coding2017.basic.linklist; + +/** + * Created by john on 2017/4/6. + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + /** + * 获取缓存中的对象 + * + * @param pageNum 对象值 + */ + public void access(int pageNum) { + if (first == null) { + Node node = createNode(pageNum); + first = last = node; + capacity--; + } else if (getNode(pageNum) == null) { + if (capacity == 0) { + Node lastNode = first; + while (lastNode.next != null) { + lastNode = lastNode.next; + } + lastNode.prev.next = null; + last = lastNode.prev; + delete(lastNode); + capacity++; + } + Node node = createNode(pageNum); + node.next = first; + node.prev = null; + first.prev = node; + first = node; + capacity--; + + } else { + if (first.pageNum != pageNum) { + Node node = getNode(pageNum); + if (node.next != null) { + node.prev.next = node.next; + node.next.prev = node.prev; + } else { + node.prev.next = null; + last = node.prev; + } + node.next = first; + node.prev = null; + first.prev = node; + first = node; + } + } + + } + + /** + * 删除节点 + */ + private void delete(Node node) { + node.pageNum = 0; + node.next = null; + node.prev = null; + } + + /** + * @param pageNum 页号 + * @return 节点 + */ + private Node createNode(int pageNum) { + Node node = new Node(); + node.pageNum = pageNum; + node.next = null; + node.prev = null; + return node; + } + + + /** + * @param pageNum 页号 + * @return 如果LRUPageFrame包含该pageNum就返回该节点,否则返回null + */ + private Node getNode(int pageNum) { + for (Node node = first; node != null; node = node.next) { + if (node.pageNum == 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/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrameTest.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..e71abd393d --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LRUPageFrameTest.java @@ -0,0 +1,30 @@ +package com.johnChnia.coding2017.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/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 new file mode 100644 index 0000000000..10f7edd0a6 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/linklist/LinkedList.java @@ -0,0 +1,486 @@ +package com.johnChnia.coding2017.basic.linklist; + +import com.johnChnia.coding2017.basic.List; + +import java.util.NoSuchElementException; + +/** + * Created by john on 2017/3/9. + * + * @// TODO: 2017/4/1 支持Iterator + */ + +public class LinkedList implements List { + + private Node first = null; + private int size = 0; + + /** + * Constructs an empty list. + */ + public LinkedList() { + + } + + + private static class Node { + T element; + Node next; + Node prev; + } + + /** + * Appends the specified element to the end of this list. + * + * @param element element to be appended to this list + */ + public void add(E element) { + Node newNode = new Node<>(); + if (first == null) { + addWhenListIsEmpty(newNode, element); + return; + } + Node last = first; + while (last.next != null) + last = last.next; + last.next = newNode; + newNode.prev = last; + newNode.next = null; + newNode.element = element; + size++; + } + + private void addWhenListIsEmpty(Node newNode, E element) { + first = newNode; + first.element = element; + first.next = null; + first.prev = null; + size++; + } + + /** + * Inserts the specified element at the beginning of this list. + * + * @param element the element to add + */ + public void addFirst(E element) { + Node newNode = new Node<>(); + if (first == null) { + addWhenListIsEmpty(newNode, element); + return; + } + newNode.next = first; + newNode.prev = null; + newNode.element = element; + + first.prev = newNode; + first = newNode; + size++; + } + + /** + * Appends the specified element to the end of this list. + * + * @param element element to be appended to this list. + */ + public void addLast(E element) { + add(element); + } + + + /** + * Inserts the specified element at the specified position in this list. + * Shifts the element currently at that position (if any) and any + * subsequent elements to the right (adds one to their indices). + * + * @param index index at which the specified element is to be inserted. + * @param element element to be inserted. + * @throws RuntimeException if list size less than 2. + */ + public void add(int index, E element) { + if (size() < 2) + throw new RuntimeException("list size should greater than or equal to 2"); + isElementIndex(index); + if (index == 0) { + addFirst(element); + return; + } else { + Node temp = new Node<>(); + Node temp2 = first; + for (int i = 0; i < index; i++) { + temp2 = temp2.next; + } + temp2.prev.next = temp; + temp.prev = temp2.prev; + + temp.next = temp2; + temp2.prev = temp; + temp.element = element; + } + size++; + + } + + + /** + * remove last element in the list. + * + * @throws RuntimeException if the list is empty. + */ + public E removeLast() { + if (size == 0) + throw new RuntimeException("linkList size should greater than or equal to 1"); + E element; + Node next = first.next; + if (next == null) { + element = first.element; + + first = null; + } else { + Node last = first; + while (last.next != null) + last = last.next; + last.prev.next = null; + + element = last.element; + + last = null; // help GC + } + size--; + return element; + } + + + /** + * @param index + * @return + * @// TODO: 2018/3/14 if i am happy, i will implement it right now! + */ + public E remove(int index) { + return null; + } + + /** + * Removes and returns the first element from this list. + * + * @return the first element from this list + */ + public E removeFirst() { + Node f = first; + if (f == null) + throw new NoSuchElementException(); + E element = f.element; + Node next = first.next; + first.element = null; + first.next = null; // help GC + + first = next; + if (next != null) { + next.prev = null; + } + size--; + return element; + } + + + /** + * Returns the element at the specified position in this list. + * + * @param index index of the element to return + * @return the element at the specified position in this list + */ + public E get(int index) { + checkElementIndex(index); + Node node = first; + if (index == 0) { + return first.element; + } + for (int i = 0; i < index; i++) { + node = node.next; + } + return node.element; + } + + /** + * Returns the first element in this list. + * + * @return the first element in this list + * @throws NoSuchElementException if this list is empty + */ + public E getFirst() { + final Node f = first; + if (f == null) + throw new NoSuchElementException(); + return f.element; + } + + /** + * Returns the number of elements in this list. + * + * @return the number of elements in this list + */ + public int size() { + return size; + } + + private void checkElementIndex(int index) { + if (!isElementIndex(index)) { + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + } + + + /** + * Tells if the argument is the index of an existing element. + */ + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(first.element); + Node temp = first; + while (temp.next != null) { + temp = temp.next; + sb.append("→"); + sb.append(temp.element); + } + return sb.toString(); + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + Node next; + Node current = first; + for (int i = 0; i < size; i++) { + next = current.next; + current.next = current.prev; + current.prev = next; + if (next != null) { + current = next; + } + } + first = current; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + int index = size() / 2; + Node current = first; + Node prev; + for (int i = 0; i < index; i++) { + prev = current; + current = current.next; + delete(prev); + } + current.prev = null; + first = current; + size = size - index; + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + checkElementIndex(i); + if (length + i > size()) { + throw new IllegalArgumentException("Length + i should less than or equal " + size()); + } + Node head = first; + Node tail = first; + if (i == 0 && length == size()) { + first = null; + } else if (i == 0 && length < size()) { + for (int j = 0; j < length; j++) { + head = head.next; + } + head.prev = null; + first = head; + } else { + for (int j = 0; j < i; j++) { + head = head.next; + } + head = head.prev; + for (int j = 0; j < length + i; j++) { + tail = tail.next; + } + head.next = tail; + if (tail != null) { + tail.prev = head; + } + } + 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) { + int[] newArray = new int[list.size()]; + Node mapNode = list.first; + Node valueNode = this.first; + int indexOfList = 0; + int indexOfArray = 0; + while (mapNode != null && valueNode != null) { + int mapValue = (int) mapNode.element; + if (mapValue == indexOfList) { + newArray[indexOfArray] = (int) valueNode.element; + mapNode = mapNode.next; + valueNode = valueNode.next; + indexOfArray++; + } else { + valueNode = valueNode.next; + } + indexOfList++; + } + return newArray; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在listB中出现的元素 + * + * @param list + */ + + public void subtract(LinkedList list) { + Node pNode = first; + Node qNode = list.first; + Node prev = null; + Node deletedNode; + while (pNode != null && qNode != null) { + if ((int) qNode.element < (int) pNode.element) { + qNode = qNode.next; + } else if ((int) qNode.element > (int) pNode.element) { + prev = pNode; + pNode = pNode.next; + } else { + if (prev == null) { // 头结点 + first = pNode.next; + } else { + prev.next = pNode.next; + } + deletedNode = pNode; + pNode = pNode.next; + qNode = qNode.next; + delete(deletedNode); + size--; + } + } + + } + + private void delete(Node node) { + node.element = null; + node.prev = null; + node.next = null; + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + Node current = first; + Node next = current.next; + while (next != null) { + if (current.element == next.element) { + current.next = next.next; + if (next.next != null) { + next.next.prev = current; + } + delete(next); + next = current.next; + size--; + } else { + current = current.next; + next = next.next; + } + + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + */ + public void removeRange(int min, int max) { + Node current = first; + Node prev = null; + Node deletedNode; + while (current != null) { + if ((int) current.element >= max) { + break; + } + if ((int) current.element > min && (int) current.element < max) { + if (prev == null) { // 头结点 + first = current.next; + } else { + prev.next = current.next; + } + deletedNode = current; + current = current.next; + delete(deletedNode); // help gc + size--; + } else { + prev = current; + current = current.next; + } + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * + * @param list + */ + public LinkedList intersection(LinkedList list) { + LinkedList l = new LinkedList(); + Node pNode = first; + Node qNode = list.first; + while (pNode != null && qNode != null) { + if ((int) pNode.element < (int) qNode.element) { + pNode = pNode.next; + } else if ((int) pNode.element > (int) qNode.element) { + qNode = qNode.next; + } else { + l.add(pNode.element); + pNode = pNode.next; + qNode = qNode.next; + } + } + return l; + } + + + /** + * Constructs an IndexOutOfBoundsException detail message. + * Of the many possible refactorings of the error handling code, + * this "outlining" performs best with both server and client VMs. + */ + private String outOfBoundsMsg(int index) { + return "Index: " + index + ", Size: " + size; + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/Stack.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/Stack.java new file mode 100644 index 0000000000..c8f1ce7d15 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/Stack.java @@ -0,0 +1,80 @@ +package com.johnChnia.coding2017.basic.stack; + +import com.johnChnia.coding2017.basic.linklist.LinkedList; + +import java.util.EmptyStackException; + +/** + * Created by john on 2017/3/10. + */ +public class Stack { + private LinkedList linkList; + + /** + * Creates an empty Stack. + */ + public Stack() { + linkList = new LinkedList<>(); + } + + + /** + * Pushes an item onto the top of this stack. + * + * @param element the element to be pushed onto this stack. + */ + public void push(E element) { + linkList.addFirst(element); + } + + /** + * Removes the object at the top of this stack and returns that + * object as the value of this function. + * + * @return The object at the top of this stack. + * @throws EmptyStackException if this stack is empty. + */ + public E pop() { + if (empty()) { + throw new EmptyStackException(); + } + return linkList.removeFirst(); + } + + /** + * Looks at the object at the top of this stack without removing it + * from the stack. + * + * @return the object at the top of this stack. + * @throws EmptyStackException if this stack is empty. + */ + public E peek() { + if (empty()) { + throw new EmptyStackException(); + } + return linkList.getFirst(); + } + + /** + * Tests if this stack is empty. + * + * @return true if and only if this stack contains + * no elements; false otherwise. + */ + public boolean empty() { + return linkList.size() == 0; + } + + public String toString() { + return linkList.toString(); + } + + /** + * Returns the number of elements in this stack. + * + * @return the number of elements in this stack + */ + public int size() { + return linkList.size(); + } +} diff --git a/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackUtil.java b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackUtil.java new file mode 100644 index 0000000000..4b7c4687d7 --- /dev/null +++ b/group24/315863321/src/main/java/com/johnChnia/coding2017/basic/stack/StackUtil.java @@ -0,0 +1,122 @@ +package com.johnChnia.coding2017.basic.stack; + +/** + * Created by john on 2017/4/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) { + if (s.empty()) { + return; + } + E item = s.pop(); + reverse(s); + insertAtBottom(item, s); + } + + /** + * @param item 插入底部的元素 + * @param s 栈对象引用 + */ + private static void insertAtBottom(E item, Stack s) { + if (s.empty()) { + s.push(item); + } else { + E temp = s.pop(); + insertAtBottom(item, s); + s.push(temp); + } + } + + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + if (s.empty()) { + return; + } + E item = s.pop(); + if (!o.equals(item)) { //没有考虑o为null的情况 + remove(s, o); + s.push(item); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if (len > s.size()) { + throw new IllegalArgumentException("Len: " + len + ", Size" + s.size()); + } + Object[] array = new Object[len]; + int index = 0; + getArray(s, array, index); + return array; + } + + /** + * 采用递归的方式把len个元素加到数组中,且保持原栈中元素不变。 + * + * @param s 栈 + * @param array Object数组 + * @param index 数组索引 + */ + private static void getArray(Stack s, Object[] array, int index) { + if (s.empty() || index == array.length) { + return; + } + E item = s.pop(); + array[index++] = item; + getArray(s, array, index); + s.push(item); + } + + /** + * 字符串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) { // last unclosed first closed + Stack stack = new Stack<>(); + for (int i = 0; i < s.length(); i++) { + String subStr = s.substring(i, i + 1); + if ("([{".contains(subStr)) { + stack.push(subStr); + } else if (")]}".contains(subStr)) { + if (stack.empty()) { + return false; + } + String left = stack.pop(); + if (subStr.equals(")")) { + if(!left.equals("(")) + return false; + }else if(subStr.equals("]")){ + if(!left.equals("[")) + return false; + }else if(subStr.equals("}")){ + if(!left.equals("{")) + return false; + } + } + } + return stack.empty(); + } + +} \ No newline at end of file diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/ArrayListTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/ArrayListTest.java index e0df250c37..4b8d986990 100644 --- a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/ArrayListTest.java +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/ArrayListTest.java @@ -54,7 +54,6 @@ public void testRemoveElementByIndex() { arrayList4.add(i); } Object removed = arrayList4.remove(4); - System.out.println(arrayList4); assertThat(removed, equalTo(4)); assertThat(arrayList4.size(), equalTo(5)); } diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java index 9a72c0d54a..941d524987 100644 --- a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/LinkedListTest.java @@ -2,7 +2,7 @@ import org.junit.Before; import org.junit.Test; - +import com.johnChnia.coding2017.basic.linklist.LinkedList; import java.util.Arrays; import static org.hamcrest.CoreMatchers.containsString; diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/StackTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/StackTest.java index 9d84f7367a..c6f4ec1b2c 100644 --- a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/StackTest.java +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/StackTest.java @@ -1,5 +1,6 @@ package com.johnChnia.coding2017.basic; +import com.johnChnia.coding2017.basic.stack.Stack; import org.junit.Before; import org.junit.Test; diff --git a/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackUtilTest.java b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..0a2f277d49 --- /dev/null +++ b/group24/315863321/src/test/java/com/johnChnia/coding2017/basic/stack/StackUtilTest.java @@ -0,0 +1,66 @@ +package com.johnChnia.coding2017.basic.stack; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static com.johnChnia.coding2017.basic.stack.StackUtil.*; + + +/** + * Created by john on 2017/4/7. + */ +public class StackUtilTest { + + Stack s1; + Stack s2; + Stack s3; + + @Before + public void setUp() throws Exception { + s1 = new Stack<>(); + s2 = new Stack<>(); + s3 = new Stack<>(); + + } + + @Test + public void testReverse() throws Exception { + for (int i = 0; i < 4; i++) { + s1.push(i); + } + reverse(s1); + Assert.assertEquals("0→1→2→3", s1.toString()); + } + + @Test + public void testRemove() throws Exception { + for (int i = 0; i < 4; i++) { + s2.push(i); + } + remove(s2, 1); + Assert.assertEquals("3→2→0", s2.toString()); + } + + @Test + public void testGetTop() throws Exception { + for (int i = 0; i < 4; i++) { + s3.push(i); + } + Object[] array = getTop(s3, 2); + Assert.assertEquals(array.length, 2); + Assert.assertEquals(array[0], 3); + Assert.assertEquals(array[1], 2); + Assert.assertEquals("3→2→1→0", s3.toString()); + + } + + @Test + public void testIsValidPairs() throws Exception { + String s1 = "([e{d}f])"; + Assert.assertTrue(isValidPairs(s1)); + String s2 = "([b{x]y})"; + Assert.assertFalse(isValidPairs(s2)); + } + +} \ No newline at end of file diff --git a/group24/330657387/src/main/week01/data_structure/ArrayList.java b/group24/330657387/src/main/week01/data_structure/ArrayList.java index 9a2f4d2c8b..6ffbf377ef 100644 --- a/group24/330657387/src/main/week01/data_structure/ArrayList.java +++ b/group24/330657387/src/main/week01/data_structure/ArrayList.java @@ -2,6 +2,9 @@ import java.util.Arrays; +import main.week01.data_structure.api.Iterator; +import main.week01.data_structure.api.List; + public class ArrayList implements List { private int size = 0; @@ -48,7 +51,7 @@ public Object remove(int index) { Object dest = elementData[index]; System.arraycopy(elementData, index + 1, elementData, index, size - index - 1); - elementData[size---1]=null;//ֹڴй© + elementData[size---1]=null;//��ֹ�ڴ�й© return dest; } diff --git a/group24/330657387/src/main/week01/data_structure/ArrayListTest.java b/group24/330657387/src/main/week01/data_structure/ArrayListTest.java new file mode 100644 index 0000000000..d54bc0b73e --- /dev/null +++ b/group24/330657387/src/main/week01/data_structure/ArrayListTest.java @@ -0,0 +1,83 @@ +package main.week01.data_structure; + +import static org.junit.Assert.*; +import main.week01.data_structure.ArrayList.ArrayListIterator; + +import org.junit.Before; +import org.junit.Test; + +public class ArrayListTest { + + public static ArrayList list; + + @Before + public void setUp() throws Exception { + list = new ArrayList(); + } + + @Test + public void testAddObject() { + list.add(1); + list.add(2); + list.add(2); + assertEquals(3,list.size()); + } + + @Test + public void testAddIntObject() { + list.add(0,1); + list.add(1,2); + list.add(2,2); + list.add(0,2); + assertEquals(2,list.get(0)); + try{ + list.add(-1 , "test"); + fail("-1 can't be index"); + list.add(1000, "test"); + fail("out of range"); + }catch (Exception e){ + + } + } + + @Test + public void testGet() { + list.add("songhao"); + assertEquals("songhao", list.get(0)); + } + + @Test + public void testRemove() { + list.add("songhao"); + assertEquals("songhao", list.remove(0)); + } + + @Test + public void testSize(){ + list.add(0,1); + list.add(1,2); + list.add(2,2); + list.add(0,2); + assertEquals(4,list.size()); + } + + @Test + public void testIterator() { + list.add(0,1); + list.add(1,2); + list.add(2,3); + list.add(0,4); + ArrayListIterator iter = list.iterator(); + assertTrue(iter.hasNext()); + assertEquals(4, iter.next()); + assertTrue(iter.hasNext()); + assertEquals(1, iter.next()); + assertTrue(iter.hasNext()); + assertEquals(2, iter.next()); + assertTrue(iter.hasNext()); + assertEquals(3, iter.next()); + assertFalse(iter.hasNext()); + + } + +} diff --git a/group24/330657387/src/main/week01/data_structure/BinaryTreeNodeTest.java b/group24/330657387/src/main/week01/data_structure/BinaryTreeNodeTest.java new file mode 100644 index 0000000000..68dcd18d87 --- /dev/null +++ b/group24/330657387/src/main/week01/data_structure/BinaryTreeNodeTest.java @@ -0,0 +1,27 @@ +package main.week01.data_structure; + +import static org.junit.Assert.*; + +import org.junit.Before; +import org.junit.Test; + +public class BinaryTreeNodeTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void testInsert() { + BinaryTreeNode head=new BinaryTreeNode(); + + head.setData(5); + head.insert(2); + head.insert(7); + head.insert(1); + head.insert(4); + head.insert(3); + assertEquals(3,head.getLeft().getRight().getLeft().getData()); + } + +} diff --git a/group24/330657387/src/main/week01/data_structure/Iterator.java b/group24/330657387/src/main/week01/data_structure/Iterator.java deleted file mode 100644 index 194891e56a..0000000000 --- a/group24/330657387/src/main/week01/data_structure/Iterator.java +++ /dev/null @@ -1,7 +0,0 @@ -package main.week01.data_structure; - -public interface Iterator { - public boolean hasNext(); - public Object next(); - -} diff --git a/group24/330657387/src/main/week01/data_structure/LinkedList.java b/group24/330657387/src/main/week01/data_structure/LinkedList.java index b61df9f254..3e4053e1da 100644 --- a/group24/330657387/src/main/week01/data_structure/LinkedList.java +++ b/group24/330657387/src/main/week01/data_structure/LinkedList.java @@ -2,6 +2,9 @@ import java.util.NoSuchElementException; +import main.week01.data_structure.api.Iterator; +import main.week01.data_structure.api.List; + public class LinkedList implements List { private Node head; @@ -49,7 +52,7 @@ public Object get(int index) { return dest.data; } - public Node getNode(int index) { + private Node getNode(int index) { rangeCheck(index); Node dest = head; for (int i = 0; i < index; i++) { @@ -62,7 +65,7 @@ public Object remove(int index) { rangeCheck(index); if (index == 0) { return removeFirst(); - }else if(index == size){ + } else if (index == size) { return removeLast(); } Node pre = getNode(index - 1); @@ -132,6 +135,10 @@ private LinkedListIterator(LinkedList list) { this.list = list; } + public void reset() { + position = 0; + } + @Override public boolean hasNext() { return position + 1 <= list.size; @@ -147,4 +154,205 @@ public Object next() { public LinkedListIterator iterator() { return new LinkedListIterator(this); } + + /** + * 把该链表逆置 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse() { + if (size <= 1) { + return; + } + Node a = head, b = head.next; + head.next = null; + Node temp; + while (null != b) { + temp = b.next; + b.next = a; + a = b; + b = temp; + } + head = a; + } + + /** + * 删除一个单链表的前半部分 例如:list = 2->5->7->8 , 删除以后的值为 7->8 如果list = 2->5->7->8->10 + * ,删除以后的值为7,8,10 + */ + public void removeFirstHalf() { + if (size <= 1) { + return; + } + size = size % 2 == 0 ? size / 2 : size / 2 + 1; + head = getNode(size - 1); + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * + * @param i + * @param length + */ + public void remove(int i, int length) { + rangeCheck(i); + rangeCheck(i + length - 1);//或者当length超出长度,直接认为删除i后面的所有部分。 + if (i == 0) { + head = getNode(length); + size -= length; + } else { + Node pre = getNode(i - 1); + pre.next = getNode(i + length - 1).next; + } + } + + /** + * 假定当前链表和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 (list == null) { + throw new Exception("传入链表为空?"); + } + + int[] res = new int[list.size]; + for (int i = 0; i < list.size; i++) { + //这个list里的值不一定合法的。可以跳过那些不合法的值。 + if(i > size - 1){ + continue; + } + res[i] = Integer.parseInt(get( + Integer.parseInt(list.get(i).toString()) - 1).toString()); + } + return res; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 从当前链表中中删除在list中出现的元素 + * + * @param list + * @throws Exception + */ + + public void subtract(LinkedList list) throws Exception { + if (list == null) { + throw new Exception("传入链表为空?"); + } + LinkedListIterator beSub = this.iterator(), sub = list.iterator(); + while (sub.hasNext()) { + Object a = sub.next(); + while (beSub.hasNext()) { + Object b = beSub.next(); + if (a.equals(b)) { + this.remove(beSub.position - 1); + } + } + beSub.reset(); + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues() { + LinkedListIterator iter = this.iterator(); + if (size <= 1) { + return; + } + Object a = iter.next(); + while (iter.hasNext()) { + Object b = iter.next(); + if (b.equals(a)) { + remove(iter.position - 1); + continue; + } else { + a = b; + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * + * @param min + * @param max + * @throws Exception + */ + public void removeRange(int min, int max) throws Exception { + if(min > max){ + throw new Exception("输入有问题!"); + } + if(max < Integer.parseInt(get(0).toString())){ + throw new Exception("全部太小!"); + } + if(min > Integer.parseInt(get(size-1).toString())){ + throw new Exception("全部太大!"); + } + int firstRemove = -1,lastRemove = -1; + LinkedListIterator iter = this.iterator(); + boolean hasmin = false; + while(iter.hasNext()){ + int n = Integer.parseInt(iter.next().toString()); + if(n>min && !hasmin){ + firstRemove = iter.position - 1; + hasmin = true; + } + if(n(int)node2.data){ + node2 = node2.next; + }else{ + res.add(node1.data); + node1 = node1.next; + node2 = node2.next; + } + } + return res; + } + + public String toString() { + LinkedListIterator iter = this.iterator(); + StringBuilder sb = new StringBuilder(); + while (iter.hasNext()) { + sb.append(iter.next()); + sb.append("->"); + } + sb.append("null"); + return sb.toString(); + } } diff --git a/group24/330657387/src/main/week01/data_structure/LinkedListTest.java b/group24/330657387/src/main/week01/data_structure/LinkedListTest.java new file mode 100644 index 0000000000..c0aa471f79 --- /dev/null +++ b/group24/330657387/src/main/week01/data_structure/LinkedListTest.java @@ -0,0 +1,213 @@ +package main.week01.data_structure; + +import static org.junit.Assert.*; + +import java.util.Arrays; + +import main.week01.data_structure.LinkedList.LinkedListIterator; + +import org.junit.Before; +import org.junit.Test; + +public class LinkedListTest { + + private LinkedList list; + private LinkedList[] lists = new LinkedList[3]; + + @Before + public void setUp() throws Exception { + list = new LinkedList(); + + lists[0] = new LinkedList(); + lists[1] = new LinkedList(); + lists[2] = new LinkedList(); + + lists[1].add("A"); + + lists[2].add("A"); + lists[2].add("B"); + lists[2].add("C"); + lists[2].add("D"); + lists[2].add("E"); + + } + + @Test + public void testGet() { + list.add("A"); + list.add("B"); + list.add(0, "C"); + assertEquals("C", list.get(0)); + } + + @Test + public void testRemove() { + list.add("A"); + list.add("B"); + list.add("C"); + list.add("D"); + list.add(0, "E"); + assertEquals("E", list.remove(0)); + assertEquals("D", list.remove(list.size() - 1)); + assertEquals(3, list.size()); + } + + @Test + public void testIterator() { + LinkedListIterator iter = list.iterator(); + list.add("A"); + list.add("B"); + list.add(0, "C"); + assertTrue(iter.hasNext()); + assertEquals("C", iter.next()); + assertTrue(iter.hasNext()); + assertEquals("A", iter.next()); + assertTrue(iter.hasNext()); + assertEquals("B", iter.next()); + assertFalse(iter.hasNext()); + } + + @Test + public void testReverse() { + LinkedList l = lists[2]; + l.reverse(); + // assertEquals("", sb.toString()); + // assertEquals("A", l.toString()); + assertEquals("E->D->C->B->A->null", l.toString()); + + } + + @Test + public void testRemoveFirstHalf() { + LinkedList l = lists[0]; + l.removeFirstHalf(); + + LinkedListIterator iter = l.iterator(); + StringBuilder sb = new StringBuilder(); + while (iter.hasNext()) { + sb.append(iter.next()); + sb.append("->"); + } + sb.append("null"); + + assertEquals("null", sb.toString()); + //assertEquals("A->null", sb.toString()); + //assertEquals("C->D->E->null", sb.toString()); + } + + @Test + public void testRemoveByIndex() { + try{ + LinkedList l = lists[2]; + l.remove(0, 1); + System.out.println(l.toString()); + }catch(Exception e){ + assertEquals(IndexOutOfBoundsException.class, e.getClass()); + } + } + + @Test + public void testGetElements() { + list.add(11); + list.add(22); + list.add(33); + list.add(44); + list.add(55); + list.add(66); + list.add(77); + list.add(88); + list.add(99); + + LinkedList l = new LinkedList(); + l.add(1); + l.add(3); + l.add(4); + l.add(6); + try{ + int[] res = list.getElements(l); + System.out.println(Arrays.toString(res)); + }catch(Exception e){ + assertEquals(e.getMessage(), "传入链表为空?"); + } + } + + @Test + public void testSubtract() { + list.add(11); + list.add(22); + list.add(33); + list.add(44); + list.add(55); + list.add(66); + list.add(77); + list.add(88); + list.add(99); + + LinkedList l = new LinkedList(); + l.add(11); + l.add(33); + l.add(44); + l.add(66); + try{ + list.subtract(l); + System.out.println(list.toString()); + }catch(Exception e){ + assertEquals(e.getMessage(), "传入链表为空?"); + } + } + + @Test + public void testRemoveDuplicateValues() { + list.add(11); + list.add(11); + list.add(22); + list.add(33); + list.add(33); + + list.removeDuplicateValues(); + + System.out.println(list.toString()); + } + + @Test + public void testRemoveRange() throws Exception { + list.add(11); + list.add(22); + list.add(33); + list.add(44); + list.add(55); + list.add(66); + list.add(77); + list.add(88); + list.add(99); + System.out.println(list.toString()); + + try{ + list.removeRange(50, 80); + System.out.println(list.toString()); + }catch(Exception e){ + assertEquals(e.getMessage(), "输入有问题!"); + } + } + + @Test + public void testIntersection() { + list.add(11); +// list.add(22); +// list.add(33); +// list.add(44); +// list.add(55); +// list.add(66); +// list.add(77); +// list.add(88); +// list.add(99); + + LinkedList l = new LinkedList(); + l.add(11); + l.add(33); +// l.add(44); +// l.add(66); + + System.out.println(list.intersection(l).toString()); + } +} diff --git a/group24/330657387/src/main/week01/data_structure/List.java b/group24/330657387/src/main/week01/data_structure/List.java deleted file mode 100644 index 6cbc15f8ab..0000000000 --- a/group24/330657387/src/main/week01/data_structure/List.java +++ /dev/null @@ -1,10 +0,0 @@ -package main.week01.data_structure; - -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/group24/330657387/src/main/week01/data_structure/api/Iterator.java b/group24/330657387/src/main/week01/data_structure/api/Iterator.java new file mode 100644 index 0000000000..3ef869c5c8 --- /dev/null +++ b/group24/330657387/src/main/week01/data_structure/api/Iterator.java @@ -0,0 +1,7 @@ +package main.week01.data_structure.api; + +public interface Iterator { + public boolean hasNext(); + public Object next(); + +} diff --git a/group24/330657387/src/main/week01/data_structure/api/List.java b/group24/330657387/src/main/week01/data_structure/api/List.java new file mode 100644 index 0000000000..138f7bd018 --- /dev/null +++ b/group24/330657387/src/main/week01/data_structure/api/List.java @@ -0,0 +1,10 @@ +package main.week01.data_structure.api; + +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/group24/330657387/src/main/week02/practice/ArrayUtil.java b/group24/330657387/src/main/week02/practice/ArrayUtil.java index d174fdbe27..ed0dd51a60 100644 --- a/group24/330657387/src/main/week02/practice/ArrayUtil.java +++ b/group24/330657387/src/main/week02/practice/ArrayUtil.java @@ -1,6 +1,7 @@ package main.week02.practice; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import com.sun.xml.internal.ws.org.objectweb.asm.Label; @@ -19,7 +20,6 @@ public void reverseArray(int[] origin) { return; } int i = 0, j = origin.length - 1; - int temp; while (j > i) { origin[i] = origin[i] ^ origin[j]; origin[j] = origin[i] ^ origin[j]; @@ -137,21 +137,36 @@ public int[] fibonacci(int max) { if (max <= 1) { return new int[0]; } - ArrayList list = new ArrayList(); - list.add(1); - list.add(1); - int index = 1; - while (list.get(index) + list.get(index - 1) < max) { - list.add(list.get(index) + list.get(index - 1)); - index++; + if(max == 2){ + return new int[]{1,1}; } - Iterator iter = list.iterator(); - int[] res = new int[list.size()]; - int i = 0; - while (iter.hasNext()) { - res[i++] = iter.next(); + int[] arr = new int[max]; + arr[0] = arr[1] = 1; + int count = 2; + for(; count < max; count++){ + arr[count] = arr[count-1] + arr[count-2]; + if(arr[count] >= max){ + break; + } } - return res; + + return Arrays.copyOf(arr, count); + +// ArrayList list = new ArrayList(); +// list.add(1); +// list.add(1); +// int index = 1; +// while (list.get(index) + list.get(index - 1) < max) { +// list.add(list.get(index) + list.get(index - 1)); +// index++; +// } +// Iterator iter = list.iterator(); +// int[] res = new int[list.size()]; +// int i = 0; +// while (iter.hasNext()) { +// res[i++] = iter.next(); +// } +// return res; } /** diff --git a/group24/330657387/src/main/week02/practice/ArrayUtilTest.java b/group24/330657387/src/main/week02/practice/ArrayUtilTest.java new file mode 100644 index 0000000000..3c7ccbc4e5 --- /dev/null +++ b/group24/330657387/src/main/week02/practice/ArrayUtilTest.java @@ -0,0 +1,105 @@ +package main.week02.practice; + +import java.util.Arrays; +import org.junit.Before; +import org.junit.Test; + + +public class ArrayUtilTest { + + ArrayUtil util; + + @Before + public void setUp() throws Exception { + util = new ArrayUtil(); + } + + @Test + public void testReverseArray() { + int[][] origin = {{1,20,5,3,65,4,6,9,7}, + {1}, + {1,2,3}, + {}, + {23,32}}; + for(int[] a : origin){ + System.out.println("前:"+Arrays.toString(a)); + util.reverseArray(a); + System.out.println("后:"+Arrays.toString(a)); + } + } + + @Test + public void testRemoveZero() { + int[][] origin = {{1,20,0,0,5,3,65,4,0,6,9,7}, + {1,0}, + {1,0,2,3,0}, + {}, + {23,0,0,32}}; + for(int[] a : origin){ + System.out.println("前:"+Arrays.toString(a)); + System.out.println("后:"+Arrays.toString(util.removeZero(a))); + } + } + + @Test + public void testMerge() { + int[][] array1 = {{0,1,2,5,6,9,11}, + {1,2,3}, + {}}; + int[][] array2 = {{0,3,8,15,16,20,50},{1},{}}; + for(int i=0;i<3;i++){ + System.out.println("前:"+Arrays.toString(array1[i])+Arrays.toString(array2[i])); + System.out.println("后:"+Arrays.toString(util.merge(array1[i], array2[i]))); + } + } + + @Test + public void testGrow() { + int[][] origin = {{1,20,3,65,4,6,9,7}, + {}, + {1,0}, + {1,0,2,3}, + {23,0,0,32}}; + for(int[] a : origin){ + System.out.println("前:"+Arrays.toString(a)); + System.out.println("后:"+Arrays.toString(util.grow(a, 3))); + } + } + + @Test + public void testFibonacci() { + int[] origin = {1,2,3,65,4,6,9,7}; + for(int a : origin){ + System.out.println(Arrays.toString(util.fibonacci(a))); + } + } + + @Test + public void testGetPrimes() { + int[] origin = {1,2,3,65,4,6,9,7}; + for(int a : origin){ + System.out.println(Arrays.toString(util.getPrimes(a))); + } + } + + @Test + public void testGetPerfectNumbers() { + int[] origin = {1,2,3,65,4,6,999,7}; + for(int a : origin){ + System.out.println(Arrays.toString(util.getPerfectNumbers(a))); + } + } + + @Test + public void testJoin() { + int[][] origin = {{1,20,3,65,4,6,9,7}, + {}, + {1,0}, + {1,0,2,3}, + {23,0,0,32}}; + for(int[] a : origin){ + System.out.println(util.join(a , "=")); + } + } + +} diff --git a/group24/330657387/src/main/week03/download/DownloadThread.java b/group24/330657387/src/main/week03/download/DownloadThread.java new file mode 100644 index 0000000000..37602d1c25 --- /dev/null +++ b/group24/330657387/src/main/week03/download/DownloadThread.java @@ -0,0 +1,56 @@ +package main.week03.download; + +import java.io.File; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import main.week03.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 + + "]"); + + byte[] data = conn.read(startPos, endPos); + //设置文件的读取权限,每个线程都独立有这个实例,这样,多线程读写同一文件就没问题。 + RandomAccessFile file = new RandomAccessFile(localFile, "rw"); + + file.seek(startPos); + + file.write(data); + + file.close(); + + conn.close(); + + barrier.await(); // 等待别的线程完成 + + } catch (Exception e) { + //如果线程出错了,无法await,怎么处理? + e.printStackTrace(); + } finally{}//这块里应该写close的 + + } +} diff --git a/group24/330657387/src/main/week03/download/FileDownloader.java b/group24/330657387/src/main/week03/download/FileDownloader.java new file mode 100644 index 0000000000..165dc4dfb2 --- /dev/null +++ b/group24/330657387/src/main/week03/download/FileDownloader.java @@ -0,0 +1,131 @@ +package main.week03.download; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +import main.week03.download.api.Connection; +import main.week03.download.api.ConnectionException; +import main.week03.download.api.ConnectionManager; +import main.week03.download.api.DownloadListener; + +public class FileDownloader { + + private String url; + private String filePath = "/"; + + public DownloadListener listener; + + public ConnectionManager cm; + + private int DOWNLOAD_TRHEAD_NUM = 3; + + public FileDownloader(String _url, String filePath) { + this.url = _url; + this.filePath = filePath; + } + + 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方法 + + // 下面的代码是示例代码, 也就是说只有一个线程, 你需要改造成多线程的。 + + //当支线线程全部结束,即每个线程都调用了await方法,就会触发主线程,即listener的notify + CyclicBarrier barrier = new CyclicBarrier(DOWNLOAD_TRHEAD_NUM, + new Runnable() { + public void run() { + listener.notifyFinished(); + } + }); + + Connection conn = null; + try { + + conn = cm.open(this.url); + + int length = conn.getContentLength(); + + //确保文件里有足够的空间,就先创建空文件。 + createPlaceHolderFile(this.filePath, length); + + //每个线程的读取区间 + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); + + for (int i = 0; i < DOWNLOAD_TRHEAD_NUM; i++) { + + DownloadThread thread = new DownloadThread(cm.open(url), + ranges[i][0], ranges[i][1], filePath, barrier); + + thread.start(); + } + + } catch (ConnectionException e) { + e.printStackTrace(); + } finally { + if (conn != null) { + conn.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; + } + + private void createPlaceHolderFile(String filePath, int contentLen) + throws IOException { + RandomAccessFile file = new RandomAccessFile(filePath, "rw"); + + for (int i = 0; i < contentLen; i++) { + file.write(1); + } + + file.close(); + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager cm) { + this.cm = cm; + } + + public DownloadListener getListener() { + return this.listener; + } + +} diff --git a/group24/330657387/src/main/week03/download/FileDownloaderTest.java b/group24/330657387/src/main/week03/download/FileDownloaderTest.java new file mode 100644 index 0000000000..cee0ae1f61 --- /dev/null +++ b/group24/330657387/src/main/week03/download/FileDownloaderTest.java @@ -0,0 +1,77 @@ +package main.week03.download; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import main.week03.download.api.ConnectionManager; +import main.week03.download.api.DownloadListener; +import main.week03.download.impl.ConnectionManagerImpl; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class FileDownloaderTest { + boolean downloadFinished = false; + String _url = "http://images2015.cnblogs.com/blog/610238/201604/610238-20160421154632101-286208268.png"; + String _filePath = "/"; + @Before + public void setUp() throws Exception { + File file = new File("."); + + String packageName = this.getClass().getPackage().getName(); + // 把包名转化成路径的一部分 + packageName = packageName.replace('.', '/'); + + _filePath = file.getCanonicalPath() + "/src/" + packageName + "/" + "test.jpg"; + try{ + System.out.println(file.getCanonicalPath());//获取标准的路径 + System.out.println(file.getAbsolutePath());//获取绝对路径 + System.out.println(file.getPath()); + System.out.println(packageName); + }catch(Exception e){} + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPath(){} + + @Test + public void testDownload() throws IOException { + + FileDownloader downloader = new FileDownloader(_url, _filePath); + + 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/group24/330657387/src/main/week03/download/api/Connection.java b/group24/330657387/src/main/week03/download/api/Connection.java new file mode 100644 index 0000000000..b75b565af5 --- /dev/null +++ b/group24/330657387/src/main/week03/download/api/Connection.java @@ -0,0 +1,24 @@ +package main.week03.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 + * @throws ConnectionException + */ + public int getContentLength() throws ConnectionException; + + /** + * 关闭连接 + */ + public void close(); +} diff --git a/group24/330657387/src/main/week03/download/api/ConnectionException.java b/group24/330657387/src/main/week03/download/api/ConnectionException.java new file mode 100644 index 0000000000..e929fd388a --- /dev/null +++ b/group24/330657387/src/main/week03/download/api/ConnectionException.java @@ -0,0 +1,19 @@ +package main.week03.download.api; + +import java.io.IOException; +import java.net.MalformedURLException; + +public class ConnectionException extends Exception { + + public ConnectionException(String errmsg){ + super(errmsg); + } + + public ConnectionException(MalformedURLException e) { + super(e); + } + + public ConnectionException(IOException e) { + super(e); + } +} diff --git a/group24/330657387/src/main/week03/download/api/ConnectionManager.java b/group24/330657387/src/main/week03/download/api/ConnectionManager.java new file mode 100644 index 0000000000..6df387d42b --- /dev/null +++ b/group24/330657387/src/main/week03/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package main.week03.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group24/330657387/src/main/week03/download/api/DownloadListener.java b/group24/330657387/src/main/week03/download/api/DownloadListener.java new file mode 100644 index 0000000000..86cdd29d70 --- /dev/null +++ b/group24/330657387/src/main/week03/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package main.week03.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group24/330657387/src/main/week03/download/impl/ConnectionImpl.java b/group24/330657387/src/main/week03/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..e42087d663 --- /dev/null +++ b/group24/330657387/src/main/week03/download/impl/ConnectionImpl.java @@ -0,0 +1,84 @@ +package main.week03.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.util.Arrays; + +import main.week03.download.FileDownloader; +import main.week03.download.api.Connection; +import main.week03.download.api.ConnectionException; + +//包级可见,是保护措施 +class ConnectionImpl implements Connection { + + URL url; + static final int BUFFER_SIZE = 1024; + + public ConnectionImpl(String _url) throws ConnectionException { + try { + //传入的字符串必须是url格式 + url = new URL(_url); + } catch (MalformedURLException e) { + throw new ConnectionException(e); + } + } + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + int totalLen = endPos - startPos + 1; + + //是URLConnection的子类,负责http协议的链接 + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + InputStream inputStream = conn.getInputStream(); + + //客户端可以在请求里放置参数,设置接收数据区间 + //代替了is.skip(),但是is.skip里有read,所以是边读边移动下标的,和本程序意图相违背。 + conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); + + byte[] buffer = new byte[BUFFER_SIZE]; + + //输出流 + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + while (baos.size() < totalLen) { + + //一次读取1024字节 + int len = inputStream.read(buffer); + if (len < 0) { + break; + } + baos.write(buffer, 0, len); + } + + //防止这个线程过度读取 + if (baos.size() > totalLen) { + byte[] data = baos.toByteArray(); + return Arrays.copyOf(data, totalLen); + } + + return baos.toByteArray(); + } + + @Override + public int getContentLength() throws ConnectionException { + int res = -1; + try { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + res = conn.getContentLength(); + conn.disconnect(); + return res; + } catch (IOException e) { + throw new ConnectionException(e); + } + } + + @Override + public void close() { + + } + +} diff --git a/group24/330657387/src/main/week03/download/impl/ConnectionManagerImpl.java b/group24/330657387/src/main/week03/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..47d5dd22e1 --- /dev/null +++ b/group24/330657387/src/main/week03/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,17 @@ +package main.week03.download.impl; + +import main.week03.download.api.Connection; +import main.week03.download.api.ConnectionException; +import main.week03.download.api.ConnectionManager; + +//返回接口,是对实现的一种隐蔽 +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + Connection res = new ConnectionImpl(url); + + return res; + } + +} diff --git a/group24/330657387/src/main/week03/download/test.jpg b/group24/330657387/src/main/week03/download/test.jpg new file mode 100644 index 0000000000..a959a6ad20 --- /dev/null +++ b/group24/330657387/src/main/week03/download/test.jpg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/group24/330657387/src/test/week01/data_structure/ArrayListTest.java b/group24/330657387/src/test/week01/data_structure/ArrayListTest.java deleted file mode 100644 index d9d63339b2..0000000000 --- a/group24/330657387/src/test/week01/data_structure/ArrayListTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package test.week01.data_structure; - -import static org.junit.Assert.*; -import main.week01.data_structure.ArrayList; -import main.week01.data_structure.ArrayList.ArrayListIterator; - -import org.junit.Before; -import org.junit.Test; - -public class ArrayListTest { - - public static ArrayList list; - - @Before - public void setUp() throws Exception { - list = new ArrayList(); - } - - @Test - public void testAddObject() { - list.add(1); - list.add(2); - list.add(2); - assertEquals(3,list.size()); - } - - @Test - public void testAddIntObject() { - list.add(0,1); - list.add(1,2); - list.add(2,2); - list.add(0,2); - assertEquals(2,list.get(0)); - try{ - list.add(-1 , "test"); - fail("-1 can't be index"); - list.add(1000, "test"); - fail("out of range"); - }catch (Exception e){ - - } - } - - @Test - public void testGet() { - list.add("songhao"); - assertEquals("songhao", list.get(0)); - } - - @Test - public void testRemove() { - list.add("songhao"); - assertEquals("songhao", list.remove(0)); - } - - @Test - public void testSize(){ - list.add(0,1); - list.add(1,2); - list.add(2,2); - list.add(0,2); - assertEquals(4,list.size()); - } - - @Test - public void testIterator() { - list.add(0,1); - list.add(1,2); - list.add(2,3); - list.add(0,4); - ArrayListIterator iter = list.iterator(); - assertTrue(iter.hasNext()); - assertEquals(4, iter.next()); - assertTrue(iter.hasNext()); - assertEquals(1, iter.next()); - assertTrue(iter.hasNext()); - assertEquals(2, iter.next()); - assertTrue(iter.hasNext()); - assertEquals(3, iter.next()); - assertFalse(iter.hasNext()); - - } - -} diff --git a/group24/330657387/src/test/week01/data_structure/BinaryTreeNodeTest.java b/group24/330657387/src/test/week01/data_structure/BinaryTreeNodeTest.java deleted file mode 100644 index 515da2e7d4..0000000000 --- a/group24/330657387/src/test/week01/data_structure/BinaryTreeNodeTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package test.week01.data_structure; - -import static org.junit.Assert.*; -import main.week01.data_structure.BinaryTreeNode; - -import org.junit.Before; -import org.junit.Test; - -public class BinaryTreeNodeTest { - - @Before - public void setUp() throws Exception { - } - - @Test - public void testInsert() { - BinaryTreeNode head=new BinaryTreeNode(); - - head.setData(5); - head.insert(2); - head.insert(7); - head.insert(1); - head.insert(4); - head.insert(3); - assertEquals(3,head.getLeft().getRight().getLeft().getData()); - } - -} diff --git a/group24/330657387/src/test/week01/data_structure/LinkedListTest.java b/group24/330657387/src/test/week01/data_structure/LinkedListTest.java deleted file mode 100644 index cf374a6dcb..0000000000 --- a/group24/330657387/src/test/week01/data_structure/LinkedListTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package test.week01.data_structure; - -import static org.junit.Assert.*; -import main.week01.data_structure.LinkedList; -import main.week01.data_structure.LinkedList.LinkedListIterator; - -import org.junit.Before; -import org.junit.Test; - -public class LinkedListTest { - - private LinkedList list; - - @Before - public void setUp() throws Exception { - list = new LinkedList(); - } - - @Test - public void testGet() { - list.add("A"); - list.add("B"); - list.add(0, "C"); - assertEquals("C", list.get(0)); - } - - @Test - public void testRemove() { - list.add("A"); - list.add("B"); - list.add("C"); - list.add("D"); - list.add(0, "E"); - assertEquals("E", list.remove(0)); - assertEquals("D", list.remove(list.size()-1)); - assertEquals(3, list.size()); - } - - @Test - public void testIterator() { - LinkedListIterator iter = list.iterator(); - list.add("A"); - list.add("B"); - list.add(0, "C"); - assertTrue(iter.hasNext()); - assertEquals("C", iter.next()); - assertTrue(iter.hasNext()); - assertEquals("A", iter.next()); - assertTrue(iter.hasNext()); - assertEquals("B", iter.next()); - assertFalse(iter.hasNext()); - } - -} diff --git a/group24/330657387/src/test/week02/practice/ArrayUtilTest.java b/group24/330657387/src/test/week02/practice/ArrayUtilTest.java deleted file mode 100644 index 0e29853068..0000000000 --- a/group24/330657387/src/test/week02/practice/ArrayUtilTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package test.week02.practice; - -import static org.junit.Assert.*; - -import java.util.Arrays; -import java.util.HashMap; - -import main.week02.practice.ArrayUtil; - -import org.junit.Before; -import org.junit.Test; - - -public class ArrayUtilTest { - - ArrayUtil util; - - @Before - public void setUp() throws Exception { - util = new ArrayUtil(); - } - - @Test - public void testReverseArray() { - int[][] origin = {{1,20,5,3,65,4,6,9,7}, - {1}, - {1,2,3}, - {}, - {23,32}}; - for(int[] a : origin){ - System.out.println("前:"+Arrays.toString(a)); - util.reverseArray(a); - System.out.println("后:"+Arrays.toString(a)); - } - } - - @Test - public void testRemoveZero() { - int[][] origin = {{1,20,0,0,5,3,65,4,0,6,9,7}, - {1,0}, - {1,0,2,3,0}, - {}, - {23,0,0,32}}; - for(int[] a : origin){ - System.out.println("前:"+Arrays.toString(a)); - System.out.println("后:"+Arrays.toString(util.removeZero(a))); - } - } - - @Test - public void testMerge() { - int[][] array1 = {{0,1,2,5,6,9,11}, - {1,2,3}, - {}}; - int[][] array2 = {{0,3,8,15,16,20,50},{1},{}}; - for(int i=0;i<3;i++){ - System.out.println("前:"+Arrays.toString(array1[i])+Arrays.toString(array2[i])); - System.out.println("后:"+Arrays.toString(util.merge(array1[i], array2[i]))); - } - } - - @Test - public void testGrow() { - int[][] origin = {{1,20,3,65,4,6,9,7}, - {}, - {1,0}, - {1,0,2,3}, - {23,0,0,32}}; - for(int[] a : origin){ - System.out.println("前:"+Arrays.toString(a)); - System.out.println("后:"+Arrays.toString(util.grow(a, 3))); - } - } - - @Test - public void testFibonacci() { - int[] origin = {1,2,3,65,4,6,9,7}; - for(int a : origin){ - System.out.println(Arrays.toString(util.fibonacci(a))); - } - } - - @Test - public void testGetPrimes() { - int[] origin = {1,2,3,65,4,6,9,7}; - for(int a : origin){ - System.out.println(Arrays.toString(util.getPrimes(a))); - } - } - - @Test - public void testGetPerfectNumbers() { - int[] origin = {1,2,3,65,4,6,999,7}; - for(int a : origin){ - System.out.println(Arrays.toString(util.getPerfectNumbers(a))); - } - } - - @Test - public void testJoin() { - int[][] origin = {{1,20,3,65,4,6,9,7}, - {}, - {1,0}, - {1,0,2,3}, - {23,0,0,32}}; - for(int[] a : origin){ - System.out.println(util.join(a , "=")); - } - } - -} diff --git "a/group24/330657387/\345\215\232\345\256\242\345\234\260\345\235\200.txt" "b/group24/330657387/\345\215\232\345\256\242\345\234\260\345\235\200.txt" index 76ae770288..79237635d2 100644 --- "a/group24/330657387/\345\215\232\345\256\242\345\234\260\345\235\200.txt" +++ "b/group24/330657387/\345\215\232\345\256\242\345\234\260\345\235\200.txt" @@ -1,6 +1,6 @@ һܲhttp://www.cnblogs.com/sargeles/p/6605493.html ڶܲhttp://www.cnblogs.com/sargeles/p/6605945.html -ܲ +ܲhttp://www.cnblogs.com/sargeles/p/6667002.html ܲ ܲ ܲ diff --git a/group24/448641125/src/com/donaldy/basic/ArrayList.java b/group24/448641125/src/com/donaldy/basic/ArrayList.java index b4528176c1..859ebaf75f 100644 --- a/group24/448641125/src/com/donaldy/basic/ArrayList.java +++ b/group24/448641125/src/com/donaldy/basic/ArrayList.java @@ -27,7 +27,7 @@ public void add(int index, Object o){ private void ensureCupacity(int capacitySize){ if (capacitySize >= MAXNSIZE) - throw new RuntimeException(); + throw new RuntimeException("capacitySize : " + capacitySize); } public void clear() { diff --git a/group24/448641125/src/com/donaldy/basic/Stack.java b/group24/448641125/src/com/donaldy/basic/Stack.java index 22fcbbf4bd..ed500638d1 100644 --- a/group24/448641125/src/com/donaldy/basic/Stack.java +++ b/group24/448641125/src/com/donaldy/basic/Stack.java @@ -4,15 +4,15 @@ public class Stack { private ArrayList elementData = new ArrayList(); public void push(Object o) { - elementData.add(o); + this.elementData.add(o); } public Object pop() { - return elementData.remove(size() - 1); + return this.elementData.remove(size() - 1); } public Object peek() { - return elementData.get(size() - 1); + return this.elementData.get(size() - 1); } public boolean isEmpty() { @@ -20,6 +20,6 @@ public boolean isEmpty() { } public int size(){ - return elementData.size(); + return this.elementData.size(); } } diff --git a/group24/448641125/src/com/donaldy/basic/StackUtil.java b/group24/448641125/src/com/donaldy/basic/StackUtil.java new file mode 100644 index 0000000000..ca0014b34e --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/StackUtil.java @@ -0,0 +1,118 @@ +package com.donaldy.basic; + +import java.util.*; + +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) { + ArrayList arrayList = new ArrayList(); + while (!s.isEmpty()) { + Object element = s.pop(); + arrayList.add(element); + } + + for (int i = 0; i < arrayList.size(); ++i) { + s.push(arrayList.get(i)); + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + //若stack的值为唯一的。 + Stack stack = new Stack(); + while (!s.isEmpty()) { + Object element = s.pop(); + if (o == element) { + break; + } + stack.push(element); + } + + while (!stack.isEmpty()) { + Object element = stack.pop(); + s.push(element); + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + if (len < 0 || len >= s.size()) + throw new IndexOutOfBoundsException("len : " + len); + + Object [] arr = new Object[len]; + + ArrayList arrayList = new ArrayList(); + + while (!s.isEmpty()) { + arrayList.add(s.pop()); + } + + for (int i = arrayList.size() - 1; i >= 0; --i) + s.push(arrayList.get(i)); + + for (int i = 0 ; i < len; ++i) + arr[i] = arrayList.get(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){ + char [] arr = s.toCharArray(); + Stack stack = new Stack(); + for (int i = 0; i < s.length(); ++i) { + if (arr[i] == '(' ) + stack.push(')'); + if ( arr[i] == '{' ) + stack.push('}'); + if ( arr[i] == '[') + stack.push(']'); + + if (arr[i] == ')' ) { + if (')' != (char)stack.peek()) + break; + stack.pop(); + } + + if (arr[i] == '}' ) { + if ('}' != (char)stack.peek()) + break; + stack.pop(); + } + + if (arr[i] == ']' ) { + if (']' != (char)stack.peek()) + break; + stack.pop(); + } + + } + + if (stack.isEmpty()) + return true; + + return false; + } + + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/InfixExpr.java b/group24/448641125/src/com/donaldy/basic/expr/InfixExpr.java new file mode 100644 index 0000000000..dfd901febb --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/InfixExpr.java @@ -0,0 +1,140 @@ +package com.donaldy.basic.expr; + +import com.donaldy.basic.Stack; + +/** + * 针对最后一个用例,expr: 10 - 30 + 50; + * 负数,直接对后面的数进行取反(实际上计算机就是这样做的,组原有提。) + * 即:expr: 10 - 30 + 50 + * 处理后: 10 + -30 + 50 + */ +public class InfixExpr { + + String expr = null; + + Stack numStack = new Stack(); + Stack symbolStack = new Stack(); + + public InfixExpr(String expr) { + this.expr = expr; + } + + public float evaluate() { + + if (!this.numStack.isEmpty()) + return (float) this.numStack.peek(); + + char [] arr = this.expr.toCharArray(); + + parseCharArray(arr); + + remainOperate(); + + return (float) this.numStack.peek(); + } + + private void parseCharArray(char [] arr) { + + for (int i = 0; i < arr.length; ) { + + i = parseNumberReturnIndex(i, arr); + + if (i >= arr.length) + break; + + i = parseSymbolReturnIndex(i, arr); + } + } + + private int parseNumberReturnIndex(int index, char [] arr) { + if (arr[index] <= '9' && arr[index] >= '0' ) { + + float value = arr[index ++] - '0'; + + while (index < arr.length && arr[index] <= '9' && arr[index] >= '0' ) { + value *= 10; + value += arr[index] - '0'; + index ++; + } + this.numStack.push(value); + } + + return index; + } + + private int parseSymbolReturnIndex(int index, char[] arr) { + + if ("+-*/".contains(arr[index] + "")) { + + char operator = arr[index ++]; + + if (operator == '+') { + this.symbolStack.push('+'); + } + + if (operator == '-') { + + this.symbolStack.push('+'); + + float value = arr[index ++] - '0'; + + while (index < arr.length && arr[index] <= '9' && arr[index] >= '0') { + value *= 10; + value += arr[index] - '0'; + index ++; + } + + this.numStack.push(-value); + } + + if (operator == '*' || operator == '/') { + + float value1 = (float) this.numStack.pop(); + float value2 = arr[index ++] - '0'; + + while (index < arr.length && arr[index] <= '9' && arr[index] >= '0') { + value2 *= 10; + value2 += arr[index] - '0'; + index ++; + } + + this.numStack.push(operate(value2, value1, operator)); + + } + + } + + return index; + } + + private void remainOperate() { + while (!this.symbolStack.isEmpty()) { + if (this.numStack.size() < 2 || this.symbolStack.size() < 1) + throw new IndexOutOfBoundsException("numStack.size : " + this.numStack.size() + + " symbolStack.size : " + this.symbolStack.size()); + + float value1 = (float) this.numStack.pop(); + float value2 = (float) this.numStack.pop(); + char cSymbol = (char) this.symbolStack.pop(); + + this.numStack.push(operate(value1, value2, cSymbol)); + } + } + + + private float operate (float value1, float value2, char operator) { + + if (operator == '+') { + return value2 + value1; + } else if (operator == '*') { + return value2 * value1; + } else if (operator == '/') { + return value2 / value1; + } else { + throw new RuntimeException("No this operator : " + operator); + } + + } + + +} diff --git a/group24/448641125/src/com/donaldy/basic/expr/InfixExprTest.java b/group24/448641125/src/com/donaldy/basic/expr/InfixExprTest.java new file mode 100644 index 0000000000..47afcec569 --- /dev/null +++ b/group24/448641125/src/com/donaldy/basic/expr/InfixExprTest.java @@ -0,0 +1,48 @@ +package com.donaldy.basic.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/group24/448641125/src/com/donaldy/jvm/attr/AttributeInfo.java b/group24/448641125/src/com/donaldy/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..db2cdc8f97 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/AttributeInfo.java @@ -0,0 +1,19 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..6b699e6991 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/CodeAttr.java @@ -0,0 +1,56 @@ +package com.donaldy.jvm.attr; + +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/attr/LineNumberTable.java b/group24/448641125/src/com/donaldy/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..9dc9ab1dc9 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/LineNumberTable.java @@ -0,0 +1,57 @@ +package com.donaldy.jvm.attr; + +import java.util.ArrayList; +import java.util.List; + +import com.donaldy.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 attributeLen = iter.nextU4ToInt(); + int lnTableLen = iter.nextU2ToInt(); + LineNumberTable lnTable = new LineNumberTable(attrNameIndex, attributeLen); + + System.out.println("LineNumberTable.lnTableLen : " + lnTableLen); + + for (int i = 0; i < lnTableLen; ++i) { + LineNumberItem lnItem = new LineNumberItem(); + + lnItem.setStartPC(iter.nextU2ToInt()); + lnItem.setLineNum(iter.nextU2ToInt()); + + lnTable.addLineNumberItem(lnItem); + } + + return lnTable; + } + + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableItem.java b/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..7f04ebbc22 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableItem.java @@ -0,0 +1,39 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableTable.java b/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..c207540570 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/LocalVariableTable.java @@ -0,0 +1,45 @@ +package com.donaldy.jvm.attr; + + +import java.util.ArrayList; +import java.util.List; + +import com.donaldy.jvm.constant.ConstantPool; + +import com.donaldy.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){ + int attrNameIndex = iter.nextU2ToInt(); + int attrLen = iter.nextU4ToInt(); + int localVariableTableLen = iter.nextU2ToInt(); + + LocalVariableTable lvTable = new LocalVariableTable(attrNameIndex, attrLen); + + for (int i = 0 ; i < localVariableTableLen; ++i) { + LocalVariableItem lvItem = new LocalVariableItem(); + lvItem.setStartPC(iter.nextU2ToInt()); + lvItem.setLength(iter.nextU2ToInt()); + lvItem.setNameIndex(iter.nextU2ToInt()); + lvItem.setDescIndex(iter.nextU2ToInt()); + lvItem.setIndex(iter.nextU2ToInt()); + + lvTable.addLocalVariableItem(lvItem); + } + + + return lvTable; + } + private void addLocalVariableItem(LocalVariableItem item) { + this.items.add(item); + } + + +} diff --git a/group24/448641125/src/com/donaldy/jvm/attr/StackMapTable.java b/group24/448641125/src/com/donaldy/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..41365dc049 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/attr/StackMapTable.java @@ -0,0 +1,30 @@ +package com.donaldy.jvm.attr; + + +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/clz/AccessFlag.java b/group24/448641125/src/com/donaldy/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..ea06ad07cb --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java b/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..c36e1940b1 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/clz/ClassFile.java @@ -0,0 +1,92 @@ +package com.donaldy.jvm.clz; + +import com.donaldy.jvm.constant.ClassInfo; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.field.Field; +import com.donaldy.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/group24/448641125/src/com/donaldy/jvm/clz/ClassIndex.java b/group24/448641125/src/com/donaldy/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..d7e0524060 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..71f31261e4 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..20cad6fcd5 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java b/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..77bdfc8e67 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..6a6f72f5da --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..e65135279f --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..21ecd2b411 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..3a2cc11017 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.donaldy.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java b/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f59d34a497 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java b/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7432e5b6c4 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.donaldy.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/group24/448641125/src/com/donaldy/jvm/field/Field.java b/group24/448641125/src/com/donaldy/jvm/field/Field.java new file mode 100644 index 0000000000..18cad5669a --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/field/Field.java @@ -0,0 +1,46 @@ +package com.donaldy.jvm.field; + +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.UTF8Info; +import com.donaldy.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(); + + //TODO : 因无static类型变量,所以这无 + int attributesCount = iter.nextU2ToInt(); + + Field file = new Field(accessFlag, nameIndex, descriptorIndex, pool); + + return file; + } + + public String toString() { + //System.out.println("name : " + this.nameIndex + ", desc : " + descriptorIndex); + String description = this.pool.getUTF8String(this.descriptorIndex); + String name = this.pool.getUTF8String(this.nameIndex); + return name + ":"+ description; + } +} diff --git a/group24/448641125/src/com/donaldy/jvm/loader/ByteCodeIterator.java b/group24/448641125/src/com/donaldy/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..82eae449b9 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,104 @@ +package com.donaldy.jvm.loader; + +import com.donaldy.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; + } + + ///////////////////////Backup////////////////// + /*private byte[] codes; + + private int pointer = 0; + + public ByteCodeIterator(byte[] codes) { + this.codes = codes; + } + + public String nextU4ToHexString() { + byte [] byteCodes = nextLenByte(4); + + return Util.byteToHexString(byteCodes); + } + + public int nextU2ToInt() { + byte [] byteCodes = nextLenByte(2); + + return Util.byteToInt(byteCodes); + } + + public int nextU1toInt() { + byte [] byteCodes = nextLenByte(1); + + return Util.byteToInt(byteCodes); + } + + public byte[] getBytes(int len) { + byte [] byteCodes = nextLenByte(len); + + return byteCodes; + } + + private byte[] nextLenByte(int len) { + if (this.pointer + len >= this.codes.length) + throw new IndexOutOfBoundsException("codes.length : " + this.codes.length); + + byte [] byteCodes = new byte[len]; + + for (int i = 0 ; i < len; ++i) { + byteCodes[i] = this.codes[pointer ++]; + } + + return byteCodes; + }*/ +} diff --git a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java index c4a64b26d6..e1132dd023 100644 --- a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java +++ b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileLoader.java @@ -2,7 +2,10 @@ import java.io.*; import java.util.ArrayList; -import java.util.Iterator; + +import com.donaldy.jvm.clz.ClassFile; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -12,15 +15,69 @@ public class ClassFileLoader { private List clzPaths = new ArrayList(); static final int BUFFER_SIZE = 1024; - + public byte[] readBinaryCode(String className) { + className = className.replace(".", File.separator) + ".class"; + + for (String path : this.clzPaths) { + + String clzFileName = path + File.separator + 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 byte[] readBinaryCode_V1(String className) { + for (String clzPath : clzPaths) { File file = new File(clzPath + className.replace(".", "\\") + ".class"); - + if (!file.exists()) continue; @@ -52,24 +109,17 @@ public byte[] readBinaryCode(String className) { } - - public void addClassPath(String path) { - if (path == null) - return; - - clzPaths.add(path); - } - - - - public String getClassPath(){ + public String getClassPath_V1(){ StringBuilder sb = new StringBuilder(); - int length = clzPaths.size(); + + int length = this.clzPaths.size(); + for (int i = 0 ; i < length; ++i) { - sb.append(clzPaths.get(i)); + sb.append(this.clzPaths.get(i)); if (i + 1 < length) sb.append(";"); } + return sb.toString(); } diff --git a/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..b0229c7435 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/loader/ClassFileParser.java @@ -0,0 +1,166 @@ +package com.donaldy.jvm.loader; + +import com.donaldy.jvm.clz.AccessFlag; +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.clz.ClassIndex; +import com.donaldy.jvm.constant.*; +import com.donaldy.jvm.field.Field; +import com.donaldy.jvm.method.Method; + +import java.io.UnsupportedEncodingException; + + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ByteCodeIterator iter = new ByteCodeIterator(codes); + ClassFile clzFile = new ClassFile(); + + 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 = parseClassIndex(iter); + clzFile.setClassIndex(clzIndex); + + ////////////Third times JVM homework//////////// + parseInterfaces(iter); //本次作业无interface + + parseFileds(clzFile, iter); + + parseMethods(clzFile, iter); + + 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) { + //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 utf8Info = new UTF8Info(pool); + utf8Info.setLength(len); + utf8Info.setValue(value); + pool.addConstantInfo(utf8Info); + } 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) { + //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); + } + } + + 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(); + + //System.out.println("fileCount : " + 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(); + + for (int i = 1; i <= methodCount; i++) { + Method m = Method.parse(clzFile, iter); + clzFile.addMethod(m); + } + + } + +} diff --git a/group24/448641125/src/com/donaldy/jvm/method/Method.java b/group24/448641125/src/com/donaldy/jvm/method/Method.java new file mode 100644 index 0000000000..a69ff696b8 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/method/Method.java @@ -0,0 +1,89 @@ +package com.donaldy.jvm.method; + +import com.donaldy.jvm.attr.*; +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.constant.ConstantPool; +import com.donaldy.jvm.constant.UTF8Info; +import com.donaldy.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){ + + int accessFlag = iter.nextU2ToInt(); + int nameIndex = iter.nextU2ToInt(); + int descriptorIndex = iter.nextU2ToInt(); + + int attributeCount = iter.nextU2ToInt(); + System.out.println("attributeCount : " + attributeCount); + + int attrNameIndex = iter.nextU2ToInt(); + if (!"Code".equals(clzFile.getConstantPool().getUTF8String(attrNameIndex))) + throw new RuntimeException("attributeInfo : " + attrNameIndex); + + int attrLen = iter.nextU4ToInt(); + int maxStack = iter.nextU2ToInt(); + int maxLocals = iter.nextU2ToInt(); + int codeLen = iter.nextU4ToInt(); + String code = iter.nextUxToHexString(codeLen); + + CodeAttr codeAttr = new CodeAttr(attrNameIndex, attrLen, maxStack, maxLocals, codeLen, code); + + int exceptionLen = iter.nextU2ToInt(); + System.out.println("execptionLen : " + exceptionLen); + + int attributesCount = iter.nextU2ToInt(); + System.out.println("attributeCount : " + attributesCount); + + LineNumberTable lnTable = LineNumberTable.parse(iter); + codeAttr.setLineNumberTable(lnTable); + + LocalVariableTable lvTable = LocalVariableTable.parse(iter); + codeAttr.setLocalVariableTable(lvTable); + + + Method method = new Method(clzFile, accessFlag, nameIndex, descriptorIndex); + + method.setCodeAttr(codeAttr); + return method; + + } +} diff --git a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java index 2ed50aa8b5..8610fda4c9 100644 --- a/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java +++ b/group24/448641125/src/com/donaldy/jvm/test/ClassFileloaderTest.java @@ -1,5 +1,10 @@ package com.donaldy.jvm.test; +import com.donaldy.jvm.clz.ClassFile; +import com.donaldy.jvm.clz.ClassIndex; +import com.donaldy.jvm.constant.*; +import com.donaldy.jvm.field.Field; +import com.donaldy.jvm.method.Method; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -7,17 +12,17 @@ import com.donaldy.jvm.loader.ClassFileLoader; - - +import java.util.List; public class ClassFileloaderTest { - + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + static String path1 = "D:\\tools\\Code\\Y_Repository\\coding2017\\group24\\448641125\\out\\production\\448641125\\"; static String path2 = "C:\\temp"; - - + + static ClassFile clzFile = null; @Before public void setUp() throws Exception { @@ -69,10 +74,7 @@ public void testMagicNumber(){ Assert.assertEquals("cafebabe", acctualValue); } - - - - + private String byteToHexString(byte[] codes ){ @@ -89,4 +91,189 @@ private String byteToHexString(byte[] codes ){ return buffer.toString(); } + + /** + * ---------------------------------------------------------------------- + */ + + + @Test + public void testVersion(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + + Assert.assertEquals(0, clzFile.getMinorVersion()); + Assert.assertEquals(52, clzFile.getMajorVersion()); + + } + + @Test + public void testConstantPool(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + + 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(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + + 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(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + + 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(){ + + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(this.path1); + clzFile = loader.loadClass("com.donaldy.jvm.test.EmployeeV1"); + + + 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); + } + } diff --git a/group24/448641125/src/com/donaldy/jvm/util/Util.java b/group24/448641125/src/com/donaldy/jvm/util/Util.java new file mode 100644 index 0000000000..f316117565 --- /dev/null +++ b/group24/448641125/src/com/donaldy/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.donaldy.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 ; --i) + stack.push(intArr[i]); + StackUtil.reverse(stack); + for (int i = 4 ; i >= 0; --i) { + Assert.assertEquals((int)stack.pop(), (int)intArr[i]); + } + } + + @Test + public void testRemove() { + Stack stack = new Stack(); + Integer [] intArr = {5, 4, 3, 2, 1}; + for (int i = 4; i >= 0 ; --i) + stack.push(intArr[i]); + + StackUtil.remove(stack, 2); + for (int i = 0; i < 5; ++i) { + if (i == 3) + continue; + System.out.println("stack: " + stack.peek() + " i : " + (int) intArr[i]); + Assert.assertEquals((int)stack.pop(), (int)intArr[i]); + } + } + + @Test + public void testGetTop() { + Stack stack = new Stack(); + Integer [] intArr = {5, 4, 3, 2, 1}; + for (int i = 4; i >= 0 ; --i) + stack.push(intArr[i]); + + int len = 3; + Object [] arr = StackUtil.getTop(stack, len); + + for (int i = 0 ; i < arr.length ; ++i) { + Assert.assertEquals((int)arr[i], (int)intArr[i]); + } + + for (int i = 0; i < 5; ++i) { + Assert.assertEquals((int)intArr[i], (int)stack.pop()); + } + } + + @Test + public void testIsValidPairs() { + + String str1 = "([e{d}f])"; + Assert.assertEquals(true, StackUtil.isValidPairs(str1)); + + String str2 = "([b{x]y})"; + Assert.assertEquals(false, StackUtil.isValidPairs(str2)); + + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..0dedb245ee --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..0d2525e416 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,76 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.clz; + + +import com.coding.mini_jvm.src.com.coderising.jvm.constant.ClassInfo; +import com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..4dc110fe5f --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..227bb010a1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..e7c849ca59 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..d4210647be --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,36 @@ +package com.coding.mini_jvm.src.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; + } + + @Override + public String toString() { + return "ConstantPool{" + + "constantInfos=" + constantInfos + + '}'; + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..1808a35c65 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..dc62d438e6 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..b8b9da7353 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..bf19f681d8 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..05a4afad6a --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..61f20ed8f1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package com.coding.mini_jvm.src.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/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..27d0c63af0 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,52 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.loader; + +import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + private static final int U1 = 1; + private static final int U2 = 2; + private static final int U4 = 4; + private static final int U8 = 8; + private byte[] bytes; + private int cursor; + + public ByteCodeIterator(byte[] bytes) { + this.bytes = bytes; + } + + public String readTwoBytesToString() { + String ret = Util.byte2String(bytes, cursor, U2); + cursor += U2; + return ret; + } + + public String readBytesToString(int len) { + String ret = Util.byte2String(bytes, cursor, len); + cursor += len; + return ret; + } + + + public int readTwoBytesToInt() { + int ret = Util.bytes2Int(bytes, cursor, U2); + cursor += U2; + return ret; + } + + public int readByteToInt() { + int ret = Util.bytes2Int(bytes, cursor, U1); + cursor += U1; + return ret; + } + + + + + public int skip(int len) { + if (cursor + len < 0 || cursor + len > bytes.length - 1) { + throw new IndexOutOfBoundsException(); + } + cursor += len; + return cursor; + } +} 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 new file mode 100644 index 0000000000..452f6bce7d --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -0,0 +1,72 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.loader; + +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.util.ArrayList; +import java.util.List; + + + +public class ClassFileLoader { + + private static final String CLASS_FILE_SUFFIX = ".class"; + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + String classPath = getClassPath(); + String[] paths = classPath.split(File.pathSeparator); + className = className.replace('.', File.separatorChar) ; + for (String path : paths) { + String clzFilename = path + File.separator + className + CLASS_FILE_SUFFIX; + byte[] data = loadClassFile(clzFilename); + if (data != null) { + return data; + } + } + return null; + } + + private byte[] loadClassFile(String clzFileName) { + File file = new File(clzFileName); + BufferedInputStream bis = null; + try { + bis = new BufferedInputStream(new FileInputStream(file)); + byte[] data = new byte[bis.available()]; + bis.read(data); + return data; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + public void addClassPath(String path) { + if (this.clzPaths.contains(path)) { + return; + } + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuffer sb = new StringBuffer(); + for (String path : clzPaths) { + sb.append(path); + sb.append(";"); + } + String path = sb.toString(); + return path.substring(0, path.lastIndexOf(";")); + } + + + public ClassFile loadClass(String className) { + byte[] data = readBinaryCode(className); + ClassFileParser classFileParser = new ClassFileParser(); + return classFileParser.parse(data); + } +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..542968c809 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,103 @@ +package com.coding.mini_jvm.src.com.coderising.jvm.loader; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.AccessFlag; +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; + + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + ClassFile classFile = new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(codes); + //跳过魔数 + iterator.skip(4); + //次版本号 + classFile.setMinorVersion(iterator.readTwoBytesToInt()); + //主版本号 + classFile.setMajorVersion(iterator.readTwoBytesToInt()); + //解析常量池 + classFile.setConstPool(parseConstantPool(iterator)); + //访问限制符 + classFile.setAccessFlag(parseAccessFlag(iterator)); + //当前类/父类 + classFile.setClassIndex(parseClassIndex(iterator)); + return classFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.readTwoBytesToInt()); + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.readTwoBytesToInt()); + classIndex.setSuperClassIndex(iter.readTwoBytesToInt()); + return classIndex; + } + + private ConstantPool parseConstantPool(ByteCodeIterator iterator) { + ConstantPool constantPool = new ConstantPool(); + //读取常量个数 + int constantPoolCount = iterator.readTwoBytesToInt(); + constantPool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i < constantPoolCount; i++) { + int flag = iterator.readByteToInt(); + int utf8Index; + int clzIndex; + int nameAndTypeIndex; + switch (flag) { + case 1: + int length = iterator.readTwoBytesToInt(); + String val = iterator.readBytesToString(length); + UTF8Info utf8Info = new UTF8Info(constantPool); + utf8Info.setLength(length); + utf8Info.setValue(val); + constantPool.addConstantInfo(utf8Info); + break; + case 7: + utf8Index = iterator.readTwoBytesToInt(); + ClassInfo classInfo = new ClassInfo(constantPool); + classInfo.setUtf8Index(utf8Index); + constantPool.addConstantInfo(classInfo); + break; + case 8: + utf8Index = iterator.readTwoBytesToInt(); + StringInfo stringInfo = new StringInfo(constantPool); + stringInfo.setIndex(utf8Index); + constantPool.addConstantInfo(stringInfo); + break; + case 9: + clzIndex = iterator.readTwoBytesToInt(); + nameAndTypeIndex = iterator.readTwoBytesToInt(); + FieldRefInfo fieldRefInfo = new FieldRefInfo(constantPool); + fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + fieldRefInfo.setClassInfoIndex(clzIndex); + constantPool.addConstantInfo(fieldRefInfo); + break; + case 10: + clzIndex = iterator.readTwoBytesToInt(); + nameAndTypeIndex = iterator.readTwoBytesToInt(); + MethodRefInfo methodRefInfo = new MethodRefInfo(constantPool); + methodRefInfo.setClassInfoIndex(clzIndex); + methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex); + constantPool.addConstantInfo(methodRefInfo); + break; + case 12: + utf8Index = iterator.readTwoBytesToInt(); + int utf8Index1 = iterator.readTwoBytesToInt(); + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(constantPool); + nameAndTypeInfo.setIndex1(utf8Index); + nameAndTypeInfo.setIndex2(utf8Index1); + constantPool.addConstantInfo(nameAndTypeInfo); + break; + default: + throw new RuntimeException("flag "+ flag +" is not exists"); + } + } + return constantPool; + } + + +} diff --git a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/util/Util.java b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..8811e3541c --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,40 @@ +package com.coding.mini_jvm.src.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 int bytes2Int(byte[] b, int start, int len) { + int sum = 0; + int end = start + len; + for (int i = start; i < end; i++) { + int n = ((int) b[i]) & 0xff; + n <<= (--len) * 8; + sum = n + sum; + } + return sum; + } + + + public static String byte2String(byte[] b, int start, int len) { + return new String(b, start, len); + } + + public static String byteToHexString(byte[] codes ){ + StringBuffer buffer = new StringBuffer(); + for(int i=0;i= 0; i--) { + sb.append(elementData.get(i).toString()); + sb.append(","); + } + return sb.substring(0, sb.lastIndexOf(",")); + } } diff --git a/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java b/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java index 0e40bc38a8..75455935be 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java +++ b/group24/494800949/src/main/java/com/coding/week3/download/FileDownloader.java @@ -68,7 +68,6 @@ public void execute() throws IOException { lastLen = fileLength % nThread; perLenOfThread = (fileLength + (nThread - lastLen)) / nThread; } - //计算 //启动线程 for (int i = 0; i < nThread; i++) { @@ -87,7 +86,7 @@ public void execute() throws IOException { } catch (ConnectionException e) { e.printStackTrace(); - }finally{ + } finally{ if(conn != null){ conn.close(); } diff --git a/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java b/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java index fe9b0a9079..9617474677 100644 --- a/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java +++ b/group24/494800949/src/main/java/com/coding/week3/download/impl/ConnectionImpl.java @@ -6,6 +6,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.util.concurrent.TimeUnit; public class ConnectionImpl implements Connection { @@ -48,8 +49,20 @@ public void close() { } @Override - public InputStream getInputStream() throws IOException { - return httpURLConnection.getInputStream(); + public InputStream getInputStream() { + try { + return httpURLConnection.getInputStream(); + } catch (IOException e) { + for (int i = 0; i < 5; i++) { + try { + TimeUnit.SECONDS.sleep(10); + return httpURLConnection.getInputStream(); + } catch (IOException | InterruptedException e1) { + e1.printStackTrace(); + } + } + throw new RuntimeException(e); + } } } diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java new file mode 100644 index 0000000000..2ef5729241 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/DownloadTask.java @@ -0,0 +1,93 @@ +package com.coding.week3.download1; + +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionManager; + +import java.io.*; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by Administrator on 2017/3/31 0031. + */ +public class DownloadTask implements Runnable { + private static final int BUFF_SIZE = 1024; + ConnectionManager connectionManager; + int startPos; + int endPos; + RandomAccessFile ras; + AtomicInteger totalDownloadBytesCount; + AtomicInteger eachThreadDownloadBytesCount; + String url; + + public DownloadTask(String url, ConnectionManager connectionManager, int startPos, int endPos, RandomAccessFile ras, AtomicInteger totalDownloadBytesCount) { + this.url = url; + this.connectionManager = connectionManager; + this.startPos = startPos; + this.endPos = endPos; + this.ras = ras; + this.totalDownloadBytesCount = totalDownloadBytesCount; + this.eachThreadDownloadBytesCount = new AtomicInteger(0); + } + + @Override + public void run() { + Connection conn = null; + InputStream is = null; + try { + conn = connectionManager.open(url); + is = getInputStream(conn); + is.skip(startPos); + ras.seek(startPos); + byte[] bytes = new byte[BUFF_SIZE]; + int hasRead; + int readTimes = (endPos - startPos) / BUFF_SIZE + 4; + for (int i = 0; i < readTimes; i++) { + hasRead = is.read(bytes); + if (hasRead == -1) { + break; + } + ras.write(bytes, 0, hasRead); + totalDownloadBytesCount.getAndAdd(hasRead); + eachThreadDownloadBytesCount.getAndAdd(hasRead); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + + private InputStream getInputStream(Connection connection){ + Connection conn = null; + InputStream is = null; + try { + conn = connectionManager.open(url); + is = conn.getInputStream(); + return is; + } catch (IOException e) { + for (int i = 0; i < 5; i++) { + try { + TimeUnit.SECONDS.sleep(5); + conn = connectionManager.open(url); + is = conn.getInputStream(); + is.skip(startPos); + break; + } catch (InterruptedException e1) { + e1.printStackTrace(); + } catch (IOException e1) { + System.out.println(e1.getMessage()); + } + } + throw new RuntimeException("连接超时", e); + } + + } + + + + + public int getEachThreadDownloadBytesCount() { + return eachThreadDownloadBytesCount.get(); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java new file mode 100644 index 0000000000..72b11c120e --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/FileDownloader.java @@ -0,0 +1,167 @@ +package com.coding.week3.download1; + + +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionException; +import com.coding.week3.download1.api.ConnectionManager; +import com.coding.week3.download1.api.DownloadListener; + +import java.io.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public class FileDownloader { + + String url; + + DownloadListener listener; + + ConnectionManager cm; + + String savePath; + + int nThread; + + int fileLength; + + AtomicInteger downloadBytesCount; + + public FileDownloader(String _url) { + this.url = _url; + } + + public FileDownloader(int nThread, String savePath, String url) { + this.nThread = nThread; + this.savePath = savePath; + this.url = url; + downloadBytesCount = new AtomicInteger(0); + } + + 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; + DownloadTask[] downloadTasks = new DownloadTask[nThread]; + try { + + //根据文件长度为每个线程分配下载字节数量 + conn = cm.open(this.url); + fileLength = conn.getContentLength(); + //已读字节数量 + ExecutorService executorService = Executors.newFixedThreadPool(nThread); +// int[][] allotSize = alloctSize(nThread, fileLength); + int[][] allotSize = readPos(nThread, fileLength); + for (int i = 0; i < nThread; i++) { + RandomAccessFile ras = new RandomAccessFile(savePath, "rw"); + downloadTasks[i] = new DownloadTask(url, cm, allotSize[0][i], + allotSize[1][i], ras , downloadBytesCount); + executorService.execute(downloadTasks[i]); + } + //关闭线程池 + executorService.shutdown(); + boolean isTermination ; + do { + isTermination = executorService.awaitTermination(500, TimeUnit.MILLISECONDS); + if (fileLength > 0) + System.out.println("已下载:"+(downloadBytesCount.get()/1024)+"K,百分比:"+ (downloadBytesCount.get()/ (fileLength/100))+"%" ); + //循环等待,直到线程全部关闭 + } while (!isTermination); + System.out.println(111111); + + } catch (ConnectionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally{ + writePos(downloadTasks); + if(conn != null){ + conn.close(); + } + } + } + + private int[][] alloctSize(int nThread, int fileLength){ + int[][] allotSize = new int[2][nThread]; + int perLenOfTask = fileLength / nThread; + int lastLen = fileLength % nThread; + for (int i = 0; i < nThread; i++) { + int start = perLenOfTask * i; + int end = perLenOfTask * (i + 1) - 1; + if (i == nThread - 1) { + end += lastLen; + } + allotSize[0][i] = start; + allotSize[1][i] = end; + } + return allotSize; + } + + public void setListener(DownloadListener listener) { + this.listener = listener; + } + + public void setConnectionManager(ConnectionManager ucm){ + this.cm = ucm; + } + + public DownloadListener getListener(){ + return this.listener; + } + + private void writePos(DownloadTask[] tasks){ + File file = new File(""); + File posFile = new File(file.getAbsolutePath()+"/tempPos"); + RandomAccessFile ras = null; + try { + ras = new RandomAccessFile(posFile, "rw"); + if (!posFile.exists()) { + posFile.createNewFile(); + } + for (int i = 0; i < tasks.length; i++) { + ras.writeInt(tasks[i].getEachThreadDownloadBytesCount()); + ras.writeInt(tasks[i].endPos); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private int[][] readPos(int nThread, int fileLength){ + File file = new File(""); + File posFile = new File(file.getAbsolutePath()+"/tempPos"); + if (!posFile.exists()) { + return alloctSize(nThread, fileLength); + } + RandomAccessFile ras = null; + int[][] pos = new int[2][nThread]; + try { + ras = new RandomAccessFile(posFile, "r"); + ras.seek(0); + for (int i = 0; i < nThread; i++) { + pos[0][i] = ras.readInt(); + pos[1][i] = ras.readInt(); + } + return pos; + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return pos; + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java new file mode 100644 index 0000000000..0811902dda --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/Connection.java @@ -0,0 +1,26 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; +import java.io.InputStream; + +public interface Connection { + /** + * 给定开始和结束位置, 读取数据, 返回值是字节数组 + * @param startPos 开始位置, 从0开始 + * @param endPos 结束位置 + * @return + */ + byte[] read(int startPos, int endPos) throws IOException; + /** + * 得到数据内容的长度 + * @return + */ + int getContentLength(); + + /** + * 关闭连接 + */ + void close(); + + InputStream getInputStream() throws IOException; +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java new file mode 100644 index 0000000000..b1d8dddc42 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionException.java @@ -0,0 +1,12 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; + +public class ConnectionException extends IOException { + public ConnectionException() { + } + + public ConnectionException(String message) { + super(message); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java new file mode 100644 index 0000000000..f9ab90bc59 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionManager.java @@ -0,0 +1,13 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; +import java.net.MalformedURLException; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + Connection open(String url) throws IOException; +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java new file mode 100644 index 0000000000..653d9520a4 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/ConnectionRefuseException.java @@ -0,0 +1,23 @@ +package com.coding.week3.download1.api; + +import java.io.IOException; + +/** + * Created by Administrator on 2017/4/2 0002. + */ +public class ConnectionRefuseException extends IOException{ + public ConnectionRefuseException() { + } + + public ConnectionRefuseException(String message) { + super(message); + } + + public ConnectionRefuseException(String message, Throwable cause) { + super(message, cause); + } + + public ConnectionRefuseException(Throwable cause) { + super(cause); + } +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java b/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java new file mode 100644 index 0000000000..2195dd9be0 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.coding.week3.download1.api; + +public interface DownloadListener { + void notifyFinished(); +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java new file mode 100644 index 0000000000..3e8773ecca --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionImpl.java @@ -0,0 +1,55 @@ +package com.coding.week3.download1.impl; + +import com.coding.week3.download1.api.Connection; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + + +public class ConnectionImpl implements Connection { + + private HttpURLConnection httpURLConnection; + + public ConnectionImpl() { + } + + public ConnectionImpl(HttpURLConnection httpURLConnection) { + this.httpURLConnection = httpURLConnection; + } + + + @Override + public byte[] read(int startPos, int endPos) throws IOException { + if (startPos < 0 || endPos < 0 || endPos > getContentLength()) { + throw new IndexOutOfBoundsException(); + } + if (startPos >= endPos) { + throw new IllegalArgumentException(); + } + byte[] bytes = new byte[endPos - startPos + 1]; + + InputStream inputStream = httpURLConnection.getInputStream(); + BufferedInputStream bis = new BufferedInputStream(inputStream); + bis.read(bytes, startPos ,bytes.length-1); + return bytes; + } + + + @Override + public int getContentLength() { + return httpURLConnection.getContentLength(); + } + + @Override + public void close() { + httpURLConnection.disconnect(); + } + + @Override + public InputStream getInputStream() throws IOException { + return httpURLConnection.getInputStream(); + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..927fc30d90 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week3/download1/impl/ConnectionManagerImpl.java @@ -0,0 +1,59 @@ +package com.coding.week3.download1.impl; + + +import com.coding.week3.download1.api.Connection; +import com.coding.week3.download1.api.ConnectionManager; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws IOException { + HttpURLConnection httpURLConnection = null; + // 统一资源 + URL realurl = new URL(url); + // 连接类的父类,抽象类 + URLConnection urlConnection = realurl.openConnection(); + // http的连接类 + httpURLConnection = (HttpURLConnection) urlConnection; + //设置属性 + setHeader(httpURLConnection); + + //设置连接超时时间 + setWaitTime(httpURLConnection); + + // 打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。 + httpURLConnection.connect(); + return new ConnectionImpl(httpURLConnection); + } + + private void setHeader(HttpURLConnection con){ + con.setRequestProperty( + "User-Agent", + "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.3) Gecko/2008092510 Ubuntu/8.04 (hardy) Firefox/3.0.3"); + con.setRequestProperty("Accept-Language", "en-us,en;q=0.7,zh-cn;q=0.3"); + con.setRequestProperty("Accept-Encoding", "aa"); + con.setRequestProperty("Accept-Charset", + "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); + con.setRequestProperty("Keep-Alive", "300"); + con.setRequestProperty("Connection", "keep-alive"); + con.setRequestProperty("If-Modified-Since", + "Fri, 02 Jan 2009 17:00:05 GMT"); + con.setRequestProperty("If-None-Match", "\"1261d8-4290-df64d224\""); + con.setRequestProperty("Cache-Control", "max-age=0"); + con.setRequestProperty("Referer", + "http://www.skycn.com/soft/14857.html"); + } + + + private void setWaitTime(HttpURLConnection con) { + //防止网络阻塞,设置指定的超时时间;单位都是ms。超过指定时间,就会抛出异常 + con.setConnectTimeout(10000); //连接超时设置 + con.setReadTimeout(10000); //读取超时设置 + } + +} diff --git a/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java b/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..bd31cd26f3 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week4/linklist/LRUPageFrame.java @@ -0,0 +1,157 @@ +package com.coding.week4.linklist; + +/** + * 用双向链表实现LRU算法 + * @author liuxin + * + */ +public class LRUPageFrame { + + private static class Node { + + Node prev; + Node next; + int pageNum; + + Node() { + } + + public Node(Node prev, int pageNum, Node next) { + this.prev = prev; + this.next = next; + this.pageNum = pageNum; + } + } + + private int capacity; + private int size; + + private Node first;// 链表头 + private Node last;// 链表尾 + + + public LRUPageFrame(int capacity) { + + this.capacity = capacity; + + } + + /** + * 获取缓存中对象 + * + * @param + * @return + */ + public void access(int pageNum) { + if (!isFull()) { + addFirst(pageNum); + } else { + if (contains(pageNum)) { + removePage(pageNum); + addFirst(pageNum); + } else { + removeLast(); + addFirst(pageNum); + } + } + } + + public boolean contains(int pageNum) { + Node node = first; + if (first == null) + return false; + do { + if (pageNum == node.pageNum) + return true; + node = node.next; + } while (node != null ); + return false; + } + + + public void addFirst(int pageNum){ + Node node = new Node(null, pageNum, null); + if (first == null) { + first = node; + last = node; + } else { + Node oldFirst = first; + first = node; + node.next = oldFirst; + oldFirst.prev = node; + } + size++; + } + + + public boolean isFull () { + return size == capacity; + } + + + public void addLast(int pageNum) { + Node oldLast = last; + Node node = new Node(oldLast, pageNum, null); + oldLast.next = node; + last = node; + size++; + } + + + public int removeLast(){ + Node oldLast = last; + last = oldLast.prev; + last.next = null; + size--; + return oldLast.pageNum; + } + + + public void removePage(int pageNum){ + Node node = first; + if (first == null) { + return; + } + do { + if (node.pageNum == pageNum) { + if (node == first) { + removeFirst(); + } else if (node == last) { + removeLast(); + } else { + Node pre = node.prev; + Node nex = node.next; + pre.next = nex; + nex.prev = pre; + size--; + } + return; + } + node = node.next; + } while (node != null); + } + + private void removeFirst() { + Node node = first; + first = node.next; + first.prev = null; + node.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/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java b/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java new file mode 100644 index 0000000000..1285ed8fa1 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week4/linklist/LinkedList.java @@ -0,0 +1,126 @@ +package com.coding.week4.linklist; + + +import com.coding.weak1.Iterator; +import com.coding.weak1.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/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java b/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java new file mode 100644 index 0000000000..7b750b3549 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/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/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..a03f29c0c3 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/ClassFileloaderTest.java @@ -0,0 +1,173 @@ +package com.coding.mini_jvm.test; + +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassFile; +import com.coding.mini_jvm.src.com.coderising.jvm.clz.ClassIndex; +import com.coding.mini_jvm.src.com.coderising.jvm.constant.*; +import com.coding.mini_jvm.src.com.coderising.jvm.loader.ClassFileLoader; +import com.coding.mini_jvm.src.com.coderising.jvm.util.Util; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + + + + +public class ClassFileloaderTest { + + + static String path1 = "H:\\sourceCode\\coding2017\\group24\\494800949\\build\\classes\\test"; + 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 = "com.coding.mini_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.coding.mini_jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1058, byteCodes.length); + + } + + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.coding.mini_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()); + } +} diff --git a/group24/494800949/src/test/java/com/coding/mini_jvm/test/EmployeeV1.java b/group24/494800949/src/test/java/com/coding/mini_jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..1d3262dd85 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/mini_jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.coding.mini_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/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java index 5b423f145f..524e3aaabb 100644 --- a/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java +++ b/group24/494800949/src/test/java/com/coding/week3/FileDownloaderTest.java @@ -1,15 +1,16 @@ package com.coding.week3; -import com.coding.week3.download.FileDownloader; -import com.coding.week3.download.api.ConnectionManager; -import com.coding.week3.download.api.DownloadListener; -import com.coding.week3.download.impl.ConnectionManagerImpl; +import com.coding.week3.download1.api.ConnectionManager; +import com.coding.week3.download1.api.DownloadListener; +import com.coding.week3.download1.impl.ConnectionManagerImpl; +import com.coding.week3.download1.FileDownloader; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import java.io.*; +import java.io.File; +import java.io.IOException; public class FileDownloaderTest { @@ -27,10 +28,12 @@ public void tearDown() throws Exception { @Test public void testDownload() throws IOException { -// String url = "http://101.95.48.97:8005/res/upload/interface/apptutorials/manualstypeico/6f83ce8f-0da5-49b3-bac8-fd5fc67d2725.png"; + String url = "http://101.95.48.97:8005/res/upload/interface/apptutorials/manualstypeico/6f83ce8f-0da5-49b3-bac8-fd5fc67d2725.png"; // String url = "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-arm32-vfp-hflt.tar.gz"; // String url = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1490808670106&di=48aa6fb7af641f0cb6f9e19120b60c7c&imgtype=0&src=http%3A%2F%2Fwww.ntjoy.com%2Fliv_loadfile%2Fhealth%2Fdzcs%2Fnvr%2Ffold1%2F1360480639_97304600.jpg"; - String url = "https://download.jetbrains.com/idea/ideaIU-2017.1.exe"; +// String url = "https://download.jetbrains.com/idea/ideaIU-2017.1.exe"; +// String url = "https://nodejs.org/dist/v6.10.1/node-v6.10.1-win-x64.zip"; +// String url = "http://download.oracle.com/otn-pub/java/jdk/8u121-b13-demos/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-windows-x64-demos.zip"; String path = new File("").getAbsolutePath(); String filename = url.substring(url.lastIndexOf("/"), url.length()); filename = path +File.separator + filename; @@ -49,17 +52,17 @@ public void notifyFinished() { downloader.execute(); - // 等待多线程下载程序执行完毕 - while (!downloadFinished) { - try { - System.out.println("还没有下载完成,休眠五秒"); - //休眠5秒 - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - System.out.println("下载完成!"); +// // 等待多线程下载程序执行完毕 +// while (!downloadFinished) { +// try { +// System.out.println("还没有下载完成,休眠五秒"); +// //休眠5秒 +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } +// System.out.println("下载完成!"); diff --git a/group24/494800949/src/test/java/com/coding/week4/LRUPageFrameTest.java b/group24/494800949/src/test/java/com/coding/week4/LRUPageFrameTest.java new file mode 100644 index 0000000000..880080eb2e --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week4/LRUPageFrameTest.java @@ -0,0 +1,32 @@ +package com.coding.week4; + +import com.coding.week4.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()); + } + +} diff --git a/group24/494800949/src/test/java/com/coding/week5/stack/StackUtilTest.java b/group24/494800949/src/test/java/com/coding/week5/stack/StackUtilTest.java new file mode 100644 index 0000000000..8e14b7cf00 --- /dev/null +++ b/group24/494800949/src/test/java/com/coding/week5/stack/StackUtilTest.java @@ -0,0 +1,56 @@ +package com.coding.week5.stack; + +import com.coding.weak1.Stack; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/9 0009. + */ +public class StackUtilTest { + + private Stack stack; + + @Before + public void setup() { + stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + + } + @Test + public void reverse() throws Exception { + Assert.assertEquals("4,3,2,1",stack.toString()); + StackUtil.reverse(stack); + Assert.assertEquals("1,2,3,4",stack.toString()); + } + + @Test + public void remove() throws Exception { + StackUtil.remove(stack, 3); + Assert.assertEquals(stack.toString(), "4,2,1"); + } + + @Test + public void getTop() throws Exception { + Object[] objects = StackUtil.getTop(stack, 2); + Assert.assertEquals(objects[0], 4); + Assert.assertEquals(objects[1], 3); + } + + @Test + public void isValidPairs() throws Exception { + String str = "[abdd]}"; + Assert.assertEquals(StackUtil.isValidPairs(str), false); + str = "{add{ad[ddd]}}"; + Assert.assertEquals(StackUtil.isValidPairs(str), true); + str = "{add{ad[d(dd]}}"; + Assert.assertEquals(StackUtil.isValidPairs(str), false); + str = "{add{ad[d(d)d]}dfd}"; + Assert.assertEquals(StackUtil.isValidPairs(str), true); + } + +} \ No newline at end of file diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/ArrayList.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/ArrayList.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/ArrayList.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/ArrayList.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/BinaryTreeNode.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/BinaryTreeNode.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/BinaryTreeNode.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/BinaryTreeNode.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Iterator.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Iterator.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Iterator.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Iterator.java diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java new file mode 100644 index 0000000000..55d8839b02 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java @@ -0,0 +1,400 @@ +package com.github.wdn.coding2017.basic; + +/** + * TODO 只是简单实现 缺少对边界的处理 + * 参考JDK源码改为更优雅的实现 + */ + +public class LinkedList implements List { + + private Node head; + private Node tail; + private int size; + + public LinkedList(){ + this.head=null; + this.tail=null; + } + public void add(Object o){ + Node newNode = new Node(o); + if (head == null) { + head = newNode; + tail = newNode; + }else{ + tail.setNext(newNode); + newNode.setPre(tail); + tail = newNode; + } + size++; + } + public void add(int index , Object o){ + checkIndex(index); + Node indexNode = getNode(index); + Node newNode = new Node(o); + Node pre = indexNode.getPre(); + if(pre!=null){ + pre.setNext(newNode); + }else{ + head = newNode; + } + newNode.setPre(pre); + newNode.setNext(indexNode); + indexNode.setPre(newNode); + size++; + } + private void checkIndex(int index){ + if(index >= size || index <0){ + throw new IndexOutOfBoundsException(); + } + } + private Node getNode(int index){ + checkIndex(index); + // TODO这里可以优化,先判断index在前半部还是后半部分 然后确定从头部或者尾部查找 + Node result=null; + if(index==0){ + return head; + } + if(index==size-1){ + return tail; + } + Node current = head; + for (int i = 0; i < index; i++) { + result = current.getNext(); + current = result; + } + return result; + } + public Object get(int index){ + return getNode(index).getData(); + } + public Object remove(int index){ + checkIndex(index); + Node indexNode = getNode(index); + Node pre = indexNode.getPre(); + Node next = indexNode.getNext(); + if(pre!=null){ + pre.setNext(next); + }else{ + head = next; + } + if(next!=null){ + next.setPre(pre); + }else{ + tail = pre; + } + size--; + return indexNode.getData(); + } + + public int size(){ + return size; + } + + public void addFirst(Object o){ + Node newNode = new Node(o); + if (size==0){ + add(o); + return; + } + head.setPre(newNode); + newNode.setNext(head); + head = newNode; + size++; + } + public void addLast(Object o){ + if (size == 0) { + add(o); + return; + } + Node newNode = new Node(o); + tail.setNext(newNode); + newNode.setPre(tail); + tail = newNode; + size++; + } + public Object removeFirst(){ + if(size<1){ + throw new IllegalArgumentException(); + } + if(size==1){ + tail=null; + } + Node next = head.getNext(); + Node oldHead = head; + head.setPre(null); + head = next; + oldHead.setNext(null); + size--; + return oldHead; + } + public Object removeLast(){ + if(size<1){ + throw new IllegalArgumentException(); + } + if(size==1){ + head=null; + } + Node oldTail = tail; + Node pre = tail.getPre(); + tail = pre; + tail.setNext(null); + oldTail.setPre(null); + size--; + return oldTail; + } + public Iterator iterator(){ + + return null; + } + + /** + * JDK 中使用构造方法的方式设置next和pre减少不必要的getset方法更优雅 + */ + private static class Node{ + + Object data; + Node next; + Node pre; + public Node(){ + + } + public Node(Object data){ + this.data = data; + } + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public Node getNext() { + return next; + } + + public void setNext(Node next) { + this.next = next; + } + + public Node getPre() { + return pre; + } + + public void setPre(Node pre) { + this.pre = pre; + } + } + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node current = head; + Node next = current.getNext(); + Node pre = current.getPre(); + while(next!=null){ + Node nNext = next.getNext(); + if(pre!=null){ + pre.setPre(current); + } + if(current!=null){ + current.setPre(next); + current.setNext(pre); + } + if(next!=null){ + next.setNext(current); + } + pre = current; + current = next; + next = nNext; + } + Node oldHead = head; + head = tail; + tail = oldHead; + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + + */ + public void removeFirstHalf(){ + int removeSize = size/2; + for (int i = 0; i < removeSize; i++) { + removeFirst(); + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param start 开始位置 + * @param length 长度 + */ + public void remove(int start, int length){ + checkIndex(start); + if(length<1){ + return; + } + if(start==0 && length>=size){ + int removeSum = size; + for (int j = 0; j < removeSum; j++) { + removeFirst(); + } + size = size-length; + return; + } + + int customMaxIndex = start+length; + int endIndex = customMaxIndex < size ? customMaxIndex : size; + if(start==0){ + for (int j = 0; j < length; j++) { + removeFirst(); + } + size = size-length; + return; + } + if(endIndex==size){ + int removeSum = size-start; + for (int j = 0; j < removeSum; j++) { + removeLast(); + } + return; + } + Node startNode = getNode(start-1); + Node endNode = getNode(endIndex); + startNode.getNext().setPre(null); + startNode.setNext(endNode); + endNode.getPre().setNext(null); + endNode.setPre(startNode); + 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){ + for (int i = 0; i < list.size; i++) { + if(Integer.parseInt(list.get(i).toString())>=this.size){ + throw new IndexOutOfBoundsException(); + } + } + int[] result = new int[list.size]; + int index = 0; + for (int i = 0; i < this.size; i++) { + if (index==list.size()){ + break; + } + if(Integer.parseInt(list.get(index).toString())==i){ + result[index] = Integer.parseInt(this.get(i).toString()); + index++; + } + } + return result; + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 从当前链表中中删除在list中出现的元素 + + * @param list + */ + + public void subtract(LinkedList list){ + int index = 0; + Object compare = list.get(index); + Node current = head; + while(current!=null && compare!=null){ + Node preCurrent = current; + current = current.getNext(); + // TODO 这里不能删除重复元素只能删除一次 + if(preCurrent.getData().equals(compare)){ + preCurrent.getPre().setNext(preCurrent.getNext()); + preCurrent.getNext().setPre(preCurrent.getPre()); + preCurrent.setPre(null); + preCurrent.setNext(null); + size--; + compare = ++index < list.size ? list.get(index) : null; + } + } + } + + /** + * 已知当前链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 删除表中所有值相同的多余元素(使得操作后的线性表中所有元素的值均不相同) + */ + public void removeDuplicateValues(){ + Node current = head; + Node next = current.getNext(); + while (next!=null){ + if(next.getData().equals(current.getData())){ + Node preNext = next; + next = preNext.getNext(); + current.setNext(preNext.getNext()); + if (next != null) { + next.setPre(current); + } + preNext.setPre(null); + preNext.setNext(null); + size--; + }else{ + current = next; + next = next.getNext(); + } + } + } + + /** + * 已知链表中的元素以值递增有序排列,并以单链表作存储结构。 + * 试写一高效的算法,删除表中所有值大于min且小于max的元素(若表中存在这样的元素) + * @param min + * @param max + */ + public void removeRange(int min, int max){ + int minIndex = -1; + int maxIndex = -1; + int index = 0; + Node current = head; + while (current!=null){ + if(current.getData().equals(min)){ + minIndex = index; + } + if(current.getData().equals(max)){ + maxIndex = index; + } + index++; + current = current.getNext(); + } + if (minIndex > -1 && maxIndex > -1 && min <= max && minIndex + 1 < size) { + remove(minIndex + 1, maxIndex - minIndex - 1); + } + } + + /** + * 假设当前链表和参数list指定的链表均以元素依值递增有序排列(同一表中的元素值各不相同) + * 现要求生成新链表C,其元素为当前链表和list中元素的交集,且表C中的元素有依值递增有序排列 + * @param list + */ + public LinkedList intersection( LinkedList list){ + return null; + } + @Override + public String toString(){ + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("["); + for (int i = 0; i < size; i++) { + stringBuffer.append(get(i)); + if(i!=size-1){ + stringBuffer.append(","); + } + } + stringBuffer.append("]"); + return stringBuffer.toString(); + } +} diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/List.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/List.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/List.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/List.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Queue.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Queue.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Queue.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Queue.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Stack.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Stack.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/basic/Stack.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/Stack.java diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrame.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrame.java new file mode 100644 index 0000000000..7e3c07737d --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrame.java @@ -0,0 +1,49 @@ +package com.github.wdn.coding2017.basic.lru; + +import com.github.wdn.coding2017.basic.LinkedList; + +/** + * 用双向链表实现LRU算法 + * @author liuxin + * + */ +public class LRUPageFrame { + private int capacity; + private LinkedList cache = new LinkedList(); + public LRUPageFrame(int capacity) { + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @return + */ + public void access(int pageNum) { + if(capacity==cache.size()){ + int exist = exist(pageNum); + if(exist>-1){ + cache.addFirst(cache.remove(exist)); + }else{ + cache.removeLast(); + cache.addFirst(pageNum); + } + }else { + cache.addFirst(pageNum); + } + + } + private int exist(int pageNum){ + for (int i = 0; i < cache.size(); i++) { + if(cache.get(i).equals(pageNum)){ + return i; + } + } + return -1; + } + public String toString(){ + return cache.toString().replace("[","").replace("]",""); + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrameTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrameTest.java new file mode 100644 index 0000000000..62edda7ec8 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/lru/LRUPageFrameTest.java @@ -0,0 +1,31 @@ +package com.github.wdn.coding2017.basic.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()); + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackUtil.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackUtil.java new file mode 100644 index 0000000000..1e43329fcc --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/StackUtil.java @@ -0,0 +1,132 @@ +package com.github.wdn.coding2017.basic.stack; + +import com.github.wdn.coding2017.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(); + 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 popObject = s.pop(); + if(popObject.equals(o)){ + break; + } + stack.push(popObject); + } + 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 IndexOutOfBoundsException(); + } + Object[] result = new Object[len]; + Stack stack = new Stack(); + for (int i = 0; i < len; i++) { + Object o = s.pop(); + result[i]=o; + stack.push(o); + } + while (!stack.isEmpty()){ + s.push(stack.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()<2){ + return false; + } + Stack s1 = new Stack(); + Stack s2 = new Stack(); + char[] chars = s.toCharArray(); + int charsLength = chars.length; + if(charsLength%2==1 && isBrackets(chars[charsLength / 2])){ + return false; + } + for (int i = 0; i < charsLength/2; i++) { + char c = chars[i]; + if (isBrackets(c)) { + s1.push(c); + } + } + for (int i = charsLength-1; i > charsLength/2; i--) { + char c = chars[i]; + if (isBrackets(c)) { + s2.push(c); + } + } + if (s1.size() != s2.size()) { + return false; + } + for (int i = 0; i < s1.size(); i++) { + if (!isPairing((Character) s1.pop(), (Character) s2.pop())) { + return false; + } + } + return true; + } + // parenthesis 圆括号 + // square brackets 方括号 + // braces 大括号 + // 这里用bracket表示统称 + private static boolean isBrackets(char c){ + if('['==c||']'==c|| + '('==c||')'==c|| + '{'==c||'}'==c){ + return true; + } + return false; + } + + private static boolean isPairing(char left, char right) { + if(left=='(' && right==')'){ + return true; + }else if(left=='[' && right==']'){ + return true; + }else if(left=='{' && right=='}'){ + return true; + }else { + return false; + } + } +} 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 new file mode 100644 index 0000000000..3a8f013b78 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExpr.java @@ -0,0 +1,90 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +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("[+|\\-|*|/]"); + 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]); + 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); + numStack.push(currentResult); + } else if(!operatorStack.isEmpty() && priorityMap.get(operatorStack.peek()) >= priorityMap.get(operator)){ + 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); + numStack.push(result); + numStack.push(number); + operatorStack.push(operator); + }else { + numStack.push(number); + operatorStack.push(operator); + } + } + while (!operatorStack.isEmpty()) { + 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); + numStack.push(result); + } + return Float.parseFloat(numStack.pop().toString()); + } catch (Exception e) { + e.printStackTrace(); + } + 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/InfixExprTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..a05f9fd578 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/basic/stack/expr/InfixExprTest.java @@ -0,0 +1,50 @@ +package com.github.wdn.coding2017.basic.stack.expr; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by Administrator on 2017/4/13 0013. + */ +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/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtil.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtil.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtil.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtil.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtilTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtilTest.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtilTest.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/array/ArrayUtilTest.java diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/DownloadThread.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/DownloadThread.java new file mode 100644 index 0000000000..7238acf44d --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/DownloadThread.java @@ -0,0 +1,54 @@ +package com.github.wdn.coding2017.coderising.download; + + +import com.github.wdn.coding2017.coderising.download.api.Connection; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +public class DownloadThread extends Thread{ + + Connection conn; + int startPos; + int endPos; + private static final Object lock = new Object(); + private static final File file = new File("E:\\down.jpg"); + private CountDownLatch latch; + public DownloadThread(Connection conn, int startPos, int endPos,CountDownLatch latch){ + this.conn = conn; + this.startPos = startPos; + this.endPos = endPos; + this.latch = latch; + } + public boolean writeFile(){ + if (file.length()==startPos) { + synchronized (lock){ + byte[] image = new byte[0]; + try { + image = conn.read(startPos, endPos); + FileOutputStream fos = new FileOutputStream(file,true); + fos.write(image); + fos.close(); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + }else{ + return false; + } + } + public void run(){ + while (!writeFile()){ + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + latch.countDown(); + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloader.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloader.java new file mode 100644 index 0000000000..ca3709a549 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloader.java @@ -0,0 +1,86 @@ +package com.github.wdn.coding2017.coderising.download; + + +import com.github.wdn.coding2017.coderising.download.api.Connection; +import com.github.wdn.coding2017.coderising.download.api.ConnectionException; +import com.github.wdn.coding2017.coderising.download.api.ConnectionManager; +import com.github.wdn.coding2017.coderising.download.api.DownloadListener; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.concurrent.CountDownLatch; + +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 threadSum = 4; + final CountDownLatch latch = new CountDownLatch(threadSum); + int length = conn.getContentLength(); + if(length<=1024){ + new DownloadThread(cm.open(this.url),0,length,latch).start(); + }else{ + int partLength = length/threadSum; + for (int i = 0; i < threadSum; i++) { + if(i==threadSum-1){ + new DownloadThread(cm.open(this.url),i*partLength,length,latch).start(); + }else{ + new DownloadThread(cm.open(this.url),i*partLength,i*partLength+partLength,latch).start(); + } + + } + } + latch.await(); + listener.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; + } + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloaderTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloaderTest.java new file mode 100644 index 0000000000..8ca48ad471 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/FileDownloaderTest.java @@ -0,0 +1,59 @@ +package com.github.wdn.coding2017.coderising.download; + +import com.github.wdn.coding2017.coderising.download.api.ConnectionManager; +import com.github.wdn.coding2017.coderising.download.api.DownloadListener; +import com.github.wdn.coding2017.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 = "http://pic1.win4000.com/wallpaper/9/58dcbb7ee7de0.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/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/Connection.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/Connection.java new file mode 100644 index 0000000000..8b0e057a32 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/Connection.java @@ -0,0 +1,27 @@ +package com.github.wdn.coding2017.coderising.download.api; + +import java.io.IOException; +import java.net.HttpURLConnection; + +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(); + + + void setHttpURLConnection(HttpURLConnection httpURLConnection); +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionException.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..5c90080401 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.github.wdn.coding2017.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionManager.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionManager.java new file mode 100644 index 0000000000..f814016839 --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionManager.java @@ -0,0 +1,10 @@ +package com.github.wdn.coding2017.coderising.download.api; + +public interface ConnectionManager { + /** + * 给定一个url , 打开一个连接 + * @param url + * @return + */ + public Connection open(String url) throws ConnectionException; +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/DownloadListener.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/DownloadListener.java new file mode 100644 index 0000000000..078b14365d --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/api/DownloadListener.java @@ -0,0 +1,5 @@ +package com.github.wdn.coding2017.coderising.download.api; + +public interface DownloadListener { + public void notifyFinished(); +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionImpl.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionImpl.java new file mode 100644 index 0000000000..7f9e090a1e --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionImpl.java @@ -0,0 +1,55 @@ +package com.github.wdn.coding2017.coderising.download.impl; + +import com.github.wdn.coding2017.coderising.download.api.Connection; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.util.Arrays; + + +public class ConnectionImpl implements Connection { + HttpURLConnection connection; + @Override + public byte[] read(int startPos, int endPos) throws IOException { + if (connection == null) { + throw new IllegalArgumentException("connection is null"); + } + int code = connection.getResponseCode(); + ByteArrayOutputStream baos=null; + InputStream is=null; + if(code==200){ + //5读取服务器资源的流 + is= connection.getInputStream(); + //准备内存输出流 临时存储的 + baos = new ByteArrayOutputStream(); + byte buff[] = new byte[1024]; + int len=0; + int sum = 0; + while((len=is.read(buff))!=-1){ + baos.write(buff,0,len); + baos.flush(); + sum+=len; + if(sum>=endPos){ + break; + } + } + } + byte[] readResult = baos.toByteArray(); + return Arrays.copyOfRange(readResult,startPos,endPos); + } + + @Override + public int getContentLength() { + return connection.getContentLength(); + } + + @Override + public void close() { + + } + public void setHttpURLConnection(HttpURLConnection httpURLConnection){ + this.connection = httpURLConnection; + } +} diff --git a/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionManagerImpl.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..bcdad865aa --- /dev/null +++ b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,26 @@ +package com.github.wdn.coding2017.coderising.download.impl; + + +import com.github.wdn.coding2017.coderising.download.api.Connection; +import com.github.wdn.coding2017.coderising.download.api.ConnectionException; +import com.github.wdn.coding2017.coderising.download.api.ConnectionManager; + +import java.net.HttpURLConnection; +import java.net.URL; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + try { + URL targetUrl = new URL(url); + Connection connection = new ConnectionImpl(); + connection.setHttpURLConnection((HttpURLConnection) targetUrl.openConnection()); + return connection; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/LoginAction.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/LoginAction.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/LoginAction.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/LoginAction.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/Struts.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/Struts.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/Struts.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/Struts.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/StrutsTest.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/StrutsTest.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/StrutsTest.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/StrutsTest.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/View.java b/group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/View.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/View.java rename to group24/626451284/data-structure/src/main/java/com/github/wdn/coding2017/coderising/litestruts/View.java diff --git a/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/LinkedListTest.java b/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/LinkedListTest.java new file mode 100644 index 0000000000..7a967cea64 --- /dev/null +++ b/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/LinkedListTest.java @@ -0,0 +1,91 @@ +package com.github.wdn.coding2017.basic; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +/** + * Created by Administrator on 2017/4/3 0003. + */ +public class LinkedListTest { + LinkedList linkedList = new LinkedList(); + @Before + public void initLinkedList(){ + for (int i = 0; i < 12; i++) { + linkedList.add(i); + } + } + @Test + public void testReverse(){ + + System.out.println(linkedList.size()); + System.out.println(linkedList); + linkedList.reverse(); + System.out.println(""); + System.out.println(linkedList); + } + @Test + public void testRemoveFirstHalf(){ + System.out.println(linkedList); + linkedList.removeFirstHalf(); + System.out.println(linkedList); + } + @Test + public void testRemove(){ + System.out.println(linkedList); + //linkedList.remove(0,30); + //System.out.println(linkedList); + //linkedList.remove(2,30); + //System.out.println(linkedList); + linkedList.remove(2,0); + System.out.println(linkedList); + } + @Test + public void testGetElements(){ + LinkedList indexs = new LinkedList(); + indexs.add(3); + indexs.add(5); + indexs.add(7); + indexs.add(9); + int[] result = linkedList.getElements(indexs); + System.out.println(Arrays.toString(result)); + Assert.assertArrayEquals(new int[]{3, 5, 7, 9},result); + } + @Test + public void testSubtract(){ + LinkedList indexs = new LinkedList(); + indexs.add(3); + indexs.add(5); + indexs.add(7); + indexs.add(9); + linkedList.subtract(indexs); + System.out.println(linkedList); + System.out.println(linkedList.size()); + } + @Test + public void testRemoveDuplicateValues(){ + LinkedList list = new LinkedList(); + list.add(3); + //list.add(3); + list.add(5); + //list.add(5); + list.add(7); + list.add(7); + list.add(9); + list.add(9); + list.removeDuplicateValues(); + System.out.println(list); + } + @Test + public void testRemoveRange(){ + LinkedList indexs = new LinkedList(); + indexs.add(3); + indexs.add(5); + indexs.add(7); + indexs.add(9); + indexs.removeRange(9, 9); + System.out.println(indexs); + } +} diff --git a/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/StackUtilTest.java b/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/StackUtilTest.java new file mode 100644 index 0000000000..7e56bbf345 --- /dev/null +++ b/group24/626451284/data-structure/src/main/test/com/github/wdn/coding2017/basic/StackUtilTest.java @@ -0,0 +1,57 @@ +package com.github.wdn.coding2017.basic; + +import com.github.wdn.coding2017.basic.stack.StackUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.Arrays; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +public class StackUtilTest { + + @Test + public void testReverse(){ + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + StackUtil.reverse(stack); + while (!stack.isEmpty()){ + System.out.println(stack.pop()); + } + } + @Test + public void testRemove(){ + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + StackUtil.remove(stack,4); + while (!stack.isEmpty()){ + System.out.println(stack.pop()); + } + } + @Test + public void testGetTop(){ + Stack stack = new Stack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + Object[] o = StackUtil.getTop(stack,0); + System.out.println(Arrays.toString(o)); + while (!stack.isEmpty()){ + System.out.println(stack.pop()); + } + } + @Test + public void testIsValidPairs(){ + Assert.assertEquals(true,StackUtil.isValidPairs("([e{d}f])")); + Assert.assertEquals(false,StackUtil.isValidPairs("([b{x]y})")); + Assert.assertEquals(false,StackUtil.isValidPairs("([({e}f])")); + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/AttributeInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..8ec8464918 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/AttributeInfo.java @@ -0,0 +1,20 @@ +package com.github.wdn.coding2017.jvm.attr; + +/** + * Created by Administrator on 2017/4/12 0012. + */ +public 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"; + + private int attributeNameIndex;// u2 + private int attributeLength; //u4 + public AttributeInfo(int attributeNameIndex,int attributeLength){ + this.attributeNameIndex = attributeNameIndex; + this.attributeLength = attributeLength; + } +} 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 new file mode 100644 index 0000000000..9400b629b2 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/CodeAttr.java @@ -0,0 +1,58 @@ +package com.github.wdn.coding2017.jvm.attr; + +/** + * Created by Administrator on 2017/4/12 0012. + */ +public class CodeAttr extends AttributeInfo { + private int maxStack; + private int maxLocals; + private String code; + private LineNumberTable lineNumTable; + private LocalVariableTable localVarTable; + private StackMapTable stackMapTable; + public CodeAttr(int attributeNameIndex, int attributeLength, int maxStack, int maxLocals, String code) { + super(attributeNameIndex, attributeLength); + this.maxStack = maxStack; + this.maxLocals = maxLocals; + this.code = code; + } + @Override + public String toString(){ + return code; + } + 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 String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public void setLineNumTable(LineNumberTable lineNumTable) { + this.lineNumTable = lineNumTable; + } + + public void setLocalVarTable(LocalVariableTable localVarTable) { + this.localVarTable = localVarTable; + } + + public void setStackMapTable(StackMapTable stackMapTable) { + this.stackMapTable = stackMapTable; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LineNumberTable.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LineNumberTable.java new file mode 100644 index 0000000000..594e574114 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LineNumberTable.java @@ -0,0 +1,48 @@ +package com.github.wdn.coding2017.jvm.attr; + +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/12 0012. + */ +public class LineNumberTable extends AttributeInfo{ + public LineNumberTable(int attributeNameIndex, int attributeLength) { + super(attributeNameIndex, attributeLength); + } + List lineNumberItems = 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.lineNumberItems.add(item); + } + + public static LineNumberTable parse(ByteCodeIterator iter){ + LineNumberTable lineNumberTable = new LineNumberTable(0, iter.readU4ToInt()); + int lineNumberTableCount = iter.readU2ToInt(); + for (int l = 0; l < lineNumberTableCount; l++) { + LineNumberItem lineNumberItem = new LineNumberItem(); + lineNumberItem.setStartPC(iter.readU2ToInt()); + lineNumberItem.setLineNum(iter.readU2ToInt()); + lineNumberTable.addLineNumberItem(lineNumberItem); + } + return lineNumberTable; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTable.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..f84a96e2d9 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTable.java @@ -0,0 +1,80 @@ +package com.github.wdn.coding2017.jvm.attr; + +import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Administrator on 2017/4/12 0012. + */ +public class LocalVariableTable extends AttributeInfo{ + List localVariableTableItems = new ArrayList<>(); + public LocalVariableTable(int attributeNameIndex, int attributeLength) { + super(attributeNameIndex, attributeLength); + } + private static class LocalVariableTableItem{ + int startPC; + int length; + int nameIndex; + int descriptorIndex; + 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 getDescriptorIndex() { + return descriptorIndex; + } + + public void setDescriptorIndex(int descriptorIndex) { + this.descriptorIndex = descriptorIndex; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + } + private void addLocalVariableItem(LocalVariableTableItem item){ + this.localVariableTableItems.add(item); + } + public static LocalVariableTable parse(ByteCodeIterator iter) { + LocalVariableTable localVariableTable = new LocalVariableTable(iter.readU2ToInt(),iter.readU2ToInt()); + int LocalVariableTableCount = iter.readU2ToInt(); + for (int l = 0; l < LocalVariableTableCount; l++) { + LocalVariableTableItem item = new LocalVariableTableItem(); + item.setStartPC(iter.readU2ToInt()); + item.setLength(iter.readU2ToInt()); + item.setNameIndex(iter.readU2ToInt()); + item.setDescriptorIndex(iter.readU2ToInt()); + item.setIndex(iter.readU2ToInt()); + localVariableTable.addLocalVariableItem(item); + } + return localVariableTable; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTypeTable.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTypeTable.java new file mode 100644 index 0000000000..cb05a8074d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/LocalVariableTypeTable.java @@ -0,0 +1,7 @@ +package com.github.wdn.coding2017.jvm.attr; + +/** + * Created by Administrator on 2017/4/12 0012. + */ +public class LocalVariableTypeTable { +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/StackMapTable.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..7c607031be --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/attr/StackMapTable.java @@ -0,0 +1,29 @@ +package com.github.wdn.coding2017.jvm.attr; + +import com.github.wdn.coding2017.jvm.loader.ByteCodeIterator; + +/** + * Created by Administrator on 2017/4/12 0012. + */ +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.readU2ToInt(); + int len = iter.readU4ToInt(); + StackMapTable t = new StackMapTable(index,len); + //后面的StackMapTable太过复杂, 不再处理, 只把原始的代码读进来保存 + String code = iter.readCustomToString(len); + t.setOriginalCode(code); + return t; + } + + private void setOriginalCode(String code) { + this.originalCode = code; + + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/AccessFlag.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..a0fcba07f6 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/AccessFlag.java @@ -0,0 +1,37 @@ +package com.github.wdn.coding2017.jvm.clz; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +public class AccessFlag { + /* + enum { + ACC_PUBLIC,ACC_FINAL,ACC_SUPER,ACC_INTERFACE,ACC_ABSTRACT,ACC_SYNTHETIC + } + private int ACC_PUBLIC =0x0001; //可以被包的类外访问。 + private int ACC_FINAL =0x0010; //不允许有子类。 + private int ACC_SUPER =0x0020;//当用到invokespecial指令时,需要特殊处理③的父类方法。 + private int ACC_INTERFACE= 0x0200; //标识定义的是接口而不是类。 + private int ACC_ABSTRACT= 0x0400; //不能被实例化。 + private int ACC_SYNTHETIC= 0x1000; //标识并非Java源码生成的代码 + */ + 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/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 new file mode 100644 index 0000000000..813c050a53 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassFile.java @@ -0,0 +1,80 @@ +package com.github.wdn.coding2017.jvm.clz; + +import com.github.wdn.coding2017.jvm.constant.ConstantPool; + +import java.util.List; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +public class ClassFile { + private int minorVersion; + private int majorVersion; + private ConstantPool constantPool; + private AccessFlag accessFlag; + private ClassIndex classIndex; + private List fields; + private List methods; + public void print() { + } + + public int getMinorVersion() { + return minorVersion; + } + + public int getMajorVersion() { + return majorVersion; + } + + public void setMinorVersion(int minorVersion) { + this.minorVersion = minorVersion; + } + + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public void setConstantPool(ConstantPool constantPool) { + this.constantPool = constantPool; + } + + public AccessFlag getAccessFlag() { + return accessFlag; + } + + public void setAccessFlag(AccessFlag accessFlag) { + this.accessFlag = accessFlag; + } + + public ClassIndex getClassIndex() { + return classIndex; + } + + public void setClassIndex(ClassIndex classIndex) { + this.classIndex = classIndex; + } + + public ClassIndex getClzIndex() { + return null; + } + + 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; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassIndex.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..f65a403d0a --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/ClassIndex.java @@ -0,0 +1,20 @@ +package com.github.wdn.coding2017.jvm.clz; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +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 int getSuperClassIndex() { + return superClassIndex; + } +} 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 new file mode 100644 index 0000000000..8d557b10de --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Field.java @@ -0,0 +1,74 @@ +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 new file mode 100644 index 0000000000..b6ace8ebce --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/clz/Method.java @@ -0,0 +1,99 @@ +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/constant/ClassInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e4565e93b1 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ClassInfo.java @@ -0,0 +1,35 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +public class ClassInfo extends ConstantInfo{ + private int nameIndex; + public ClassInfo(ConstantPool constantPool){ + super(constantPool); + } + @Override + public int getType() { + return CLASS_INFO; + } + @Override + public String getValue() { + return getConstantPool().getConstantInfo(nameIndex).getValue(); + } + + public int getNameIndex() { + return nameIndex; + } + + public void setNameIndex(int nameIndex) { + this.nameIndex = nameIndex; + } + + public int getUtf8Index() { + return nameIndex; + } + + public String getClassName() { + return getConstantPool().getConstantInfo(nameIndex).getValue(); + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..24975d30c8 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantInfo.java @@ -0,0 +1,30 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +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 constantPool){ + this.constantPool = constantPool; + } + public abstract int getType(); + public abstract String getValue(); + public ConstantPool getConstantPool(){ + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return constantPool.getConstantInfo(index); + } + +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantPool.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..3a3f4e03e4 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/ConstantPool.java @@ -0,0 +1,32 @@ +package com.github.wdn.coding2017.jvm.constant; + + +import java.util.ArrayList; + +/** + * Created by Administrator on 2017/4/6 0006. + */ +public class ConstantPool { + public static ArrayList constantPool = new ArrayList(); + static{ + constantPool.add(new NullConstantInfo()); + } + public void put(ConstantInfo info){ + constantPool.add(info); + } + public int getSize() { + return constantPool.size()-1; + } + + public ConstantInfo getConstantInfo(int i) { + return constantPool.get(i); + } + @Override + public String toString(){ + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 1; i < constantPool.size(); i++) { + stringBuffer.append("#"+i+"=>"+constantPool.get(i).getValue()); + } + return stringBuffer.toString(); + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/FieldRefInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..86c89dc9c3 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/FieldRefInfo.java @@ -0,0 +1,39 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class FieldRefInfo extends ConstantInfo { + private int classInfoIndex; + private int nameAndTypeIndex; + + public FieldRefInfo(ConstantPool constantPool) { + super(constantPool); + } + + @Override + public int getType() { + return FIELD_INFO; + } + + @Override + public String getValue() { + return getConstantPool().getConstantInfo(classInfoIndex).getValue()+getConstantPool().getConstantInfo(nameAndTypeIndex).getValue(); + } + + 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; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/MethodRefInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..e4d6412cd1 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/MethodRefInfo.java @@ -0,0 +1,37 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class MethodRefInfo extends ConstantInfo { + private int classInfoIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool constantPool) { + super(constantPool); + } + @Override + public int getType() { + return METHOD_INFO; + } + @Override + public String getValue() { + return getConstantPool().getConstantInfo(classInfoIndex).getValue()+getConstantPool().getConstantInfo(nameAndTypeIndex).getValue(); + } + + 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; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NameAndTypeInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..3a3f1bf4c8 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,38 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class NameAndTypeInfo extends ConstantInfo{ + private int nameIndex; + private int descriptorIndex; + + public NameAndTypeInfo(ConstantPool constantPool) { + super(constantPool); + } + + @Override + public int getType() { + return 0; + } + @Override + public String getValue() { + return getConstantPool().getConstantInfo(nameIndex).getValue()+getConstantPool().getConstantInfo(descriptorIndex).getValue(); + } + + 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; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NullConstantInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..bea4eb973f --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/NullConstantInfo.java @@ -0,0 +1,14 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class NullConstantInfo extends ConstantInfo { + public int getType() { + return 0; + } + + public String getValue() { + return null; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/StringInfo.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..a4cbd7bb5d --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/StringInfo.java @@ -0,0 +1,30 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class StringInfo extends ConstantInfo { + public StringInfo(ConstantPool constantPool) { + super(constantPool); + } + + private int stringIndex; + + @Override + public int getType() { + return 0; + } + + @Override + public String getValue() { + return getConstantPool().getConstantInfo(stringIndex).getValue(); + } + + public int getStringIndex() { + return stringIndex; + } + + public void setStringIndex(int stringIndex) { + this.stringIndex = stringIndex; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/UTF8Info.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..bf5efd842a --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/constant/UTF8Info.java @@ -0,0 +1,23 @@ +package com.github.wdn.coding2017.jvm.constant; + +/** + * Created by Administrator on 2017/4/8 0008. + */ +public class UTF8Info extends ConstantInfo{ + private String value; + public UTF8Info(ConstantPool constantPool){ + super(constantPool); + } + @Override + public int getType() { + return UTF8_INFO; + } + @Override + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} 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 new file mode 100644 index 0000000000..dc4c1c0b54 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,42 @@ +package com.github.wdn.coding2017.jvm.loader; + + +import com.github.wdn.coding2017.jvm.util.Util; + +import java.nio.charset.Charset; + +public class ByteCodeIterator { + private byte[] bytes; + private int index; + + public ByteCodeIterator(byte[] bytes){ + this.bytes = bytes; + } + + public byte[] read(){ + return new byte[]{bytes[index++]}; + } + public int readToInt(){ + return Util.byteToInt(new byte[]{bytes[index++]}); + } + public int readU2ToInt(){ + return Util.byteToInt(new byte[]{bytes[index++],bytes[index++]}); + } + public String readU2ToString(){ + return Util.byteToHexString(new byte[]{bytes[index++],bytes[index++]}); + } + public int readU4ToInt(){ + return Util.byteToInt(new byte[]{bytes[index++],bytes[index++],bytes[index++],bytes[index++]}); + } + public String readU4ToString(){ + return Util.byteToHexString(new byte[]{bytes[index++],bytes[index++],bytes[index++],bytes[index++]}); + } + public String readCustomToString(int len){ + byte[] b = new byte[len]; + for (int i = 0; i < len; i++) { + b[i] = bytes[index++]; + } + return new String(b); + //return Util.byteToHexString(b); + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileLoader.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..6f29b692d4 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileLoader.java @@ -0,0 +1,83 @@ +package com.github.wdn.coding2017.jvm.loader; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +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) { + File file = null; + for (int i = 0; i < clzPaths.size(); i++) { + String path = clzPaths.get(i); + String fullPath = path +File.separator+ className.replace(".", File.separator)+".class"; + file = new File(fullPath); + } + + try { + if(file.exists()){ + // 使用FileUtils最简单 + // return FileUtils.readFileToByteArray(file); + FileInputStream inputStream = new FileInputStream(file); + long fileLength = file.length(); + if (fileLength>Integer.MAX_VALUE) { + throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + fileLength); + } + byte[] fileBytes = new byte[(int)fileLength]; + byte[] bytes = new byte[1024]; + int len; + int offset=0; + // for循环使用inputStream api读取 一次读完。。 + for(offset = 0; offset < fileLength && (len = inputStream.read(fileBytes, offset, (int)fileLength - offset)) != -1; offset += len) { + ; + } + // while循环使用System.arraycopy读取 + /*while ((len = inputStream.read(bytes))>-1){ + System.arraycopy(bytes, 0, fileBytes, offset, len); + offset += len; + }*/ + return fileBytes; + } + throw new FileNotFoundException(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + public void addClassPath(String path) { + clzPaths.add(path); + } + + + + public String getClassPath(){ + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < clzPaths.size(); i++) { + if (i==clzPaths.size()-1) { + stringBuffer.append(clzPaths.get(i)); + }else{ + stringBuffer.append(clzPaths.get(i)).append(";"); + } + } + return stringBuffer.toString(); + } + + + public ClassFile loadClass(String className) { + ClassFileParser classFileParser = new ClassFileParser(); + ClassFile classFile = classFileParser.parse(readBinaryCode(className)); + return classFile; + } +} 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 new file mode 100644 index 0000000000..22d2e5bcd7 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/loader/ClassFileParser.java @@ -0,0 +1,105 @@ +package com.github.wdn.coding2017.jvm.loader; + +import com.github.wdn.coding2017.jvm.clz.*; +import com.github.wdn.coding2017.jvm.constant.*; + +import java.util.ArrayList; +import java.util.List; + +public class ClassFileParser { + ConstantPool pool = new ConstantPool(); + public ClassFile parse(byte[] codes) { + ByteCodeIterator iter = new ByteCodeIterator(codes); + String magic = iter.readU4ToString(); + if(!"cafebabe".equals(magic)){ + throw new Error(); + } + ClassFile classFile = new ClassFile(); + classFile.setMinorVersion(iter.readU2ToInt()); + classFile.setMajorVersion(iter.readU2ToInt()); + classFile.setConstantPool(parseConstantPool(iter)); + classFile.setAccessFlag(parseAccessFlag(iter)); + classFile.setClassIndex(parseClassIndex(iter)); + parseInterface(iter); + classFile.setFields(parseField(iter)); + classFile.setMethods(parseMethod(iter)); + return classFile; + } + + private List parseMethod(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.setPool(pool); + methods.add(method); + } + return methods; + } + + private List parseField(ByteCodeIterator iter) { + int fieldsCount = iter.readU2ToInt(); + List fields = new ArrayList<>(fieldsCount); + for (int i = 0; i < fieldsCount; i++) { + Field field = Field.parse(iter); + field.setPool(pool); + fields.add(field); + } + return fields; + } + + private void parseInterface(ByteCodeIterator iter){ + int interfaceNum = iter.readU2ToInt(); + if (interfaceNum > 0) { + throw new RuntimeException("接口数量>0"); + } + } + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + return new AccessFlag(iter.readU2ToInt()); + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + return new ClassIndex(iter.readU2ToInt(),iter.readU2ToInt()); + } + + public ConstantPool parseConstantPool(ByteCodeIterator iter) { + + int constantPoolNum = iter.readU2ToInt(); + for (int i = 0; i < constantPoolNum-1; i++) { + int type = iter.readToInt(); + if(type==7){// class + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setNameIndex(iter.readU2ToInt()); + pool.put(classInfo); + }else if(type==9){// Fieldref + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.readU2ToInt()); + fieldRefInfo.setNameAndTypeIndex(iter.readU2ToInt()); + pool.put(fieldRefInfo); + }else if(type==10){// Methodref + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassInfoIndex(iter.readU2ToInt()); + methodRefInfo.setNameAndTypeIndex(iter.readU2ToInt()); + pool.put(methodRefInfo); + }else if(type==1){// Utf8 + int length = iter.readU2ToInt(); + String value = iter.readCustomToString(length); + UTF8Info utf8Info = new UTF8Info(pool); + utf8Info.setValue(value); + pool.put(utf8Info); + }else if(type==8){// String + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setStringIndex(iter.readU2ToInt()); + pool.put(stringInfo); + }else if(type==12){// NameAndType + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setNameIndex(iter.readU2ToInt()); + nameAndTypeInfo.setDescriptorIndex(iter.readU2ToInt()); + pool.put(nameAndTypeInfo); + }else{ + throw new RuntimeException("未知类型"+type); + } + } + return pool; + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/ClassFileloaderTest.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/ClassFileloaderTest.java new file mode 100644 index 0000000000..9d2b468236 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/ClassFileloaderTest.java @@ -0,0 +1,169 @@ +package com.github.wdn.coding2017.jvm.test; + +import com.github.wdn.coding2017.jvm.clz.ClassFile; +import com.github.wdn.coding2017.jvm.clz.ClassIndex; +import com.github.wdn.coding2017.jvm.constant.*; +import com.github.wdn.coding2017.jvm.loader.ClassFileLoader; +import com.github.wdn.coding2017.jvm.util.Util; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + + + + +public class ClassFileloaderTest { + + + static String path1 = "E:\\softdata\\ideaworkspace\\self\\coding2017\\group24\\626451284\\mini-jvm\\target\\classes"; + static String path2 = "E:\\temp"; + + static ClassFile clzFile = null; + static final String FULL_QUALIFIED_CLASS_NAME="com/coderising/jvm/test/EmployeeV1"; + static { + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.github.wdn.coding2017.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.github.wdn.coding2017.jvm.test.EmployeeV1"; + + byte[] byteCodes = loader.readBinaryCode(className); + + // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 + Assert.assertEquals(1078, byteCodes.length); + + } + + @Test + public void testMagicNumber(){ + ClassFileLoader loader = new ClassFileLoader(); + loader.addClassPath(path1); + String className = "com.github.wdn.coding2017.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.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()); + } +} diff --git a/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/EmployeeV1.java b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..0b035bcf88 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package com.github.wdn.coding2017.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/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 new file mode 100644 index 0000000000..1e54f24a79 --- /dev/null +++ b/group24/626451284/mini-jvm/src/main/java/com/github/wdn/coding2017/jvm/util/Util.java @@ -0,0 +1,24 @@ +package com.github.wdn.coding2017.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 - - 4.0.0 - - com.github.wdn - coding2017 - 1.0-SNAPSHOT - \ No newline at end of file diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java b/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java deleted file mode 100644 index 6040cb5a47..0000000000 --- a/group24/626451284/src/main/java/com/github/wdn/coding2017/basic/LinkedList.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.github.wdn.coding2017.basic; - -/** - * TODO 只是简单实现 缺少对边界的处理 - * 参考JDK源码改为更优雅的实现 - */ - -public class LinkedList implements List { - - private Node head; - private Node tail; - private int size; - - public LinkedList(){ - this.head=null; - this.tail=null; - } - public void add(Object o){ - Node newNode = new Node(o); - if (head == null) { - head = newNode; - tail = newNode; - }else{ - tail.setNext(newNode); - newNode.setPre(tail); - tail = newNode; - } - size++; - } - public void add(int index , Object o){ - checkIndex(index); - Node indexNode = getNode(index); - Node newNode = new Node(o); - Node pre = indexNode.getPre(); - if(pre!=null){ - pre.setNext(newNode); - }else{ - head = newNode; - } - newNode.setPre(pre); - newNode.setNext(indexNode); - indexNode.setPre(newNode); - } - private void checkIndex(int index){ - if(index >= size || index <0){ - throw new IndexOutOfBoundsException(); - } - } - private Node getNode(int index){ - checkIndex(index); - // TODO这里可以优化,先判断index在前半部还是后半部分 然后确定从头部或者尾部查找 - Node result=null; - if(index==0){ - return head; - } - if(index==size-1){ - return tail; - } - for (int i = 0; i < index; i++) { - result = head.getNext(); - } - return result; - } - public Object get(int index){ - return getNode(index).getData(); - } - public Object remove(int index){ - checkIndex(index); - Node indexNode = getNode(index); - Node pre = indexNode.getPre(); - Node next = indexNode.getNext(); - if(pre!=null){ - pre.setNext(next); - }else{ - head = next; - } - if(next!=null){ - next.setPre(pre); - }else{ - tail = pre; - } - return indexNode.getData(); - } - - public int size(){ - return size; - } - - public void addFirst(Object o){ - Node newNode = new Node(o); - head.setPre(newNode); - newNode.setNext(head); - head = newNode; - } - public void addLast(Object o){ - Node newNode = new Node(o); - tail.setNext(newNode); - newNode.setPre(tail); - tail = newNode; - } - public Object removeFirst(){ - Node next = head.getNext(); - Node oldHead = head; - head = next; - head.setPre(null); - return oldHead; - } - public Object removeLast(){ - Node oldTail = tail; - Node pre = tail.getPre(); - tail = pre; - tail.setNext(null); - return oldTail; - } - public Iterator iterator(){ - - return null; - } - - /** - * JDK 中使用构造方法的方式设置next和pre减少不必要的getset方法更优雅 - */ - private static class Node{ - - Object data; - Node next; - Node pre; - public Node(){ - - } - public Node(Object data){ - this.data = data; - } - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public Node getNext() { - return next; - } - - public void setNext(Node next) { - this.next = next; - } - - public Node getPre() { - return pre; - } - - public void setPre(Node pre) { - this.pre = pre; - } - } - - /** - * 把该链表逆置 - * 例如链表为 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/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/struts.xml b/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/struts.xml deleted file mode 100644 index fb12bdc239..0000000000 --- a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group24/798277403/out/production/zhouliang/week2/litestruts/struts.xml b/group24/798277403/out/production/zhouliang/week2/litestruts/struts.xml deleted file mode 100644 index 54550a4174..0000000000 --- a/group24/798277403/out/production/zhouliang/week2/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group24/798277403/src/basic/ArrayList.java b/group24/798277403/src/basic/ArrayList.java new file mode 100644 index 0000000000..436ca1f9f2 --- /dev/null +++ b/group24/798277403/src/basic/ArrayList.java @@ -0,0 +1,147 @@ +package basic; + +import java.util.Arrays; + +/** + java泛型: + ? 表示不确定的java类型。 + T 表示java类型。 + K V 分别代表java键值中的Key Value。 + E 代表Element。 + + * 自己实现的ArrayList + * Created by zhouliang on 2017-03-10. + */ +class ArrayList implements List { + + private Object[] elementData; + + private int size; + + public ArrayList(int size){ + this.elementData = new Object[size]; + } + + //默认大小为10 + public ArrayList(){ + this.elementData = new Object[10]; + } + + //判断是否需要扩展容量 ((旧容量 * 3) / 2) + 1 + private void checkcapacity(int index){ + if(index>elementData.length){ + int length = (elementData.length*3)/2+1; + /* + Object[] temp = new Object[length]; + for(int i=0; i= 0 && index < size; + } + + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + + size); + } + } + + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + + public Iterator iterator() { + return new ArrayListIterator(this); + } + + private class ArrayListIterator implements Iterator { + private ArrayList list = null; + private int position = 0; + + private ArrayListIterator(ArrayList list) { + this.list = list; + } + + @Override + public boolean hasNext() { + if ((position + 1) > size()) { + return false; + } + return true; + } + + @Override + public E next() { + return list.get(position++); + } + } +} diff --git a/group24/798277403/src/basic/ArrayListTest.java b/group24/798277403/src/basic/ArrayListTest.java new file mode 100644 index 0000000000..c50af7befa --- /dev/null +++ b/group24/798277403/src/basic/ArrayListTest.java @@ -0,0 +1,55 @@ +package basic; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by zhouliang on 2017-03-10. + */ +public class ArrayListTest { + + private ArrayList arrayList = new ArrayList(); + + @Before + public void setUp(){ + for(int i=0; i<100; i++){ + arrayList.add(i); + } + } + + @Test + public void add() throws Exception { + for(int i=100; i<1000; i++){ + arrayList.add(i); + } + Assert.assertEquals(1000,arrayList.size()); + } + + @Test + public void add1() throws Exception { + java.util.LinkedList l = new java.util.LinkedList(); + } + + @Test + public void get() throws Exception { + System.out.println(arrayList.get(99)); + } + + @Test + public void remove() throws Exception { + System.out.println(arrayList.size()); + arrayList.remove(arrayList.size()-1); + System.out.println(arrayList.size()); + //Assert.assertEquals((Integer)99,(Integer)arrayList.size()); + } + + @Test + public void iterator() throws Exception { + Iterator iterator = arrayList.iterator(); + while(iterator.hasNext()){ + System.out.println(iterator.next()); + } + } + +} \ No newline at end of file diff --git a/group24/798277403/src/week1/BinaryTree.java b/group24/798277403/src/basic/BinaryTree.java similarity index 99% rename from group24/798277403/src/week1/BinaryTree.java rename to group24/798277403/src/basic/BinaryTree.java index 3c480dc012..c2d5bb2c24 100644 --- a/group24/798277403/src/week1/BinaryTree.java +++ b/group24/798277403/src/basic/BinaryTree.java @@ -1,4 +1,4 @@ -package week1; +package basic; /** * Created by zhouliang on 2017-03-11. diff --git a/group24/798277403/src/basic/BinaryTreeNode.java b/group24/798277403/src/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..599b2b1ca8 --- /dev/null +++ b/group24/798277403/src/basic/BinaryTreeNode.java @@ -0,0 +1,72 @@ +package basic; + +/** + * 自己实现的BinaryTreeNode + * Created by zhouliang on 2017-03-10. + */ +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 && left==null && right==null){ + this.setData(o); + this.setLeft(null); + this.setRight(null); + return this; + }else{ + BinaryTreeNode temp = this; + BinaryTreeNode node = new BinaryTreeNode(); + while(true){ + if((Integer)o > (Integer)temp.getData()){ + if(temp.getRight() == null){ + node.setData(o); + node.setLeft(null); + node.setRight(null); + + temp.setRight(node); + return this; + }else{ + temp = temp.getRight(); + } + }else{ + if(temp.getLeft() == null){ + node.setData(o); + node.setLeft(null); + node.setRight(null); + + temp.setLeft(node); + return this; + }else{ + temp = temp.getLeft(); + } + } + } + } + } +} diff --git a/group24/798277403/src/basic/Iterator.java b/group24/798277403/src/basic/Iterator.java new file mode 100644 index 0000000000..4c0fedf988 --- /dev/null +++ b/group24/798277403/src/basic/Iterator.java @@ -0,0 +1,10 @@ +package basic; + +/** + * 自己实现的Iterator + * Created by zhouliang on 2017-03-10. + */ +interface Iterator { + boolean hasNext(); + Object next(); +} diff --git a/group24/798277403/src/basic/LRU/LRUPageFrame.java b/group24/798277403/src/basic/LRU/LRUPageFrame.java new file mode 100644 index 0000000000..e69e051321 --- /dev/null +++ b/group24/798277403/src/basic/LRU/LRUPageFrame.java @@ -0,0 +1,130 @@ +package basic.LRU; + +/** + * Created by zhouliang on 2017-04-04. + */ +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 pageNum + * @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/group24/798277403/src/basic/LRU/LRUPageFrameTest.java b/group24/798277403/src/basic/LRU/LRUPageFrameTest.java new file mode 100644 index 0000000000..4993f42e75 --- /dev/null +++ b/group24/798277403/src/basic/LRU/LRUPageFrameTest.java @@ -0,0 +1,33 @@ +package basic.LRU; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by zhouliang on 2017-04-04. + */ +public class LRUPageFrameTest { + @Test + public void testAccess() { + MyLRUPageFrame frame = new MyLRUPageFrame(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/group24/798277403/src/basic/LRU/MyLRUPageFrame.java b/group24/798277403/src/basic/LRU/MyLRUPageFrame.java new file mode 100644 index 0000000000..b2387dbd81 --- /dev/null +++ b/group24/798277403/src/basic/LRU/MyLRUPageFrame.java @@ -0,0 +1,133 @@ +package basic.LRU; + +/** + * Created by zhouliang on 2017-04-04. + */ +public class MyLRUPageFrame { + private static class Node { + Node prev; + Node next; + int pageNum; + + Node() { + } + } + + private int capacity; + private int currentSize; + private Node first;// 链表头 + private Node last;// 链表尾 + + public MyLRUPageFrame(int capacity) { + this.currentSize = 0; + this.capacity = capacity; + } + + /** + * 获取缓存中对象 + * + * @param pageNum + * @return + */ + public void access(int pageNum) { + //1、是否为空号 + //2、不为空,查找后面有没有出现pageNum,如果出现则把pageNum结点移动到head + //3、如果没有出现pageNum,则判断栈是否满 + //4、如果栈没有满,则添加pageNum到head + //5、否则删除最后一个再添加pageNum到head + Node temp = find(pageNum); + if (temp != null) { + moveExistingNodeToHead(temp); + } else { + temp = new Node(); + temp.pageNum = pageNum; + if (currentSize >= capacity) { + removeLast(); + } + addNewNodetoHead(temp); + } + + } + + 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; + } + currentSize++; + } + + private Node find(int data) { + if (isEmpty()) { + return null; + } else { + Node temp = first; + while (temp.next != null) { + if (temp.pageNum == data) { + return temp; + } + temp = temp.next; + } + return null; + } + } + + /** + * 删除链表尾部节点 表示 删除最少使用的缓存对象 + */ + private void removeLast() { + Node temp = last.prev; + temp.next = null; + last.prev = null; + last = temp; + currentSize--; + } + + /** + * 移动到链表头,表示这个节点是最新使用过的 + */ + private void moveExistingNodeToHead(Node node) { + if(node == first){ + return; + } + if(node != last){ + Node prev = node.prev; + Node next = node.next; + prev.next = next; + next.prev = prev; + }else{ + Node prev = node.prev; + prev.next = null; + last.prev = null; + last = prev; + } + node.next = first; + node.prev = null; + 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/group24/798277403/src/basic/LinkedList.java b/group24/798277403/src/basic/LinkedList.java new file mode 100644 index 0000000000..30d0b4a099 --- /dev/null +++ b/group24/798277403/src/basic/LinkedList.java @@ -0,0 +1,234 @@ +package basic; + +/** + * 自己实现的LinkedList + * Created by zhouliang on 2017-03-10. + */ +class LinkedList implements List { + + private int size; + private Node first; + private Node last; + + public LinkedList(){ + } + + @Override + public void add(E e) { + Node temp = new Node(e); + if(first != null){ + last.next = temp; + last = temp; + }else{ + first = temp; + last = temp; + } + size++; + } + + /** + * 指定下标添加元素 + * @param index 可以在链表末尾加,就是可以的等于size,不能大于size + * @param e 代表Element + */ + @Override + public void add(int index, E e) { + checkPositionIndex(index); + + Node temp = new Node(e); + if(index == size){ + last.next = temp; + last = temp; + }else{ + Node begin = first; + index--; + while(index>0){ + begin = begin.next; + index--; + } + Node next = begin.next; + begin.next = temp; + temp.next = next; + } + size++; + } + + @Override + public E get(int index) { + checkElementIndex(index); + + Node temp = first; + while(index>0){ + temp = temp.next; + index--; + } + return temp.value; + } + + @Override + public E remove(int index) { + checkElementIndex(index); + + Node temp; + if(index == 0){ + temp = first; + first = first.next; + size--; + return temp.value; + }else{ + temp = first; + index--; + //找到要删除节点的前一个节点 + while(index>0){ + temp = temp.next; + index--; + } + Node removeNode = temp.next; + temp.next = removeNode.next; + size--; + return removeNode.value; + + } + + } + + public E removeLast(){ + return remove(size-1); + } + + public void addFirst(E e){ + Node temp = new Node(e); + if(first == null){ + first = temp; + last = temp; + }else{ + temp.next = first; + first = temp; + } + size++; + } + + public void addLast(E e){ + Node temp = new Node(); + if(first == null){ + first = temp; + last = temp; + }else{ + last.next = temp; + last = temp; + } + size++; + } + + private void checkElementIndex(int index) { + if (!isElementIndex(index)) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + + size); + } + } + + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + + size); + } + } + + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + @Override + public int size() { + return size; + } + + private static class Node{ + E value; + Node next; + + Node(){ + + } + + Node(E e){ + this.value = e; + } + } + + /** + * 把该链表逆置 + * 例如链表为 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/group24/798277403/src/basic/LinkedListTest.java b/group24/798277403/src/basic/LinkedListTest.java new file mode 100644 index 0000000000..0611a1ddb7 --- /dev/null +++ b/group24/798277403/src/basic/LinkedListTest.java @@ -0,0 +1,53 @@ +package basic; + +import org.junit.Before; +import org.junit.Test; + +/** + * Created by zhouliang on 2017-03-10. + */ +public class LinkedListTest { + + private LinkedList myLinkedList = new LinkedList<>(); + + private java.util.LinkedList systemLinkedList = new java.util.LinkedList<>(); + + @Before + public void setUp(){ + for(int i=0; i<10; i++){ + myLinkedList.add(i); + systemLinkedList.add(i); + } + } + @Test + public void add() throws Exception { + for(int i=0; i<10; i++){ + System.out.println(myLinkedList.get(i)); + } + } + + @Test + public void remove() throws Exception { + myLinkedList.remove(5); + for(int i=0; i { + void add(E e); + void add(int index, E e); + E get(int index); + E remove(int index); + int size(); +} diff --git a/group24/798277403/src/basic/Queue.java b/group24/798277403/src/basic/Queue.java new file mode 100644 index 0000000000..371f2f9340 --- /dev/null +++ b/group24/798277403/src/basic/Queue.java @@ -0,0 +1,33 @@ +package basic; + +/** + * 自己实现的Queue,用自己的LinkedList实现 + * Created by zhouliang on 2017-03-10. + */ +class Queue { + + private LinkedList linkedList; + + public Queue(){ + this.linkedList = new LinkedList(); + } + /** + * 从队列头部添加元素 + * @param e 代表Element + */ + public void enQueue(E e){ + linkedList.addFirst(e); + } + + public E deQueue(){ + return linkedList.removeLast(); + } + + public boolean isEmpty(){ + return linkedList.size() > 0; + } + + public int size(){ + return linkedList.size(); + } +} diff --git a/group24/798277403/src/basic/QueueTest.java b/group24/798277403/src/basic/QueueTest.java new file mode 100644 index 0000000000..8af2de5ada --- /dev/null +++ b/group24/798277403/src/basic/QueueTest.java @@ -0,0 +1,36 @@ +package basic; + +import org.junit.Before; +import org.junit.Test; + +/** + * 自己实现的队列,先进先出 + * Created by zhouliang on 2017-03-10. + */ +public class QueueTest { + private Queue queue = new Queue<>(); + + + @Before + public void setUp(){ + for(int i=0; i<10; i++){ + queue.enQueue(i); + } + } + + @Test + public void enQueue() throws Exception { + System.out.println(queue.size()); + } + + @Test + public void deQueue() throws Exception { + System.out.println(queue.deQueue()+" "+queue.size()); + } + + @Test + public void isEmpty() throws Exception { + + } + +} \ No newline at end of file diff --git a/group24/798277403/src/basic/Stack.java b/group24/798277403/src/basic/Stack.java new file mode 100644 index 0000000000..e6351da277 --- /dev/null +++ b/group24/798277403/src/basic/Stack.java @@ -0,0 +1,34 @@ +package basic; + +/** + * 自己实现的Stack + * Created by zhouliang on 2017-03-10. + */ +class Stack { + + private ArrayList elementData; + + public Stack(){ + this.elementData = new ArrayList(); + } + + public void push(E e){ + elementData.add(e); + } + + public E pop(){ + return elementData.remove(elementData.size()-1); + } + + public E peek(){ + return elementData.get(elementData.size()-1); + } + + public boolean isEmpty(){ + return elementData.size() > 0; + } + + public int size(){ + return elementData.size(); + } +} diff --git a/group24/798277403/src/basic/StackTest.java b/group24/798277403/src/basic/StackTest.java new file mode 100644 index 0000000000..921560a0f0 --- /dev/null +++ b/group24/798277403/src/basic/StackTest.java @@ -0,0 +1,39 @@ +package basic; + +import org.junit.Before; +import org.junit.Test; + +/** + * Created by zhouliang on 2017-03-10. + */ +public class StackTest { + private Stack stack = new Stack<>(); + + @Before + public void setUp(){ + for(int i=0; i<10; i++){ + stack.push(i); + } + } + + @Test + public void pop() throws Exception { + System.out.println("size "+stack.size()); + while(stack.size()>0){ + System.out.println(stack.pop()); + } + } + + @Test + public void peek() throws Exception { + System.out.println(stack.size()); + int i = stack.peek(); + System.out.println(i+" "+stack.size()); + } + + @Test + public void isEmpty() throws Exception { + + } + +} \ No newline at end of file diff --git a/group24/798277403/src/basic/array/ArrayUtil.java b/group24/798277403/src/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..e29a4845bf --- /dev/null +++ b/group24/798277403/src/basic/array/ArrayUtil.java @@ -0,0 +1,235 @@ +package basic.array; + +import java.util.Arrays; + + +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 原数组 + */ + void reverseArray(int[] origin){ + if(origin!=null && origin.length>0){ + int i, n; + for(i=0, n=origin.length-1; i0) { + int index = 0; + int length = 0; + int[] temp = new int[oldArray.length]; + for(int i=0; iarray2[j]){ + merges[index] = array2[j]; + j++; + }else{ + merges[index] = array2[j]; + i++; + j++; + split++; + } + } + while(i0) { + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < array.length; i++) { + stringBuffer.append(array[i]); + if (i != array.length - 1) { + stringBuffer.append(seperator); + } + } + return stringBuffer.toString(); + }else{ + return null; + } + } + +} diff --git a/group24/798277403/src/basic/array/ArrayUtilTest.java b/group24/798277403/src/basic/array/ArrayUtilTest.java new file mode 100644 index 0000000000..792c778e75 --- /dev/null +++ b/group24/798277403/src/basic/array/ArrayUtilTest.java @@ -0,0 +1,92 @@ +package basic.array; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; + +/** + * Created by zhouliang on 2017-03-13. + */ +public class ArrayUtilTest { + private int[] array; + private ArrayUtil arrayUtil ; + private int SIZE = 11; + + @Before + public void setUp() throws Exception { + arrayUtil = new ArrayUtil(); + array = new int[SIZE]; + Random random = new Random(); + + for(int i=0; i implements List{ + + private int size; + private Node first; + private Node last; + + public LinkedList(){ + } + + @Override + public void add(E e) { + Node temp = new Node(e); + if(first != null){ + last.next = temp; + last = temp; + }else{ + first = temp; + last = temp; + } + size++; + } + + /** + * 指定下标添加元素 + * @param index 可以在链表末尾加,就是可以的等于size,不能大于size + * @param e 代表Element + */ + @Override + public void add(int index, E e) { + checkPositionIndex(index); + + Node temp = new Node(e); + if(index == size){ + last.next = temp; + last = temp; + }else{ + Node begin = first; + index--; + while(index>0){ + begin = begin.next; + index--; + } + Node next = begin.next; + begin.next = temp; + temp.next = next; + } + size++; + } + + @Override + public E get(int index) { + checkElementIndex(index); + + Node temp = first; + while(index>0){ + temp = temp.next; + index--; + } + return temp.value; + } + + @Override + public E remove(int index) { + checkElementIndex(index); + + Node temp; + if(index == 0){ + temp = first; + first = first.next; + size--; + return temp.value; + }else{ + temp = first; + index--; + //找到要删除节点的前一个节点 + while(index>0){ + temp = temp.next; + index--; + } + Node removeNode = temp.next; + temp.next = removeNode.next; + size--; + return removeNode.value; + + } + + } + + public E removeLast(){ + return remove(size-1); + } + + public void addFirst(E e){ + Node temp = new Node(e); + if(first == null){ + first = temp; + last = temp; + }else{ + temp.next = first; + first = temp; + } + size++; + } + + public void addLast(E e){ + Node temp = new Node(); + if(first == null){ + first = temp; + last = temp; + }else{ + last.next = temp; + last = temp; + } + size++; + } + + //检查index是否是合法的get下标 + private void checkElementIndex(int index) { + if (!isElementIndex(index)) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + + size); + } + } + + private boolean isElementIndex(int index) { + return index >= 0 && index < size; + } + + //检查index是否是合法的add下标 + private void checkPositionIndex(int index) { + if (!isPositionIndex(index)) { + throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + + size); + } + } + + private boolean isPositionIndex(int index) { + return index >= 0 && index <= size; + } + + @Override + public int size() { + return size; + } + + private static class Node{ + E value; + Node next; + Node(){ + } + Node(E e){ + this.value = e; + } + } + + + /** + * 把该链表逆置 + * 例如链表为 3->7->10 , 逆置后变为 10->7->3 + */ + public void reverse(){ + Node preNode = first; + + //头尾结点互换位置 + Node node = last; + last = first; + first = node; + + node = preNode.next; + Node nextNode; + + while (node != null) { + nextNode = node.next; + node.next = preNode; + preNode = node; + node = nextNode; + } + } + + /** + * 删除一个单链表的前半部分 + * 例如:list = 2->5->7->8 , 删除以后的值为 7->8 + * 如果list = 2->5->7->8->10 ,删除以后的值为7,8,10 + */ + public void removeFirstHalf(){ + int num = this.size/2; + this.size = this.size - num; + while(num>0){ + //Node temp = first.next; + first = first.next; + num--; + } + } + + /** + * 从第i个元素开始, 删除length 个元素 , 注意i从0开始 + * @param i + * @param length + */ + public void remove(int i, int length){ + checkPositionIndex(i); + if(length+i>size-1){ + throw new IndexOutOfBoundsException("Index: " + (i+length) + ", Size: " + + size); + } + int temp = 0; + Node newFirst = first; + Node beginNode = newFirst; + while(temp < i){ + beginNode = beginNode.next; + temp++; + } + Node endNode = beginNode.next; + size = size - length; + while(length>0){ + endNode = endNode.next; + length--; + } + first = newFirst; + beginNode.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(list==null || list.size()==0){ + return null; + }else{ + int[] result = new int[list.size()]; + int index = 0; + int length = 0; + Node temp = first; + for (int i=0; imin && (Integer)temp.value myLinkedList = new LinkedList<>(); + + private java.util.LinkedList systemLinkedList = new java.util.LinkedList<>(); + + @Before + public void setUp(){ + for(int i=0; i<10; i++){ + myLinkedList.add(i); + systemLinkedList.add(i); + } + } + @Test + public void add() throws Exception { + for(int i=0; i<10; i++){ + System.out.println(myLinkedList.get(i)); + } + } + + @Test + public void reverse(){ + myLinkedList.reverse(); + for(int i=0; i<10; i++){ + System.out.println(myLinkedList.get(i)); + } + } + + @Test + public void removeFirstHalf(){ + myLinkedList.removeFirstHalf(); + System.out.println(myLinkedList.size()); + for(int i=0; i list = new LinkedList(); + list.add(0); + list.add(7); + list.add(9); + int[] reuslt = myLinkedList.getElements(list); + System.out.println(reuslt.length); + for(int i=0; i list = new LinkedList(); + list.add(0); + list.add(7); + list.add(9); + myLinkedList.subtract(list); + for(int i=0; i list = new LinkedList(); + list.add(0); + list.add(2); + list.add(9); + list.add(9); + list.add(9); + list.add(9); + list.add(9); + list.add(9); + list.add(9); + + + + LinkedList result = myLinkedList.intersection(list); + for(int i=0; i { + void add(E e); + void add(int index, E e); + E get(int index); + E remove(int index); + int size(); +} diff --git a/group24/798277403/src/basic/stack/StackUtil.java b/group24/798277403/src/basic/stack/StackUtil.java new file mode 100644 index 0000000000..7e5c157306 --- /dev/null +++ b/group24/798277403/src/basic/stack/StackUtil.java @@ -0,0 +1,116 @@ +package basic.stack; + +import java.util.Stack; + +/** + * Created by zhouliang on 2017-04-08. + */ +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.empty()){ + return; + } + int i = getAndRemoveBottom(s); // 依次返回1、2、3 + reverse(s); + s.push(i); + } + + //移除并返回当前的栈底元素 + private static int getAndRemoveBottom(Stack s){ + int result = s.pop(); + if(s.empty()){ + return result; + }else{ + int bottom = getAndRemoveBottom(s); + s.push(result); + return bottom; + } + } + + + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param o + */ + public static void remove(Stack s,Object o) { + if(s.empty()){ + return; + } + Object temp = s.pop(); + if(temp == o){ + return; + } + remove(s,o); + s.push(temp); + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + Object[] result = new Object[len]; + int index = 0; + while(index s, int index){ + Object temp = s.pop(); + index--; + if(0 == index){ + s.push(temp); + return temp; + } + Object result = getIndex(s,index); + s.push(temp); + 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){ + char[] chars = s.toCharArray(); + Stack stack = new Stack(); + for(char c : chars){ + if(c=='(' || c=='[' || c=='{'){ + stack.push(c); + }else if(c==')'){ + char top = stack.peek(); + if(top == '('){ + stack.pop(); + } + }else if(c==']'){ + char top = stack.peek(); + if(top == '['){ + stack.pop(); + } + }else if(c=='}'){ + char top = stack.peek(); + if(top == '{'){ + stack.pop(); + } + } + } + + return stack.empty(); + } +} diff --git a/group24/798277403/src/basic/stack/StackUtilTest.java b/group24/798277403/src/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..c5ecd1fcbe --- /dev/null +++ b/group24/798277403/src/basic/stack/StackUtilTest.java @@ -0,0 +1,77 @@ +package basic.stack; + +import org.junit.Test; + +import java.util.Stack; + +/** + * Created by zhouliang on 2017-04-08. + */ +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); + while(!s.isEmpty()){ + System.out.println(s.pop()); + } + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + StackUtil.reverse(s); + while(!s.isEmpty()){ + System.out.println(s.pop()); + } + } + + @Test + public void remove(){ + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + StackUtil.remove(s,3); + while(!s.isEmpty()){ + System.out.println(s.pop()); + } + } + + @Test + public void getTop(){ + Stack s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + s.push(4); + s.push(5); + + Object[] result = StackUtil.getTop(s,2); + while(!s.isEmpty()){ + System.out.println(s.pop()); + } + + for(Object o : result){ + System.out.println(o); + } + } + + @Test + public void isValidPairs(){ + String s = "([e{d}f])"; + String s1 = "([b{x]y})"; + boolean result = StackUtil.isValidPairs(s); + System.out.println(result); + boolean result1 = StackUtil.isValidPairs(s1); + System.out.println(result1); + } +} diff --git a/group24/798277403/src/download/DownloadThread.java b/group24/798277403/src/download/DownloadThread.java new file mode 100644 index 0000000000..df55a6fee1 --- /dev/null +++ b/group24/798277403/src/download/DownloadThread.java @@ -0,0 +1,50 @@ +package download; + + +import download.api.Connection; + +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +class DownloadThread extends Thread{ + + private Connection conn; + private int startPos; + private int endPos; + private CyclicBarrier barrier; + private 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(); + + barrier.await(); //等待别的线程完成 + + } catch (Exception e) { + e.printStackTrace(); + + } + + } +} diff --git a/group24/798277403/src/download/FileDownloader.java b/group24/798277403/src/download/FileDownloader.java new file mode 100644 index 0000000000..928c1cf2e5 --- /dev/null +++ b/group24/798277403/src/download/FileDownloader.java @@ -0,0 +1,116 @@ +package download; + + +import download.api.Connection; +import download.api.ConnectionManager; +import download.api.DownloadListener; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.concurrent.CyclicBarrier; + +public class FileDownloader { + + private String url; + private String localFile; + + DownloadListener listener; + + ConnectionManager cm; + + + private static final int DOWNLOAD_TRHEAD_NUM = 3; + + 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_TRHEAD_NUM , new Runnable(){ + public void run(){ + listener.notifyFinished(); + } + }); + + Connection conn = null; + try { + conn = cm.open(this.url); + int length = conn.getContentLength(); + createPlaceHolderFile(this.localFile, length); + int[][] ranges = allocateDownloadRange(DOWNLOAD_TRHEAD_NUM, length); + for(int i=0; i< DOWNLOAD_TRHEAD_NUM; i++){ + DownloadThread thread = new DownloadThread( + cm.open(url), + ranges[i][0], + ranges[i][1], + localFile, + barrier); + thread.start(); + } + } catch (Exception e) { + e.printStackTrace(); + }finally{ + if(conn != null){ + conn.close(); + } + } + } + + //往文件里面写0,占住磁盘 + private void createPlaceHolderFile(String fileName, int contentLen) throws IOException { + RandomAccessFile file = new RandomAccessFile(fileName,"rw"); + for(int i=0; i 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 (IOException e) { + e.printStackTrace(); + } + return -1; + } + + @Override + public void close() { + + } + +} diff --git a/group24/798277403/src/download/impl/ConnectionManagerImpl.java b/group24/798277403/src/download/impl/ConnectionManagerImpl.java new file mode 100644 index 0000000000..e721d46194 --- /dev/null +++ b/group24/798277403/src/download/impl/ConnectionManagerImpl.java @@ -0,0 +1,14 @@ +package download.impl; + +import download.api.Connection; +import download.api.ConnectionException; +import download.api.ConnectionManager; + +public class ConnectionManagerImpl implements ConnectionManager { + + @Override + public Connection open(String url) throws ConnectionException { + return new ConnectionImpl(url); + } + +} diff --git a/group24/798277403/src/download/test/ConnectionTest.java b/group24/798277403/src/download/test/ConnectionTest.java new file mode 100644 index 0000000000..cd8c9ca04d --- /dev/null +++ b/group24/798277403/src/download/test/ConnectionTest.java @@ -0,0 +1,53 @@ +package download.test; + +import download.api.Connection; +import download.api.ConnectionManager; +import download.impl.ConnectionManagerImpl; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + + +public class ConnectionTest { + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testContentLength() throws Exception{ + 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 Exception{ + + 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, 35469); + + 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/group24/798277403/src/download/test/FileDownloaderTest.java b/group24/798277403/src/download/test/FileDownloaderTest.java new file mode 100644 index 0000000000..f0337f6bc1 --- /dev/null +++ b/group24/798277403/src/download/test/FileDownloaderTest.java @@ -0,0 +1,63 @@ +package download.test; + +import download.FileDownloader; +import download.api.ConnectionManager; +import download.api.DownloadListener; +import 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://www.hinews.cn/pic/0/13/91/26/13912621_821796.jpg"; + + String url = "http://images2015.cnblogs.com/blog/610238/201604/610238-20160421154632101-286208268.png"; + + FileDownloader downloader = new FileDownloader(url,"C:\\Users\\zhouliang\\Desktop\\mycoding\\test.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/group24/798277403/src/litestruts/LoginAction.java b/group24/798277403/src/litestruts/LoginAction.java new file mode 100644 index 0000000000..8c448e3630 --- /dev/null +++ b/group24/798277403/src/litestruts/LoginAction.java @@ -0,0 +1,41 @@ +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/group24/798277403/src/litestruts/Struts.java b/group24/798277403/src/litestruts/Struts.java new file mode 100644 index 0000000000..2139dd8551 --- /dev/null +++ b/group24/798277403/src/litestruts/Struts.java @@ -0,0 +1,155 @@ +package litestruts; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/* + +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字段中。 + +*/ +public class Struts { + + public static View runAction(String actionName, Map parameters) { + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = null; + Class actionClass = null; + LoginAction loginAction = null; + View view = new View(); + try { + db = documentBuilderFactory.newDocumentBuilder(); + Document document = db.parse("src/litestruts/struts.xml"); + NodeList nodeList = document.getElementsByTagName("action"); + + //遍历每一个action节点 + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + //获取action节点的所有属性集合 + NamedNodeMap attrs = node.getAttributes(); + //获取name结点的值 + String nodeName = attrs.getNamedItem("name").getNodeValue(); + + if(nodeName.equals(actionName)){ + //获取LoginAction实例 + actionClass = Class.forName(attrs.getNamedItem("class").getNodeValue()); + loginAction = (LoginAction) actionClass.newInstance(); + + //设置用户名密码属性 + Set> entrySet = parameters.entrySet(); + for (Map.Entry entry : entrySet) { + if (entry.getKey().equals("name")) { + loginAction.setName(entry.getValue()); + } + if (entry.getKey().equals("password")) { + loginAction.setPassword(entry.getValue()); + } + } + + //执行execute()方法 + String result = loginAction.execute(); + + //将message封装到view + String message = loginAction.getMessage(); + Map map = new HashMap(); + map.put("message",message); + view.setParameters(map); + + //解析对应的result节点 + NodeList childNodes = node.getChildNodes(); + //遍历childNodes获取每个节点的节点名和节点值 + for (int k = 0; k < childNodes.getLength(); k++) { + Node childNode = childNodes.item(k); + //区分出text类型的node以及element类型的node + if (childNode.getNodeType() == Node.ELEMENT_NODE) { + NamedNodeMap attributes = childNode.getAttributes(); + String nodeValue = attributes.getNamedItem("name").getNodeValue(); + if(nodeValue.equals(result)){ + view.setJsp(childNode.getTextContent()); + } + } + + } + + } + + } + } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + + return view; + } + +/* DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = null; + Class actionClass = null; + LoginAction loginAction = null; + try { + db = documentBuilderFactory.newDocumentBuilder(); + Document document = db.parse("src/week2/litestruts/struts.xml"); + NodeList nodeList = document.getElementsByTagName("action"); + System.out.println("一共有" + nodeList.getLength() + "个结点"); + //遍历每一个action节点 + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + //获取action节点的所有属性集合 + NamedNodeMap attrs = node.getAttributes(); + //遍历action的属性 + for (int j = 0; j < attrs.getLength(); j++) { + //通过item(index)方法获取book节点的某一个属性 + Node attr = attrs.item(j); + String name = attrs.getNamedItem("name").getNodeValue(); + System.out.println("++++++++++"+name); + //获取属性名 + System.out.print("属性名:" + attr.getNodeName()); + //获取属性值 + System.out.println("--属性值" + attr.getNodeValue()); + if(attr.getNodeName().equals(actionName)){ + actionClass = Class.forName(attr.getNodeValue()); + loginAction = (LoginAction) actionClass.newInstance(); + } + } + //解析book节点的子节点 + NodeList childNodes = node.getChildNodes(); + //遍历childNodes获取每个节点的节点名和节点值 + for (int k = 0; k < childNodes.getLength(); k++) { + //区分出text类型的node以及element类型的node + if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) { + //获取了element类型节点的节点名 + System.out.print(childNodes.item(k).getNodeName()); + //获取了element类型节点的节点值 + System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue()); + System.out.println("--节点值是:" + childNodes.item(k).getTextContent()); + } + } + } + } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + }*/ +} \ No newline at end of file diff --git a/group24/798277403/src/litestruts/StrutsTest.java b/group24/798277403/src/litestruts/StrutsTest.java new file mode 100644 index 0000000000..868a78cdba --- /dev/null +++ b/group24/798277403/src/litestruts/StrutsTest.java @@ -0,0 +1,40 @@ +package 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/group24/798277403/src/litestruts/View.java b/group24/798277403/src/litestruts/View.java new file mode 100644 index 0000000000..1eed614744 --- /dev/null +++ b/group24/798277403/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/group24/798277403/src/mini_jvm/clz/AccessFlag.java b/group24/798277403/src/mini_jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..b6717402da --- /dev/null +++ b/group24/798277403/src/mini_jvm/clz/AccessFlag.java @@ -0,0 +1,25 @@ +package mini_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/group24/798277403/src/mini_jvm/clz/ClassFile.java b/group24/798277403/src/mini_jvm/clz/ClassFile.java new file mode 100644 index 0000000000..4cf756c090 --- /dev/null +++ b/group24/798277403/src/mini_jvm/clz/ClassFile.java @@ -0,0 +1,65 @@ +package mini_jvm.clz; + + +import mini_jvm.constant.ClassInfo; +import mini_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/group24/798277403/src/mini_jvm/clz/ClassIndex.java b/group24/798277403/src/mini_jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..dcc59908f0 --- /dev/null +++ b/group24/798277403/src/mini_jvm/clz/ClassIndex.java @@ -0,0 +1,19 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/ClassInfo.java b/group24/798277403/src/mini_jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..ed39387440 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/ClassInfo.java @@ -0,0 +1,24 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/ConstantInfo.java b/group24/798277403/src/mini_jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..d488321043 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/ConstantInfo.java @@ -0,0 +1,29 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/ConstantPool.java b/group24/798277403/src/mini_jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..c8d30c78db --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/ConstantPool.java @@ -0,0 +1,27 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/FieldRefInfo.java b/group24/798277403/src/mini_jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..3d74c4244f --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/FieldRefInfo.java @@ -0,0 +1,54 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/MethodRefInfo.java b/group24/798277403/src/mini_jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..4037881ad8 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/MethodRefInfo.java @@ -0,0 +1,55 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/NameAndTypeInfo.java b/group24/798277403/src/mini_jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..badba119df --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,45 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/NullConstantInfo.java b/group24/798277403/src/mini_jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..28d102c997 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/NullConstantInfo.java @@ -0,0 +1,13 @@ +package mini_jvm.constant; + +public class NullConstantInfo extends ConstantInfo { + + public NullConstantInfo(){ + + } + @Override + public int getType() { + return -1; + } + +} diff --git a/group24/798277403/src/mini_jvm/constant/StringInfo.java b/group24/798277403/src/mini_jvm/constant/StringInfo.java new file mode 100644 index 0000000000..2a9387d247 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/StringInfo.java @@ -0,0 +1,26 @@ +package mini_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/group24/798277403/src/mini_jvm/constant/UTF8Info.java b/group24/798277403/src/mini_jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..6fc44f5355 --- /dev/null +++ b/group24/798277403/src/mini_jvm/constant/UTF8Info.java @@ -0,0 +1,32 @@ +package mini_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/group24/798277403/src/mini_jvm/loader/ByteCodeIterator.java b/group24/798277403/src/mini_jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..35ca6420b6 --- /dev/null +++ b/group24/798277403/src/mini_jvm/loader/ByteCodeIterator.java @@ -0,0 +1,55 @@ +package mini_jvm.loader; + +import mini_jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + private byte[] codes; + private int pos; + + 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/group24/798277403/src/mini_jvm/loader/ClassFileLoader.java b/group24/798277403/src/mini_jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..db3402aeb6 --- /dev/null +++ b/group24/798277403/src/mini_jvm/loader/ClassFileLoader.java @@ -0,0 +1,94 @@ +package mini_jvm.loader; + +import mini_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()); + } + +} diff --git a/group24/798277403/src/mini_jvm/test/EmployeeV1.java b/group24/798277403/src/mini_jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..aed78de928 --- /dev/null +++ b/group24/798277403/src/mini_jvm/test/EmployeeV1.java @@ -0,0 +1,28 @@ +package mini_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/group24/798277403/src/mini_jvm/util/Util.java b/group24/798277403/src/mini_jvm/util/Util.java new file mode 100644 index 0000000000..bc2e724f03 --- /dev/null +++ b/group24/798277403/src/mini_jvm/util/Util.java @@ -0,0 +1,22 @@ +package mini_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 implements List { - - private Object[] elementData; - - private int size; - - public ArrayList(int size){ - this.elementData = new Object[size]; - } - - //默认大小为10 - public ArrayList(){ - this.elementData = new Object[10]; - } - - //判断是否需要扩展容量 ((旧容量 * 3) / 2) + 1 - private void checkcapacity(int index){ - if(index>elementData.length){ - int length = (elementData.length*3)/2+1; - /* - Object[] temp = new Object[length]; - for(int i=0; i= 0 && index < size; - } - - private void checkPositionIndex(int index) { - if (!isPositionIndex(index)) { - throw new IndexOutOfBoundsException("Index: " + index + ", Size: " - + size); - } - } - - private boolean isPositionIndex(int index) { - return index >= 0 && index <= size; - } - - public Iterator iterator() { - return new ArrayListIterator(this); - } - - private class ArrayListIterator implements Iterator { - private ArrayList list = null; - private int position = 0; - - private ArrayListIterator(ArrayList list) { - this.list = list; - } - - @Override - public boolean hasNext() { - if ((position + 1) > size()) { - return false; - } - return true; - } - - @Override - public E next() { - return list.get(position++); - } - } -} diff --git a/group24/798277403/src/week1/ArrayListTest.java b/group24/798277403/src/week1/ArrayListTest.java deleted file mode 100644 index 98e30a222a..0000000000 --- a/group24/798277403/src/week1/ArrayListTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package week1; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Created by zhouliang on 2017-03-10. - */ -public class ArrayListTest { - - private ArrayList arrayList = new ArrayList(); - - @Before - public void setUp(){ - for(int i=0; i<100; i++){ - arrayList.add(i); - } - } - - @Test - public void add() throws Exception { - for(int i=100; i<1000; i++){ - arrayList.add(i); - } - Assert.assertEquals(1000,arrayList.size()); - } - - @Test - public void add1() throws Exception { - java.util.LinkedList l = new java.util.LinkedList(); - } - - @Test - public void get() throws Exception { - System.out.println(arrayList.get(99)); - } - - @Test - public void remove() throws Exception { - System.out.println(arrayList.size()); - arrayList.remove(arrayList.size()-1); - System.out.println(arrayList.size()); - //Assert.assertEquals((Integer)99,(Integer)arrayList.size()); - } - - @Test - public void iterator() throws Exception { - Iterator iterator = arrayList.iterator(); - while(iterator.hasNext()){ - System.out.println(iterator.next()); - } - } - -} \ No newline at end of file diff --git a/group24/798277403/src/week1/BinaryTreeNode.java b/group24/798277403/src/week1/BinaryTreeNode.java deleted file mode 100644 index e680d5ed15..0000000000 --- a/group24/798277403/src/week1/BinaryTreeNode.java +++ /dev/null @@ -1,72 +0,0 @@ -package week1; - -/** - * 自己实现的BinaryTreeNode - * Created by zhouliang on 2017-03-10. - */ -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 && left==null && right==null){ - this.setData(o); - this.setLeft(null); - this.setRight(null); - return this; - }else{ - BinaryTreeNode temp = this; - BinaryTreeNode node = new BinaryTreeNode(); - while(true){ - if((Integer)o > (Integer)temp.getData()){ - if(temp.getRight() == null){ - node.setData(o); - node.setLeft(null); - node.setRight(null); - - temp.setRight(node); - return this; - }else{ - temp = temp.getRight(); - } - }else{ - if(temp.getLeft() == null){ - node.setData(o); - node.setLeft(null); - node.setRight(null); - - temp.setLeft(node); - return this; - }else{ - temp = temp.getLeft(); - } - } - } - } - } -} diff --git a/group24/798277403/src/week1/Iterator.java b/group24/798277403/src/week1/Iterator.java deleted file mode 100644 index 73ba87c125..0000000000 --- a/group24/798277403/src/week1/Iterator.java +++ /dev/null @@ -1,10 +0,0 @@ -package week1; - -/** - * 自己实现的Iterator - * Created by zhouliang on 2017-03-10. - */ -interface Iterator { - boolean hasNext(); - Object next(); -} diff --git a/group24/798277403/src/week1/LinkedList.java b/group24/798277403/src/week1/LinkedList.java deleted file mode 100644 index d0933cfcb1..0000000000 --- a/group24/798277403/src/week1/LinkedList.java +++ /dev/null @@ -1,161 +0,0 @@ -package week1; - -/** - * 自己实现的LinkedList - * Created by zhouliang on 2017-03-10. - */ -class LinkedList implements List { - - private int size; - private Node first; - private Node last; - - public LinkedList(){ - } - - @Override - public void add(E e) { - Node temp = new Node(e); - if(first != null){ - last.next = temp; - last = temp; - }else{ - first = temp; - last = temp; - } - size++; - } - - /** - * 指定下标添加元素 - * @param index 可以在链表末尾加,就是可以的等于size,不能大于size - * @param e 代表Element - */ - @Override - public void add(int index, E e) { - checkPositionIndex(index); - - Node temp = new Node(e); - if(index == size){ - last.next = temp; - last = temp; - }else{ - Node begin = first; - index--; - while(index>0){ - begin = begin.next; - index--; - } - Node next = begin.next; - begin.next = temp; - temp.next = next; - } - size++; - } - - @Override - public E get(int index) { - checkElementIndex(index); - - Node temp = first; - while(index>0){ - temp = temp.next; - index--; - } - return temp.value; - } - - @Override - public E remove(int index) { - checkElementIndex(index); - - Node temp; - if(index == 0){ - temp = first; - first = first.next; - size--; - return temp.value; - }else{ - temp = first; - index--; - //找到要删除节点的前一个节点 - while(index>0){ - temp = temp.next; - index--; - } - Node removeNode = temp.next; - temp.next = removeNode.next; - size--; - return removeNode.value; - - } - - } - - public E removeLast(){ - return remove(size-1); - } - - public void addFirst(E e){ - Node temp = new Node(e); - if(first == null){ - first = temp; - last = temp; - }else{ - temp.next = first; - first = temp; - } - size++; - } - - public void addLast(E e){ - Node temp = new Node(); - if(first == null){ - first = temp; - last = temp; - }else{ - last.next = temp; - last = temp; - } - size++; - } - - private void checkElementIndex(int index) { - if (!isElementIndex(index)) { - throw new IndexOutOfBoundsException("Index: " + index + ", Size: " - + size); - } - } - - private boolean isElementIndex(int index) { - return index >= 0 && index < size; - } - - private void checkPositionIndex(int index) { - if (!isPositionIndex(index)) { - throw new IndexOutOfBoundsException("Index: " + index + ", Size: " - + size); - } - } - - private boolean isPositionIndex(int index) { - return index >= 0 && index <= size; - } - @Override - public int size() { - return size; - } - - private static class Node{ - E value; - Node next; - - Node(){ - - } - - Node(E e){ - this.value = e; - } - } -} diff --git a/group24/798277403/src/week1/LinkedListTest.java b/group24/798277403/src/week1/LinkedListTest.java deleted file mode 100644 index 9a8a9d936d..0000000000 --- a/group24/798277403/src/week1/LinkedListTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package week1; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by zhouliang on 2017-03-10. - */ -public class LinkedListTest { - - private LinkedList myLinkedList = new LinkedList<>(); - - private java.util.LinkedList systemLinkedList = new java.util.LinkedList<>(); - - @Before - public void setUp(){ - for(int i=0; i<10; i++){ - myLinkedList.add(i); - systemLinkedList.add(i); - } - } - @Test - public void add() throws Exception { - for(int i=0; i<10; i++){ - System.out.println(myLinkedList.get(i)); - } - } - - @Test - public void remove() throws Exception { - myLinkedList.remove(5); - for(int i=0; i { - void add(E e); - void add(int index, E e); - E get(int index); - E remove(int index); - int size(); -} diff --git a/group24/798277403/src/week1/Queue.java b/group24/798277403/src/week1/Queue.java deleted file mode 100644 index 184f3a5336..0000000000 --- a/group24/798277403/src/week1/Queue.java +++ /dev/null @@ -1,33 +0,0 @@ -package week1; - -/** - * 自己实现的Queue,用自己的LinkedList实现 - * Created by zhouliang on 2017-03-10. - */ -class Queue { - - private LinkedList linkedList; - - public Queue(){ - this.linkedList = new LinkedList(); - } - /** - * 从队列头部添加元素 - * @param e 代表Element - */ - public void enQueue(E e){ - linkedList.addFirst(e); - } - - public E deQueue(){ - return linkedList.removeLast(); - } - - public boolean isEmpty(){ - return linkedList.size() > 0; - } - - public int size(){ - return linkedList.size(); - } -} diff --git a/group24/798277403/src/week1/QueueTest.java b/group24/798277403/src/week1/QueueTest.java deleted file mode 100644 index b5a333f64d..0000000000 --- a/group24/798277403/src/week1/QueueTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package week1; - -import org.junit.Before; -import org.junit.Test; - -/** - * 自己实现的队列,先进先出 - * Created by zhouliang on 2017-03-10. - */ -public class QueueTest { - private Queue queue = new Queue<>(); - - - @Before - public void setUp(){ - for(int i=0; i<10; i++){ - queue.enQueue(i); - } - } - - @Test - public void enQueue() throws Exception { - System.out.println(queue.size()); - } - - @Test - public void deQueue() throws Exception { - System.out.println(queue.deQueue()+" "+queue.size()); - } - - @Test - public void isEmpty() throws Exception { - - } - -} \ No newline at end of file diff --git a/group24/798277403/src/week1/Stack.java b/group24/798277403/src/week1/Stack.java deleted file mode 100644 index f85aa2ada5..0000000000 --- a/group24/798277403/src/week1/Stack.java +++ /dev/null @@ -1,34 +0,0 @@ -package week1; - -/** - * 自己实现的Stack - * Created by zhouliang on 2017-03-10. - */ -class Stack { - - private ArrayList elementData; - - public Stack(){ - this.elementData = new ArrayList(); - } - - public void push(E e){ - elementData.add(e); - } - - public E pop(){ - return elementData.remove(elementData.size()-1); - } - - public E peek(){ - return elementData.get(elementData.size()-1); - } - - public boolean isEmpty(){ - return elementData.size() > 0; - } - - public int size(){ - return elementData.size(); - } -} diff --git a/group24/798277403/src/week1/StackTest.java b/group24/798277403/src/week1/StackTest.java deleted file mode 100644 index f4213d66d3..0000000000 --- a/group24/798277403/src/week1/StackTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package week1; - -import org.junit.Before; -import org.junit.Test; - -/** - * Created by zhouliang on 2017-03-10. - */ -public class StackTest { - private Stack stack = new Stack<>(); - - @Before - public void setUp(){ - for(int i=0; i<10; i++){ - stack.push(i); - } - } - - @Test - public void pop() throws Exception { - System.out.println("size "+stack.size()); - while(stack.size()>0){ - System.out.println(stack.pop()); - } - } - - @Test - public void peek() throws Exception { - System.out.println(stack.size()); - int i = stack.peek(); - System.out.println(i+" "+stack.size()); - } - - @Test - public void isEmpty() throws Exception { - - } - -} \ No newline at end of file diff --git a/group24/798277403/src/week2/array/ArrayUtil.java b/group24/798277403/src/week2/array/ArrayUtil.java deleted file mode 100644 index 04c03f95e0..0000000000 --- a/group24/798277403/src/week2/array/ArrayUtil.java +++ /dev/null @@ -1,235 +0,0 @@ -package week2.array; - -import java.util.Arrays; - - -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 原数组 - */ - void reverseArray(int[] origin){ - if(origin!=null && origin.length>0){ - int i, n; - for(i=0, n=origin.length-1; i0) { - int index = 0; - int length = 0; - int[] temp = new int[oldArray.length]; - for(int i=0; iarray2[j]){ - merges[index] = array2[j]; - j++; - }else{ - merges[index] = array2[j]; - i++; - j++; - split++; - } - } - while(i0) { - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < array.length; i++) { - stringBuffer.append(array[i]); - if (i != array.length - 1) { - stringBuffer.append(seperator); - } - } - return stringBuffer.toString(); - }else{ - return null; - } - } - -} diff --git a/group24/798277403/src/week2/array/ArrayUtilTest.java b/group24/798277403/src/week2/array/ArrayUtilTest.java deleted file mode 100644 index 77c99242fa..0000000000 --- a/group24/798277403/src/week2/array/ArrayUtilTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package week2.array; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.Random; - -/** - * Created by zhouliang on 2017-03-13. - */ -public class ArrayUtilTest { - private int[] array; - private ArrayUtil arrayUtil ; - private int SIZE = 11; - - @Before - public void setUp() throws Exception { - arrayUtil = new ArrayUtil(); - array = new int[SIZE]; - Random random = new Random(); - - for(int i=0; i 配置,以及execute的返回值, 确定哪一个jsp, -放到View对象的jsp字段中。 - -*/ -public class Struts { - - public static View runAction(String actionName, Map parameters) { - - DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = null; - Class actionClass = null; - LoginAction loginAction = null; - View view = new View(); - try { - db = documentBuilderFactory.newDocumentBuilder(); - Document document = db.parse("src/week2/litestruts/struts.xml"); - NodeList nodeList = document.getElementsByTagName("action"); - - //遍历每一个action节点 - for (int i = 0; i < nodeList.getLength(); i++) { - Node node = nodeList.item(i); - //获取action节点的所有属性集合 - NamedNodeMap attrs = node.getAttributes(); - //获取name结点的值 - String nodeName = attrs.getNamedItem("name").getNodeValue(); - - if(nodeName.equals(actionName)){ - //获取LoginAction实例 - actionClass = Class.forName(attrs.getNamedItem("class").getNodeValue()); - loginAction = (LoginAction) actionClass.newInstance(); - - //设置用户名密码属性 - Set> entrySet = parameters.entrySet(); - for (Map.Entry entry : entrySet) { - if (entry.getKey().equals("name")) { - loginAction.setName(entry.getValue()); - } - if (entry.getKey().equals("password")) { - loginAction.setPassword(entry.getValue()); - } - } - - //执行execute()方法 - String result = loginAction.execute(); - - //将message封装到view - String message = loginAction.getMessage(); - Map map = new HashMap(); - map.put("message",message); - view.setParameters(map); - - //解析对应的result节点 - NodeList childNodes = node.getChildNodes(); - //遍历childNodes获取每个节点的节点名和节点值 - for (int k = 0; k < childNodes.getLength(); k++) { - Node childNode = childNodes.item(k); - //区分出text类型的node以及element类型的node - if (childNode.getNodeType() == Node.ELEMENT_NODE) { - NamedNodeMap attributes = childNode.getAttributes(); - String nodeValue = attributes.getNamedItem("name").getNodeValue(); - if(nodeValue.equals(result)){ - view.setJsp(childNode.getTextContent()); - } - } - - } - - } - - } - } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - } - - return view; - } - -/* DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = null; - Class actionClass = null; - LoginAction loginAction = null; - try { - db = documentBuilderFactory.newDocumentBuilder(); - Document document = db.parse("src/week2/litestruts/struts.xml"); - NodeList nodeList = document.getElementsByTagName("action"); - System.out.println("一共有" + nodeList.getLength() + "个结点"); - //遍历每一个action节点 - for (int i = 0; i < nodeList.getLength(); i++) { - Node node = nodeList.item(i); - //获取action节点的所有属性集合 - NamedNodeMap attrs = node.getAttributes(); - //遍历action的属性 - for (int j = 0; j < attrs.getLength(); j++) { - //通过item(index)方法获取book节点的某一个属性 - Node attr = attrs.item(j); - String name = attrs.getNamedItem("name").getNodeValue(); - System.out.println("++++++++++"+name); - //获取属性名 - System.out.print("属性名:" + attr.getNodeName()); - //获取属性值 - System.out.println("--属性值" + attr.getNodeValue()); - if(attr.getNodeName().equals(actionName)){ - actionClass = Class.forName(attr.getNodeValue()); - loginAction = (LoginAction) actionClass.newInstance(); - } - } - //解析book节点的子节点 - NodeList childNodes = node.getChildNodes(); - //遍历childNodes获取每个节点的节点名和节点值 - for (int k = 0; k < childNodes.getLength(); k++) { - //区分出text类型的node以及element类型的node - if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) { - //获取了element类型节点的节点名 - System.out.print(childNodes.item(k).getNodeName()); - //获取了element类型节点的节点值 - System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue()); - System.out.println("--节点值是:" + childNodes.item(k).getTextContent()); - } - } - } - } catch (ParserConfigurationException | SAXException | IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - }*/ -} \ No newline at end of file diff --git a/group24/798277403/src/week2/litestruts/StrutsTest.java b/group24/798277403/src/week2/litestruts/StrutsTest.java deleted file mode 100644 index 5c4379d912..0000000000 --- a/group24/798277403/src/week2/litestruts/StrutsTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package week2.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/group24/798277403/src/week2/litestruts/View.java b/group24/798277403/src/week2/litestruts/View.java deleted file mode 100644 index 01a422a808..0000000000 --- a/group24/798277403/src/week2/litestruts/View.java +++ /dev/null @@ -1,23 +0,0 @@ -package 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/group24/798277403/src/week2/litestruts/struts.xml b/group24/798277403/src/week2/litestruts/struts.xml deleted file mode 100644 index 54550a4174..0000000000 --- a/group24/798277403/src/week2/litestruts/struts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - /jsp/homepage.jsp - /jsp/showLogin.jsp - - - /jsp/welcome.jsp - /jsp/error.jsp - - diff --git a/group27/1016908591/week04/src/com/coderising/jvm/clz/AccessFlag.java b/group27/1016908591/week04/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/clz/ClassFile.java b/group27/1016908591/week04/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..650ca8375d --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/clz/ClassIndex.java b/group27/1016908591/week04/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/ClassInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..aea9048ea4 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..466b072244 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/ConstantPool.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..86c0445695 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..65475e194c --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..7f05870020 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..402f9dec86 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..936736016f --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/StringInfo.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/constant/UTF8Info.java b/group27/1016908591/week04/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group27/1016908591/week04/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/1016908591/week04/src/com/coderising/jvm/loader/ClassFileLoader.java b/group27/1016908591/week04/src/com/coderising/jvm/loader/ClassFileLoader.java index b1b316dbeb..122f174ab6 100644 --- a/group27/1016908591/week04/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group27/1016908591/week04/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -15,9 +15,179 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.test.ClassFileParser; + public class ClassFileLoader { +/* + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + className = className.replace('.', File.separatorChar); + + for(String path:this.clzPaths) + { + String clzFileName = path + File.separatorChar+className; + byte[] codes = loadClassFile_V2(clzFileName); + if(codes != null){ + return codes; + } + + } + + return null; + + + } + + private byte[] loadClassFile_V2(String clzFileName) { + File f= new File(clzFileName); + try { + return IOUtils.toByteArray(new FileInputStream(f)); + + } catch (Exception e) { + + return null; + } + + } + + //第一种加载类的方法 + 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(); + return null; + } +/* + public void addClassPath(String path) { + if(this.clzPaths.contains(path)) + { + return; + } + this.clzPaths.add(path); + + } + + public String getClassPath() { + int count = 0; + String clzP = null; + for(String clzPathName:clzPaths){ + if(count clzPaths = new ArrayList(); /* @@ -97,7 +267,7 @@ public String getClassPath() { public byte[] readBinaryCode(String className) throws IOException { className = className.replace('.', File.separatorChar); for(String path:this.clzPaths){ - String clz = path+File.separatorChar+className; + String clz = path+File.separatorChar+className+".class"; byte[] codes = loadClassFile_V2(clz); if(codes!=null){ return codes; @@ -110,6 +280,8 @@ public byte[] readBinaryCode(String className) throws IOException { return null; } + + private byte[] loadClassFile_V2(String clz) throws IOException { BufferedInputStream in = null; @@ -139,7 +311,8 @@ private byte[] loadClassFile_V2(String clz) throws IOException { return null; } - + + /* } @@ -173,8 +346,14 @@ public String getClassPathV1(){ return StringUtils.join(this.clzPaths,";"); } */ - - - + public ClassFile loadClass(String className) throws IOException { + //变成字节数组 + byte[] codes = this.readBinaryCode(className); + + ClassFileParser parser = new ClassFileParser(); + //把字节数组传给解析类 + return parser.parse(codes); + + } } diff --git a/group27/1016908591/week04/src/com/coderising/jvm/test/ByteCodeIterator.java b/group27/1016908591/week04/src/com/coderising/jvm/test/ByteCodeIterator.java new file mode 100644 index 0000000000..75c57e5755 --- /dev/null +++ b/group27/1016908591/week04/src/com/coderising/jvm/test/ByteCodeIterator.java @@ -0,0 +1,47 @@ +package com.coderising.jvm.test; + +import java.lang.reflect.Array; +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 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 byte[] getBytes(int len) { + if (pos+len>=codes.length) { + throw new ArrayIndexOutOfBoundsException(); + } + byte[] data = Arrays.copyOfRange(codes, pos, pos+len); + pos +=len; + return data; + } + + +} diff --git a/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileParser.java b/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileParser.java new file mode 100644 index 0000000000..1ebd2d4c1b --- /dev/null +++ b/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileParser.java @@ -0,0 +1,114 @@ +package com.coderising.jvm.test; + +import java.io.UnsupportedEncodingException; + +import javax.management.RuntimeErrorException; + +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 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); + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + + return null; + } + + private ClassIndex parseClassInfex(ByteCodeIterator iter) { + + return null; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + //取出常量池的个数 + int constPoolCount = iter.nextU2ToInt(); + System.out.println("Constant pool Count:"+constPoolCount); + //定义一个常量池 + ConstantPool pool = new ConstantPool(); + //因为数组的第零项是无效的,数组从0开始,但是JVM确从1开始 + 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); + //把classInfo加入到常量池中 + 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) { + // TODO Auto-generated catch block + 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 RuntimeErrorException(null, "the constant pool tag"+tag+"has not been implemented yet "); + } + } + + + System.out.println("Finshed reading Constant pool"); + return pool; + } + + +} diff --git a/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileloaderTest.java index 5801c7ca04..9119be2105 100644 --- a/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/1016908591/week04/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -7,6 +7,13 @@ import org.junit.Before; import org.junit.Test; +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.MethodRefInfo; +import com.coderising.jvm.constant.NameAndTypeInfo; +import com.coderising.jvm.constant.UTF8Info; import com.coderising.jvm.loader.ClassFileLoader; @@ -16,9 +23,28 @@ public class ClassFileloaderTest { - static String path1 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-jvm\\bin"; + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + + static String path1 = "E:\\Git\\myGit\\coding2017\\group27\\1016908591\\week04\\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"; + + + try { + clzFile = loader.loadClass(className); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + clzFile.print(); + } @Before @@ -49,14 +75,8 @@ public void testClassFileLength() throws IOException { loader.addClassPath(path1); String className = "com.coderising.jvm.test.EmployeeV1"; - //装载这个类 - byte[] byteCodes = null; - try { - byteCodes = loader.readBinaryCode(className); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + + byte[] byteCodes = loader.readBinaryCode(className); // 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大 Assert.assertEquals(1056, byteCodes.length); @@ -72,7 +92,7 @@ public void testMagicNumber() throws IOException{ byte[] byteCodes = loader.readBinaryCode(className); byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; - //这个函数是关于16进制字符串 + String acctualValue = this.byteToHexString(codes); Assert.assertEquals("cafebabe", acctualValue); @@ -80,21 +100,113 @@ public void testMagicNumber() throws IOException{ + 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/group27/1016908591/week04/src/com/coding/basic/stack/Stack.java b/group27/1016908591/week04/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..9a35110681 --- /dev/null +++ b/group27/1016908591/week04/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,44 @@ +package com.coding.basic.stack; +import java.util.Arrays; +import java.util.EmptyStackException; + + +import com.coding.basic.array.ArrayList; + +public class Stack { + private ArrayList elementData = new ArrayList(); + private int topIndex =-1;//栈顶元素索引 + private static final int DEFAULT_MAX_SIZE = 50; + private int length; + + //压入一个元素 + public void push(Object o){ + topIndex++; + elementData.add(o); + + + + } + + public Object pop(){ + if(elementData.size() ==0 ){ + throw new EmptyStackException(); + } + topIndex--; + return elementData.remove(elementData.size()-1); + + } + + public Object peek(){ + if(elementData.size()!=1){ + return elementData.get(elementData.size()-1); + } + return null; + } + public boolean isEmpty(){ + return topIndex>0; + } + public int size(){ + return topIndex; + } +} diff --git a/group27/1016908591/week04/src/com/coding/basic/stack/StackUtil.java b/group27/1016908591/week04/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..c205c101ce --- /dev/null +++ b/group27/1016908591/week04/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,102 @@ +package com.coding.basic.stack; + +import java.util.ArrayList; + + + +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 newStack = new Stack(); + while(!s.isEmpty()){ + newStack.push(s.peek()); + s.pop(); + } + s = newStack; + + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + Stack newStack = new Stack(); + while(s.isEmpty()){ + if(o == s.peek()){ + s.pop(); + break; + }else { + newStack.push(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) { + Stack newStack= new Stack(); + Object[] arr = (Object[]) new Object(); + for(int count = 0;count + + diff --git a/group27/383117348/src/com/coderising/array/ArrayUtil.java b/group27/383117348/src/com/coderising/array/ArrayUtil.java deleted file mode 100644 index 61fd42254a..0000000000 --- a/group27/383117348/src/com/coderising/array/ArrayUtil.java +++ /dev/null @@ -1,327 +0,0 @@ -package com.coderising.array; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; - -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[] copy = new int[origin.length]; - for (int x = 0; x < copy.length; x++) { - copy[x] = origin[x]; - } - for (int x = 0; x < origin.length; x++) { - origin[x] = copy[origin.length - 1 - x]; - System.out.println(copy[origin.length - 1 - x]); - } - - } - - /** - * 现在有如下的一个数组: 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) { - List list = new ArrayList(); - for (int x = 0; x < oldArray.length; x++) { - if (oldArray[x] != 0) - list.add(oldArray[x]); - } - - return parseToInt(list); - } - - /** - * 给定两个已经排序好的整形数组, 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[] newArray = new int[array1.length + array2.length]; - // 如果array1为空,array2不为空,则返回array2排序后的数组 - if (array1 == null || array1.length == 0 && array2 != null && array2.length > 0) { - return sort(array2); - } - // 如果array2为空,array1不为空,则返回array1排序后的数组 - if (array1 == null || array1.length == 0 && array2 != null && array2.length > 0) { - return sort(array1); - } - // 如果都不为空,则将两个数组放入一个数组中,先排序后去重 - if (array1 != null && array2 != null & array1.length > 0 && array2.length > 0) { - // 将array1的数组正序存放 - for (int x = 0; x < array1.length; x++) { - newArray[x] = array1[x]; - } - // 将array2的数组倒序存放 - for (int x = 0; x < array2.length; x++) { - newArray[newArray.length - 1 - x] = array2[x]; - } - newArray = sort(newArray); - newArray = getDistinct(newArray); - } - return newArray; - } - - // 数组去重 - private int[] getDistinct(int[] newArray) { - List list = new java.util.ArrayList(); - for (int i = 0; i < newArray.length; i++) { - if (!list.contains(newArray[i])) {// 如果list数组不包括num[i]中的值的话,就返回true。 - list.add(newArray[i]); // 在list数组中加入num[i]的值。已经过滤过。 - } - } - int[] result = parseToInt(list); - return result; - } - - // 冒泡排序 - private int[] sort(int[] array1) { - // TODO Auto-generated method stub - int[] arr = array1; - for (int i = 0; i < arr.length; i++) - for (int j = 0; j < arr.length - i - 1; j++) { - if (arr[j] > arr[j + 1]) { - int t = arr[j]; - arr[j] = arr[j + 1]; - arr[j + 1] = t; - } - } - 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) { - int[] newArray = new int[oldArray.length + size]; - for (int x = 0; x < oldArray.length; x++) { - newArray[x] = oldArray[x]; - } - 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) { - int n = 0; - for (int i = 1, j = 1, k; i < max; n++) { - k = i + j; - i = j; - j = k; - } - int[] newArray = new int[n]; - if (n > 1) { - newArray[0] = 1; - newArray[1] = 1; - } - for (int i = 2; i < n; i++) { - newArray[i] = newArray[i - 1] + newArray[i - 2]; - } - return newArray; - } - - /** - * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] - * - * @param max - * @return - */ - public int[] getPrimes(int max) { - int n = 0; - for (int i = 2; i < max; i++) { - if (primeNumber(i)) - n++; - } - - int[] newArray = new int[n]; - for (int i = 2, j = 0; i < max; i++) { - if (primeNumber(i)) { - newArray[j++] = i; - } - } - return newArray; - } - - private boolean primeNumber(int number) { - for (int i = 2; i < number; i++) { - if (number % i == 0) - return false; - } - return true; - } - - /** - * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 - * - * @param max - * @return - */ - public int[] getPerfectNumbers(int max) { - List list = new ArrayList(); - for (int i = 2; i < max; i++) { - int sum = 0; - // 查找因数 - for (int j = 1; j < i; j++) { - if (i % j == 0) { - sum += j; - } - } - if (sum == i) - list.add(i); - - } - - return parseToInt(list); - } - - /** - * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" - * - * @param array - * @param s - * @return - */ - public String join(int[] array, String seperator) { - String str = ""; - if (array.length > 0) { - for (int i = 0; i < array.length; i++) { - str += array[i] + seperator; - } - str = str.substring(0, str.length() - seperator.length()); - } - return str; - } - - /** - * 将集合转化为int数组 - * - * @param list - * @return - */ - private int[] parseToInt(List list) { - int[] arr = new int[list.size()]; - for (int x = 0; x < list.size(); x++) { - arr[x] = list.get(x); - } - return arr; - } - - /*********************************** 单元测试 ***********************************/ - @Test - public void testReserve() { - int[] arr = { 7, 9, 30, 3 }; - reverseArray(arr); - for (int x = 0; x < 4; x++) { - System.out.println(arr[x]); - } - } - - @Test - public void testZero() { - int oldArr[] = { 1, 3, 4, 5, 0, 0, 6, 6, 0, 5, 4, 7, 6, 7, 0, 5 }; - int[] arr = removeZero(oldArr); - for (int x = 0; x < arr.length; x++) { - System.out.print(arr[x] + " "); - } - } - - @Test - public void testMerge() { - // a1=[3, 5, 7,8] a2 = [4, 5, 6,7] - int[] a1 = { 3, 5, 7, 8 }; - int[] a2 = { 4, 5, 6, 7 }; - // a3 = [3,4,5,6,7,8] - int[] a3 = merge(a1, a2); - for (int x = 0; x < a3.length; x++) { - System.out.print(a3[x] + " "); - } - } - - @Test - public void testGrow() { - int[] oldArray = { 2, 3, 6 }; - int[] newArray = grow(oldArray, 3); - for (int x = 0; x < newArray.length; x++) { - System.out.println(newArray[x]); - } - } - - @Test - public void testFibo() { - // 1,1,2,3,5,8,13 - int[] arr = fibonacci(20); - for (int x = 0; x < arr.length; x++) { - System.out.print(arr[x] + " "); - } - } - - @Test - public void testPrime() { - int arr[] = getPrimes(23); - for (int x = 0; x < arr.length; x++) { - System.out.print(arr[x]); - System.out.print(" "); - } - } - - @Test - public void testPerfectNum() { - int[] arr = getPerfectNumbers(25); - for (int x = 0; x < arr.length; x++) { - System.out.println(arr[x]); - } - - } - - @Test - public void testJoin() { - int[] arr = new int[10]; - for (int x = 0; x < arr.length; x++) { - arr[x] = x; - } - String s = join(arr, "--"); - System.out.println(s); - } - - @Test - public void testParseToInt() { - List list = new ArrayList(); - for (int x = 0; x < 10; x++) { - list.add(x); - } - int[] arr = parseToInt(list); - for (int x = 0; x < arr.length; x++) { - System.out.println(arr[x]); - } - } - -} diff --git a/group27/383117348/src/com/coderising/jvm/clz/AccessFlag.java b/group27/383117348/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..cdb8f8859a --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/clz/ClassFile.java b/group27/383117348/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..1b5a8b95a6 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/clz/ClassIndex.java b/group27/383117348/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..df22981441 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/ClassInfo.java b/group27/383117348/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..e12b3e164e --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/383117348/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..a3a0b53b76 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,30 @@ +package com.coderising.jvm.constant; + +public abstract class ConstantInfo { + public static final int UTF8_INFO = 1; + public static final int INTEGER_INFO = 3; + 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/383117348/src/com/coderising/jvm/constant/ConstantPool.java b/group27/383117348/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..0e940b78d0 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/383117348/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ff9d5fb77 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/FloatInfo.java b/group27/383117348/src/com/coderising/jvm/constant/FloatInfo.java new file mode 100644 index 0000000000..dc3765720c --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/constant/FloatInfo.java @@ -0,0 +1,26 @@ +package com.coderising.jvm.constant; + + +public class FloatInfo extends ConstantInfo{ + private int type = ConstantInfo.FLOAT_INFO; + + private float value; + + public FloatInfo(ConstantPool pool){ + super(pool); + } + + @Override + public int getType() { + // TODO Auto-generated method stub + return type; + } + + public float getValue() { + return value; + } + + public void setValue(float value) { + this.value = value; + } +} diff --git a/group27/383117348/src/com/coderising/jvm/constant/IntegerInfo.java b/group27/383117348/src/com/coderising/jvm/constant/IntegerInfo.java new file mode 100644 index 0000000000..06e66c6e08 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/constant/IntegerInfo.java @@ -0,0 +1,28 @@ +package com.coderising.jvm.constant; + +public class IntegerInfo extends ConstantInfo { + + private int type = ConstantInfo.INTEGER_INFO; + + private int value; + + public IntegerInfo(ConstantPool pool) { + super(pool); + } + + @Override + public int getType() { + + return type; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + +} diff --git a/group27/383117348/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/383117348/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..0feffa65b5 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/383117348/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..dcac7f97c4 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/383117348/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..fa90d110fe --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/StringInfo.java b/group27/383117348/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..d01065fd53 --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/constant/UTF8Info.java b/group27/383117348/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..b7407d146f --- /dev/null +++ b/group27/383117348/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/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..2688ae5810 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,51 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +public class ByteCodeIterator { + + private byte[] code = null; + private int pos = 0; + + public ByteCodeIterator(byte[] code){ + this.code = code; + } + + public int nextU1Int(){ + return Util.byteToInt(getByteBySize(1)); + } + + public int nextU2Int(){ + + return Util.byteToInt(getByteBySize(2)); + } + + public String nextU4HexString(){ + return Util.byteToHexString(getByteBySize(4)); + } + + public float nextU4Float(){ + return Util.byteToFloat(getByteBySize(4)); + } + + public int nextU4Integer(){ + return Util.byteToInt(getByteBySize(4)); + } + + public byte[] getByteByLength(int length){ + if(pos+length>code.length){ + throw new RuntimeException("长度超出字节数组最大长度"); + }else{ + byte[] by = getByteBySize(length); + return by; + } + } + + private byte[] getByteBySize(int size){ + byte[] by = new byte[size]; + for(int i=0;i clzPaths = new ArrayList(); - + public byte[] readBinaryCode(String className) { - className = className.replace(".", "\\"); - File file = null; - for(String classPath : clzPaths){ - file = new File(classPath + "\\" + className + ".class"); - if(file.exists()){ - break; - } + + 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; } - if(!file.exists()){ - try { - throw new ClassNotFoundException(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); + + 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 0) { - if (!clzPaths.contains(path)) { - clzPaths.add(path); - } - } - } - public String getClassPath() { - String paths = ""; - for (String s : clzPaths) { - paths += s + ";"; - } - paths = paths.substring(0, paths.length() - 1); - return paths; - } + -} +} \ No newline at end of file diff --git a/group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader_backup.java b/group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader_backup.java new file mode 100644 index 0000000000..014def27d5 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/loader/ClassFileLoader_backup.java @@ -0,0 +1,77 @@ +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; + +public class ClassFileLoader_backup { + + private List clzPaths = new ArrayList(); + + public byte[] readBinaryCode(String className) { + className = className.replace(".", "\\"); + File file = null; + for(String classPath : clzPaths){ + file = new File(classPath + "\\" + className + ".class"); + if(file.exists()){ + break; + } + } + if(!file.exists()){ + try { + throw new ClassNotFoundException(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length()); + BufferedInputStream in = null; + try { + in = new BufferedInputStream(new FileInputStream(file)); + int buf_size = 1024; + byte[] buffer = new byte[buf_size]; + int len = 0; + while (-1 != (len = in.read(buffer, 0, buf_size))) { + bos.write(buffer, 0, len); + } + return bos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + bos.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return null; + } + + public void addClassPath(String path) { + if (path != null && path.length() > 0) { + if (!clzPaths.contains(path)) { + clzPaths.add(path); + } + } + } + + public String getClassPath() { + String paths = ""; + for (String s : clzPaths) { + paths += s + ";"; + } + paths = paths.substring(0, paths.length() - 1); + return paths; + } + +} diff --git a/group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java b/group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100644 index 0000000000..209ee78d36 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,110 @@ +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.FloatInfo; +import com.coderising.jvm.constant.IntegerInfo; +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) { + ByteCodeIterator by = new ByteCodeIterator(codes); + ClassFile file = new ClassFile(); + String magicNum = by.nextU4HexString(); + if(!magicNum.equals("cafebabe")){ + throw new RuntimeException("文件类型错误"); + } + + int minVersion = by.nextU2Int(); + int majorVersion = by.nextU2Int(); + + ConstantPool constant = parseConstantPool(by); + AccessFlag flag = parseAccessFlag(by); + ClassIndex index = parseClassIndex(by); + + file.setMinorVersion(minVersion); + file.setMajorVersion(majorVersion); + file.setAccessFlag(flag); + file.setClassIndex(index); + file.setConstPool(constant); + return file; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag flag = new AccessFlag(iter.nextU2Int()); + return flag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex index = new ClassIndex(); + index.setThisClassIndex(iter.nextU2Int()); + index.setSuperClassIndex(iter.nextU2Int()); + return index; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constantCount = iter.nextU2Int(); + ConstantPool pool = new ConstantPool(); + pool.addConstantInfo(new NullConstantInfo()); + for(int i=1;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/383117348/src/com/coderising/jvm/test/EmployeeV1.java b/group27/383117348/src/com/coderising/jvm/test/EmployeeV1.java index d36b122f60..9a36573dd3 100644 --- a/group27/383117348/src/com/coderising/jvm/test/EmployeeV1.java +++ b/group27/383117348/src/com/coderising/jvm/test/EmployeeV1.java @@ -1,30 +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(); - - } + 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/383117348/src/com/coderising/jvm/util/Util.java b/group27/383117348/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0038d09530 --- /dev/null +++ b/group27/383117348/src/com/coderising/jvm/util/Util.java @@ -0,0 +1,29 @@ +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 0) - System.arraycopy(elementData, index + 1, elementData, index, afterRemove); - elementData = Arrays.copyOf(elementData, --size); - return obj; - } - - /** - * 获取数组大小 - */ - public int size() { - return size; - } - - /** - * 迭代器 - * - * @return - */ - public Iterator iterator() { - return new Iter(); - } - - /** - * 迭代器内部类 - * - * @author Adminstater - * - */ - private class Iter implements Iterator { - private int nextIndex = 0; - - @Override - public boolean hasNext() { - // TODO Auto-generated method stub - return nextIndex != size; - } - - @Override - public Object next() { - // TODO Auto-generated method stub - int i = nextIndex++; - if (i > size - 1) - throw new IndexOutOfBoundsException(); - - return elementData[i]; - } - - } - - /** - * 检查数组长度是否越界,越界就自动增长100 - */ - private void growUp(int size) { - if (size > elementData.length - 1) { - Object[] elementGrow = new Object[elementData.length + GROW_UP_SIZE]; - System.arraycopy(elementData, 0, elementGrow, 0, elementData.length); - elementData = elementGrow; - // System.out.println(elementData.length); - } - } - - /** - * 检查下标是否越界,越界抛出异常 - */ - private void checkIndex(int index) { - if (index < 0 || index > size) { - throw new IndexOutOfBoundsException("下标越界"); - } - } - - /*------------------------------------------------------单元测试----------------------------------------------------*/ - /** - * 测试自增长数组长度变化及增加功能 - */ - @Test - public void TestAddFunction() { - ArrayList list = new ArrayList(); - for (int x = 0; x < 300; x++) { - list.add(x); - } - } - - /** - * 测试add(int index,Object obj)方法 - */ - @Test - public void TestAddIndexFunction() { - ArrayList list = new ArrayList(); - // System.out.println(list.size()); - list.add(0, 20); - list.add(1, 30); - System.out.println(list.get(1)); - - } - - /** - * 测试get方法 - */ - @Test - public void TestGetFunction() { - ArrayList list = new ArrayList(); - for (int x = 0; x < 300; x++) { - list.add(x); - } - for (int x = 0; x < list.size; x++) { - System.out.println(list.get(x)); - } - } - - /** - * 测试size方法 - */ - @Test - public void TestSizeFunction() { - ArrayList list = new ArrayList(); - for (int x = 0; x < 259; x++) { - list.add(x); - } - /* - * for(int x=0;x list = null; - } - -} diff --git a/group27/383117348/src/com/coding/basic/Stack.java b/group27/383117348/src/com/coding/basic/Stack.java deleted file mode 100644 index 1b12b63b0f..0000000000 --- a/group27/383117348/src/com/coding/basic/Stack.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.coding.basic; - -import org.junit.Test; - -public class Stack { - - private ArrayList elementData = new ArrayList(); - - /** - * 压栈方法 - * - * @param o - */ - public void push(Object o) { - if (o != null) - elementData.add(o); - } - - /** - * 弹栈方法 - * - * @return - */ - public Object pop() { - Object result = elementData.remove(elementData.size() - 1); - return result; - } - - /** - * 查看栈顶对象 - * - * @return - */ - public Object peek() { - Object result = elementData.get(elementData.size() - 1); - return result; - } - - /** - * 判断是否为空 - * - * @return - */ - public boolean isEmpty() { - return elementData.size() == 0; - } - - /** - * 获取栈的长度 - * - * @return - */ - public int size() { - return elementData.size(); - } - - /*------------------------------------------------------单元测试----------------------------------------------------*/ - /** - * push(Object obj)方法测试 - */ - @Test - public void TestPushFunction() { - Stack stack = new Stack(); - for (int x = 0; x < 100; x++) { - stack.push(x); - } - } - - /** - * peek()方法测试 - */ - @Test - public void TestPeekFunction() { - Stack stack = new Stack(); - for (int x = 0; x < 100; x++) { - stack.push(x); - } - for (int x = 0; x < stack.size(); x++) { - System.out.println(x + ":" + stack.peek()); - } - } - - /** - * pop()方法测试 - */ - @Test - public void TestPopFunction() { - Stack stack = new Stack(); - for (int x = 0; x < 100; x++) { - stack.push(x); - } - System.out.println("before:" + stack.size()); - for (int x = 0; x < stack.size();) { - System.out.println(stack.pop()); - } - System.out.println("after:" + stack.size()); - } - -} diff --git a/group27/383117348/src/com/coding/basic/array/ArrayList.java b/group27/383117348/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..c9bb3e8f62 --- /dev/null +++ b/group27/383117348/src/com/coding/basic/array/ArrayList.java @@ -0,0 +1,216 @@ +package com.coding.basic.array; + +import java.util.Arrays; + +import org.junit.Test; + +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]; + + /** + * 自动增长值 + */ + private static final int GROW_UP_SIZE = 100; + + /** + * 在数组最末尾添加对象 + */ + public void add(Object o) { + growUp(size); + elementData[size] = o; + size++; + } + + /** + * 向指定下标处添加对象 + */ + public void add(int index, Object o) { + checkIndex(index); + growUp(size + 1); + System.arraycopy(elementData, index, elementData, index + 1, size - index); + elementData[index] = o; + size++; + + } + + /** + * 根据index获取对象 + */ + public Object get(int index) { + checkIndex(index); + return elementData[index]; + } + + /** + * 移除指定下标对象 + */ + public Object remove(int index) { + checkIndex(index); + Object obj = elementData[index]; + int afterRemove = size - index - 1; + // System.out.println("@@@@"+afterRemove+"---"+index); + if (afterRemove > 0) + System.arraycopy(elementData, index + 1, elementData, index, afterRemove); + elementData = Arrays.copyOf(elementData, --size); + return obj; + } + + /** + * 获取数组大小 + */ + public int size() { + return size; + } + + /** + * 迭代器 + * + * @return + */ + public Iterator iterator() { + return new Iter(); + } + + /** + * 迭代器内部类 + * + * @author Adminstater + * + */ + private class Iter implements Iterator { + private int nextIndex = 0; + + @Override + public boolean hasNext() { + // TODO Auto-generated method stub + return nextIndex != size; + } + + @Override + public Object next() { + // TODO Auto-generated method stub + int i = nextIndex++; + if (i > size - 1) + throw new IndexOutOfBoundsException(); + + return elementData[i]; + } + + } + + /** + * 检查数组长度是否越界,越界就自动增长100 + */ + private void growUp(int size) { + if (size > elementData.length - 1) { + Object[] elementGrow = new Object[elementData.length + GROW_UP_SIZE]; + System.arraycopy(elementData, 0, elementGrow, 0, elementData.length); + elementData = elementGrow; + // System.out.println(elementData.length); + } + } + + /** + * 检查下标是否越界,越界抛出异常 + */ + private void checkIndex(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("下标越界"); + } + } + + /*------------------------------------------------------单元测试----------------------------------------------------*/ + /** + * 测试自增长数组长度变化及增加功能 + */ + @Test + public void TestAddFunction() { + ArrayList list = new ArrayList(); + for (int x = 0; x < 300; x++) { + list.add(x); + } + } + + /** + * 测试add(int index,Object obj)方法 + */ + @Test + public void TestAddIndexFunction() { + ArrayList list = new ArrayList(); + // System.out.println(list.size()); + list.add(0, 20); + list.add(1, 30); + System.out.println(list.get(1)); + + } + + /** + * 测试get方法 + */ + @Test + public void TestGetFunction() { + ArrayList list = new ArrayList(); + for (int x = 0; x < 300; x++) { + list.add(x); + } + for (int x = 0; x < list.size; x++) { + System.out.println(list.get(x)); + } + } + + /** + * 测试size方法 + */ + @Test + public void TestSizeFunction() { + ArrayList list = new ArrayList(); + for (int x = 0; x < 259; x++) { + list.add(x); + } + /* + * for(int x=0;x list = null; + } + +} diff --git a/group27/383117348/src/com/coding/basic/array/ArrayUtil.java b/group27/383117348/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..b8ba0beb4b --- /dev/null +++ b/group27/383117348/src/com/coding/basic/array/ArrayUtil.java @@ -0,0 +1,327 @@ +package com.coding.basic.array; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +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[] copy = new int[origin.length]; + for (int x = 0; x < copy.length; x++) { + copy[x] = origin[x]; + } + for (int x = 0; x < origin.length; x++) { + origin[x] = copy[origin.length - 1 - x]; + System.out.println(copy[origin.length - 1 - x]); + } + + } + + /** + * 现在有如下的一个数组: 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) { + List list = new ArrayList(); + for (int x = 0; x < oldArray.length; x++) { + if (oldArray[x] != 0) + list.add(oldArray[x]); + } + + return parseToInt(list); + } + + /** + * 给定两个已经排序好的整形数组, 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[] newArray = new int[array1.length + array2.length]; + // 如果array1为空,array2不为空,则返回array2排序后的数组 + if (array1 == null || array1.length == 0 && array2 != null && array2.length > 0) { + return sort(array2); + } + // 如果array2为空,array1不为空,则返回array1排序后的数组 + if (array1 == null || array1.length == 0 && array2 != null && array2.length > 0) { + return sort(array1); + } + // 如果都不为空,则将两个数组放入一个数组中,先排序后去重 + if (array1 != null && array2 != null & array1.length > 0 && array2.length > 0) { + // 将array1的数组正序存放 + for (int x = 0; x < array1.length; x++) { + newArray[x] = array1[x]; + } + // 将array2的数组倒序存放 + for (int x = 0; x < array2.length; x++) { + newArray[newArray.length - 1 - x] = array2[x]; + } + newArray = sort(newArray); + newArray = getDistinct(newArray); + } + return newArray; + } + + // 数组去重 + private int[] getDistinct(int[] newArray) { + List list = new java.util.ArrayList(); + for (int i = 0; i < newArray.length; i++) { + if (!list.contains(newArray[i])) {// 如果list数组不包括num[i]中的值的话,就返回true。 + list.add(newArray[i]); // 在list数组中加入num[i]的值。已经过滤过。 + } + } + int[] result = parseToInt(list); + return result; + } + + // 冒泡排序 + private int[] sort(int[] array1) { + // TODO Auto-generated method stub + int[] arr = array1; + for (int i = 0; i < arr.length; i++) + for (int j = 0; j < arr.length - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + int t = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = t; + } + } + 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) { + int[] newArray = new int[oldArray.length + size]; + for (int x = 0; x < oldArray.length; x++) { + newArray[x] = oldArray[x]; + } + 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) { + int n = 0; + for (int i = 1, j = 1, k; i < max; n++) { + k = i + j; + i = j; + j = k; + } + int[] newArray = new int[n]; + if (n > 1) { + newArray[0] = 1; + newArray[1] = 1; + } + for (int i = 2; i < n; i++) { + newArray[i] = newArray[i - 1] + newArray[i - 2]; + } + return newArray; + } + + /** + * 返回小于给定最大值max的所有素数数组 例如max = 23, 返回的数组为[2,3,5,7,11,13,17,19] + * + * @param max + * @return + */ + public int[] getPrimes(int max) { + int n = 0; + for (int i = 2; i < max; i++) { + if (primeNumber(i)) + n++; + } + + int[] newArray = new int[n]; + for (int i = 2, j = 0; i < max; i++) { + if (primeNumber(i)) { + newArray[j++] = i; + } + } + return newArray; + } + + private boolean primeNumber(int number) { + for (int i = 2; i < number; i++) { + if (number % i == 0) + return false; + } + return true; + } + + /** + * 所谓“完数”, 是指这个数恰好等于它的因子之和,例如6=1+2+3 给定一个最大值max, 返回一个数组, 数组中是小于max 的所有完数 + * + * @param max + * @return + */ + public int[] getPerfectNumbers(int max) { + List list = new ArrayList(); + for (int i = 2; i < max; i++) { + int sum = 0; + // 查找因数 + for (int j = 1; j < i; j++) { + if (i % j == 0) { + sum += j; + } + } + if (sum == i) + list.add(i); + + } + + return parseToInt(list); + } + + /** + * 用seperator 把数组 array给连接起来 例如array= [3,8,9], seperator = "-" 则返回值为"3-8-9" + * + * @param array + * @param s + * @return + */ + public String join(int[] array, String seperator) { + String str = ""; + if (array.length > 0) { + for (int i = 0; i < array.length; i++) { + str += array[i] + seperator; + } + str = str.substring(0, str.length() - seperator.length()); + } + return str; + } + + /** + * 将集合转化为int数组 + * + * @param list + * @return + */ + private int[] parseToInt(List list) { + int[] arr = new int[list.size()]; + for (int x = 0; x < list.size(); x++) { + arr[x] = list.get(x); + } + return arr; + } + + /*********************************** 单元测试 ***********************************/ + @Test + public void testReserve() { + int[] arr = { 7, 9, 30, 3 }; + reverseArray(arr); + for (int x = 0; x < 4; x++) { + System.out.println(arr[x]); + } + } + + @Test + public void testZero() { + int oldArr[] = { 1, 3, 4, 5, 0, 0, 6, 6, 0, 5, 4, 7, 6, 7, 0, 5 }; + int[] arr = removeZero(oldArr); + for (int x = 0; x < arr.length; x++) { + System.out.print(arr[x] + " "); + } + } + + @Test + public void testMerge() { + // a1=[3, 5, 7,8] a2 = [4, 5, 6,7] + int[] a1 = { 3, 5, 7, 8 }; + int[] a2 = { 4, 5, 6, 7 }; + // a3 = [3,4,5,6,7,8] + int[] a3 = merge(a1, a2); + for (int x = 0; x < a3.length; x++) { + System.out.print(a3[x] + " "); + } + } + + @Test + public void testGrow() { + int[] oldArray = { 2, 3, 6 }; + int[] newArray = grow(oldArray, 3); + for (int x = 0; x < newArray.length; x++) { + System.out.println(newArray[x]); + } + } + + @Test + public void testFibo() { + // 1,1,2,3,5,8,13 + int[] arr = fibonacci(20); + for (int x = 0; x < arr.length; x++) { + System.out.print(arr[x] + " "); + } + } + + @Test + public void testPrime() { + int arr[] = getPrimes(23); + for (int x = 0; x < arr.length; x++) { + System.out.print(arr[x]); + System.out.print(" "); + } + } + + @Test + public void testPerfectNum() { + int[] arr = getPerfectNumbers(25); + for (int x = 0; x < arr.length; x++) { + System.out.println(arr[x]); + } + + } + + @Test + public void testJoin() { + int[] arr = new int[10]; + for (int x = 0; x < arr.length; x++) { + arr[x] = x; + } + String s = join(arr, "--"); + System.out.println(s); + } + + @Test + public void testParseToInt() { + List list = new ArrayList(); + for (int x = 0; x < 10; x++) { + list.add(x); + } + int[] arr = parseToInt(list); + for (int x = 0; x < arr.length; x++) { + System.out.println(arr[x]); + } + } + +} diff --git a/group27/383117348/src/com/coding/basic/stack/Stack.java b/group27/383117348/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..47e9918d1a --- /dev/null +++ b/group27/383117348/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,101 @@ +package com.coding.basic.stack; + +import org.junit.Test; + +import com.coding.basic.array.ArrayList; + +public class Stack { + + private ArrayList elementData = new ArrayList(); + + /** + * 压栈方法 + * + * @param o + */ + public void push(Object o) { + if (o != null) + elementData.add(o); + } + + /** + * 弹栈方法 + * + * @return + */ + public Object pop() { + Object result = elementData.remove(elementData.size() - 1); + return result; + } + + /** + * 查看栈顶对象 + * + * @return + */ + public Object peek() { + Object result = elementData.get(elementData.size() - 1); + return result; + } + + /** + * 判断是否为空 + * + * @return + */ + public boolean isEmpty() { + return elementData.size() == 0; + } + + /** + * 获取栈的长度 + * + * @return + */ + public int size() { + return elementData.size(); + } + + /*------------------------------------------------------单元测试----------------------------------------------------*/ + /** + * push(Object obj)方法测试 + */ + @Test + public void TestPushFunction() { + Stack stack = new Stack(); + for (int x = 0; x < 100; x++) { + stack.push(x); + } + } + + /** + * peek()方法测试 + */ + @Test + public void TestPeekFunction() { + Stack stack = new Stack(); + for (int x = 0; x < 100; x++) { + stack.push(x); + } + for (int x = 0; x < stack.size(); x++) { + System.out.println(x + ":" + stack.peek()); + } + } + + /** + * pop()方法测试 + */ + @Test + public void TestPopFunction() { + Stack stack = new Stack(); + for (int x = 0; x < 100; x++) { + stack.push(x); + } + System.out.println("before:" + stack.size()); + for (int x = 0; x < stack.size();) { + System.out.println(stack.pop()); + } + System.out.println("after:" + stack.size()); + } + +} diff --git a/group27/383117348/src/com/coding/basic/stack/StackUtil.java b/group27/383117348/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..dfb1c95e7d --- /dev/null +++ b/group27/383117348/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,107 @@ +package com.coding.basic.stack; + +import org.junit.Test; + +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()) { + Object [] obj = new Object[s.size()]; + for(int i =0 ;i < obj.length; i++){ + obj[i] = s.pop(); + } + for(int i =0 ;i < obj.length; i++){ + s.push(obj[i]); + } + }else{ + + } + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + if(s!=null && s.size()>0){ + Stack newStack = new Stack(); + while(s.size()>0){ + newStack.push(s.pop()); + if(newStack.peek().equals(o)){ + newStack.pop(); + } + } + while(newStack.size()>0){ + s.push(newStack.pop()); + } + }else{ + + } + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, + * 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + if(s!=null && s.size()>0 && len>0 && len<=s.size()){ + Object[] objs = new Object[len]; + Stack newStack = new Stack(); + for(int i = 0;i0){ + s.push(newStack.pop()); + } + return objs; + } + return null; + } + + /** + * 字符串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 special = new Stack(); + for(int i =0; i 0){ + str+=s.pop()+";"; + } + return str; + } + +} diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java b/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..4a0980079b --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/Stack.java @@ -0,0 +1,68 @@ + +package com.coding.basic.stack; + +import com.coding.basic.List; +import com.coding.basic.array.ArrayList; + +/** + * author zhougd 20170306 + * + */ +public class Stack { + private List elementData = new ArrayList(); + + + public Stack() { + } + + /** + * 入栈 + * @param o + */ + public void push(Object o){ + elementData.add(o); + } + + /** + * 出栈 + * @return + */ + public Object pop(){ + if(this.isEmpty()){ + throw new IndexOutOfBoundsException("stack is empty!"); + } + Object element = elementData.get(size()-1); + elementData.remove(size()-1); + return element; + } + + /** + * 查看栈顶元素 + * @return Object + */ + public Object peek(){ + if(this.isEmpty()){ + throw new IndexOutOfBoundsException("stack is empty!"); + } + Object element = elementData.get(size()-1); + return element; + } + + /** + * 查看栈是否为空 + * @return boolean + */ + public boolean isEmpty(){ + + return elementData == null || elementData.size()<=0; + + } + + /** + * 获取栈大小 + * @return + */ + public int size(){ + return elementData.size(); + } +} \ No newline at end of file diff --git a/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java new file mode 100755 index 0000000000..e53e38ca4b --- /dev/null +++ b/group27/513274874/data-structure/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,128 @@ +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 temp = new Stack(); + //先清空s + while (!s.isEmpty()) { + temp.push(s.pop()); + } + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s, Object o) { + Stack temp = new Stack(); + while (!s.isEmpty()) { + Object a = s.pop(); + if (a.equals(o)) { + break; + } + temp.push(a); + } + + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param len + * @return + */ + public static Object[] getTop(Stack s, int len) { + + Object[] os = null; + if (len > 0) { + os = new Object[len]; + } else { + return null; + } + + Stack temp = new Stack(); + for (int i = 0; i < len; i++) { + if (!s.isEmpty()) { + Object o = s.pop(); + os[i] = o; + temp.push(o); + } else { + break; + } + } + + while (!temp.isEmpty()) { + s.push(temp.pop()); + } + return os; + } + + /** + * 字符串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.trim().equals("")) return false; + Stack stack = new Stack(); + byte[] bytes = s.getBytes(); + byte temp; + for (byte b : bytes) { + switch (b) { + case '(': + case '[': + case '{': + stack.push(b); + break; + + case ')': + temp = (byte) stack.peek(); + if (temp != '(') { + return false; + } else { + stack.pop(); + } + break; + case ']': + temp = (byte) stack.peek(); + if (temp != ']') { + return false; + } else { + stack.pop(); + } + break; + case '}': + temp = (byte) stack.peek(); + if (temp != ']') { + return false; + } else { + stack.pop(); + } + break; + + } + + if(stack.isEmpty() ) return true; + } + + return false; + } + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100755 index 0000000000..faae056835 --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassFile.java new file mode 100755 index 0000000000..650ca8375d --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100755 index 0000000000..e424f284b3 --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100755 index 0000000000..aea9048ea4 --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100755 index 0000000000..5d66317801 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantInfo.java @@ -0,0 +1,34 @@ +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(); + + @Override + public String toString(){ + return super.toString(); + } + + public ConstantPool getConstantPool() { + return constantPool; + } + public ConstantInfo getConstantInfo(int index){ + return this.constantPool.getConstantInfo(index); + } + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100755 index 0000000000..f92c8028b9 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/ConstantPool.java @@ -0,0 +1,29 @@ +package com.coderising.jvm.constant; + +import java.util.LinkedList; +import java.util.List; + +public class ConstantPool { + + private List constantInfos = new LinkedList(); + + + 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/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100755 index 0000000000..65475e194c --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100755 index 0000000000..65c586916c --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/MethodRefInfo.java @@ -0,0 +1,56 @@ +package com.coderising.jvm.constant; + +public class MethodRefInfo extends ConstantInfo { + + private int type = ConstantInfo.METHOD_INFO; + + private int classIndex; + private int nameAndTypeIndex; + + public MethodRefInfo(ConstantPool pool) { + super(pool); + } + + public int getType() { + return type; + } + + public int getClassInfoIndex() { + return classIndex; + } + public void setClassIndex(int classIndex) { + this.classIndex = classIndex; + } + 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(); + } + + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100755 index 0000000000..b9d9185ef8 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java @@ -0,0 +1,49 @@ +package com.coderising.jvm.constant; + +public class NameAndTypeInfo extends ConstantInfo{ + public int type = ConstantInfo.NAME_AND_TYPE_INFO; + + private int name_index; + private int descriptor_index; + + public NameAndTypeInfo(ConstantPool pool) { + super(pool); + } + + public int getNameIndex() { + return name_index; + } + + public void setNameIndex(int name_index) { + this.name_index = name_index; + } + + public int getDescriptorIndex() { + return descriptor_index; + } + + public void setDescriptorIndex(int descriptor_index) { + this.descriptor_index = descriptor_index; + } + + public int getType() { + return type; + } + + + public String getName(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(name_index); + return utf8Info1.getValue(); + } + + public String getTypeInfo(){ + ConstantPool pool = this.getConstantPool(); + UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(descriptor_index); + return utf8Info2.getValue(); + } + + public String toString(){ + return "(" + getName() + "," + getTypeInfo()+")"; + } +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100755 index 0000000000..936736016f --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/StringInfo.java new file mode 100755 index 0000000000..f1f8eb4ed4 --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100755 index 0000000000..5cac9f04f7 --- /dev/null +++ b/group27/513274874/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/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100755 index 0000000000..e4c5c83681 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java @@ -0,0 +1,34 @@ +package com.coderising.jvm.loader; + +import com.coderising.jvm.util.Util; + +import java.util.Arrays; + +public class ByteCodeIterator { + private byte[] code ; + private int pos = 0; + + public ByteCodeIterator(byte[] code) { + this.code = code; + } + + public int nextU1Int(){ + return Util.byteToInt(new byte[]{code[pos++]}); + } + public int nextU2Int(){ + + return Util.byteToInt(new byte[]{code[pos++],code[pos++]}); + } + public String nextU4HexString(){ + return Util.byteToHexString(new byte[]{code[pos++],code[pos++],code[pos++],code[pos++]}); + } + + public byte[] getBytes(int length){ + if(pos+length >= code.length){ + throw new IndexOutOfBoundsException("not enough bytes!"); + } + byte[] bytes = Arrays.copyOfRange(code,pos,pos+length); + pos += length; + return bytes; + } +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java index 4b5d12b49f..4d146e14c2 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -1,5 +1,7 @@ package com.coderising.jvm.loader; +import com.coderising.jvm.clz.ClassFile; + import java.io.*; import java.util.ArrayList; import java.util.List; @@ -54,4 +56,12 @@ public String getClassPath() { return clazzPaths; } + public ClassFile loadClass(String className) { + byte[] codes = this.readBinaryCode(className); + ClassFileParser parser = new ClassFileParser(); + return parser.parse(codes); + + } + + } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java new file mode 100755 index 0000000000..0c35bca807 --- /dev/null +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java @@ -0,0 +1,109 @@ +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.*; + +import java.io.UnsupportedEncodingException; + +public class ClassFileParser { + + public ClassFile parse(byte[] codes) { + + ClassFile clzFile = new ClassFile(); + ByteCodeIterator iterator = new ByteCodeIterator(codes); + + String magicNumber = iterator.nextU4HexString(); + if (!"cafebabe".equals(magicNumber)) { + return null; + } + + clzFile.setMinorVersion(iterator.nextU2Int()); + clzFile.setMajorVersion(iterator.nextU2Int()); + + clzFile.setConstPool(parseConstantPool(iterator)); + clzFile.setAccessFlag(parseAccessFlag(iterator)); + clzFile.setClassIndex(parseClassIndex(iterator)); + + return clzFile; + } + + private AccessFlag parseAccessFlag(ByteCodeIterator iter) { + AccessFlag accessFlag = new AccessFlag(iter.nextU2Int()); + return accessFlag; + } + + private ClassIndex parseClassIndex(ByteCodeIterator iter) { + ClassIndex classIndex = new ClassIndex(); + classIndex.setThisClassIndex(iter.nextU2Int()); + classIndex.setSuperClassIndex(iter.nextU2Int()); + + return classIndex; + + } + + private ConstantPool parseConstantPool(ByteCodeIterator iter) { + int constantCount = iter.nextU2Int(); + ConstantPool pool = new ConstantPool(); + //因为常量池索引是#1开始,所以此处常量池的第0位设置成空 + pool.addConstantInfo(new NullConstantInfo()); + for (int i = 1; i < constantCount; i++) { + int tag = iter.nextU1Int(); + if (tag == 7) { + //CONSTANT_Class_info + ClassInfo classInfo = new ClassInfo(pool); + classInfo.setUtf8Index(iter.nextU2Int()); + pool.addConstantInfo(classInfo); + } else if (tag == 1) { + //CONSTANT_Utf8_info + UTF8Info utf8Info = new UTF8Info(pool); + int len = iter.nextU2Int(); + utf8Info.setLength(len); + byte[] utf8Bytes = iter.getBytes(len); + String utf8Value = null; + try { + utf8Value = new String(utf8Bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + utf8Info.setValue(utf8Value); + + pool.addConstantInfo(utf8Info); + } else if (tag == 8) { + //CONSTANT_String_info + StringInfo stringInfo = new StringInfo(pool); + stringInfo.setIndex(iter.nextU2Int()); + + pool.addConstantInfo(stringInfo); + } else if (tag == 9) { + //CONSTANT_Fieldref_info + FieldRefInfo fieldRefInfo = new FieldRefInfo(pool); + fieldRefInfo.setClassInfoIndex(iter.nextU2Int()); + fieldRefInfo.setNameAndTypeIndex(iter.nextU2Int()); + + pool.addConstantInfo(fieldRefInfo); + } else if (tag == 10) { + //CONSTANT_Methodref_info + MethodRefInfo methodRefInfo = new MethodRefInfo(pool); + methodRefInfo.setClassIndex(iter.nextU2Int()); + methodRefInfo.setNameAndTypeIndex(iter.nextU2Int()); + + pool.addConstantInfo(methodRefInfo); + } else if (tag == 12) { + //CONSTANT_NameAndType_info + NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool); + nameAndTypeInfo.setNameIndex(iter.nextU2Int()); + nameAndTypeInfo.setDescriptorIndex(iter.nextU2Int()); + + pool.addConstantInfo(nameAndTypeInfo); + } else { + throw new RuntimeException("constant pool hasn't this tag : " + tag); + } + + } + return pool; + } + + +} diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java index e5d2bd89c5..b3b281bc8a 100755 --- a/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ b/group27/513274874/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java @@ -1,5 +1,8 @@ package com.coderising.jvm.test; +import com.coderising.jvm.clz.ClassFile; +import com.coderising.jvm.clz.ClassIndex; +import com.coderising.jvm.constant.*; import com.coderising.jvm.loader.ClassFileLoader; import org.junit.After; import org.junit.Assert; @@ -13,9 +16,20 @@ public class ClassFileloaderTest { + private static final String FULL_QUALIFIED_CLASS_NAME = "com/coderising/jvm/test/EmployeeV1"; + static String path1 = "/Users/guodongchow/Desktop/coding2017/projects/mini-jvm/bin/"; static String path2 = "/Users/guodongchow/bin"; + 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 @@ -87,5 +101,99 @@ private String byteToHexString(byte[] codes ){ } 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.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()); + } + + } diff --git a/group27/513274874/mini-jvm/src/com/coderising/jvm/util/Util.java b/group27/513274874/mini-jvm/src/com/coderising/jvm/util/Util.java new file mode 100755 index 0000000000..0c4cc8c57c --- /dev/null +++ b/group27/513274874/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 execute(int n, int m){ + + return null; + } + +} diff --git a/liuxin/data-structure/answer/src/com/coding/basic/queue/JosephusTest.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/queue/Queue.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java b/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..4be68d6cbd --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/queue/QueueWithTwoStacks.java @@ -0,0 +1,41 @@ +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/liuxin/data-structure/answer/src/com/coding/basic/stack/Stack.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..fedb243604 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/StackUtil.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..7c86d22fe7 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..08918c490c --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExpr.java @@ -0,0 +1,78 @@ +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()){ + + 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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExprTest.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20e34e8852 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..67ff350735 --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/InfixToPostfix.java @@ -0,0 +1,13 @@ +package com.coding.basic.stack.expr; + +import java.util.List; + +public class InfixToPostfix { + + public static List convert(String expr) { + return null; + } + + + +} diff --git a/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PostfixExpr.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..c54eb69e2a --- /dev/null +++ b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,46 @@ +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){ + 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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PostfixExprTest.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PrefixExpr.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..f811fd6d9a --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PrefixExprTest.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/Token.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/TokenParser.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d3b0f167e1 --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/TokenParserTest.java b/liuxin/data-structure/answer/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/liuxin/data-structure/answer/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/liuxin/data-structure/src/com/coderising/download/DownloadThread.java b/liuxin/data-structure/assignment/src/com/coderising/download/DownloadThread.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/DownloadThread.java rename to liuxin/data-structure/assignment/src/com/coderising/download/DownloadThread.java diff --git a/liuxin/data-structure/src/com/coderising/download/FileDownloader.java b/liuxin/data-structure/assignment/src/com/coderising/download/FileDownloader.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/FileDownloader.java rename to liuxin/data-structure/assignment/src/com/coderising/download/FileDownloader.java diff --git a/liuxin/data-structure/src/com/coderising/download/FileDownloaderTest.java b/liuxin/data-structure/assignment/src/com/coderising/download/FileDownloaderTest.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/FileDownloaderTest.java rename to liuxin/data-structure/assignment/src/com/coderising/download/FileDownloaderTest.java diff --git a/liuxin/data-structure/src/com/coderising/download/api/Connection.java b/liuxin/data-structure/assignment/src/com/coderising/download/api/Connection.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/api/Connection.java rename to liuxin/data-structure/assignment/src/com/coderising/download/api/Connection.java diff --git a/liuxin/data-structure/assignment/src/com/coderising/download/api/ConnectionException.java b/liuxin/data-structure/assignment/src/com/coderising/download/api/ConnectionException.java new file mode 100644 index 0000000000..1551a80b3d --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coderising/download/api/ConnectionException.java @@ -0,0 +1,5 @@ +package com.coderising.download.api; + +public class ConnectionException extends Exception { + +} diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionManager.java b/liuxin/data-structure/assignment/src/com/coderising/download/api/ConnectionManager.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/ConnectionManager.java rename to liuxin/data-structure/assignment/src/com/coderising/download/api/ConnectionManager.java diff --git a/group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/DownloadListener.java b/liuxin/data-structure/assignment/src/com/coderising/download/api/DownloadListener.java similarity index 100% rename from group24/626451284/src/main/java/com/github/wdn/coding2017/coderising/download/api/DownloadListener.java rename to liuxin/data-structure/assignment/src/com/coderising/download/api/DownloadListener.java diff --git a/liuxin/data-structure/src/com/coderising/download/impl/ConnectionImpl.java b/liuxin/data-structure/assignment/src/com/coderising/download/impl/ConnectionImpl.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/impl/ConnectionImpl.java rename to liuxin/data-structure/assignment/src/com/coderising/download/impl/ConnectionImpl.java diff --git a/liuxin/data-structure/src/com/coderising/download/impl/ConnectionManagerImpl.java b/liuxin/data-structure/assignment/src/com/coderising/download/impl/ConnectionManagerImpl.java similarity index 100% rename from liuxin/data-structure/src/com/coderising/download/impl/ConnectionManagerImpl.java rename to liuxin/data-structure/assignment/src/com/coderising/download/impl/ConnectionManagerImpl.java diff --git a/liuxin/data-structure/assignment/src/com/coderising/litestruts/LoginAction.java b/liuxin/data-structure/assignment/src/com/coderising/litestruts/LoginAction.java new file mode 100644 index 0000000000..dcdbe226ed --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coderising/litestruts/LoginAction.java @@ -0,0 +1,39 @@ +package com.coderising.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/liuxin/data-structure/assignment/src/com/coderising/litestruts/Struts.java b/liuxin/data-structure/assignment/src/com/coderising/litestruts/Struts.java new file mode 100644 index 0000000000..85e2e22de3 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coderising/litestruts/Struts.java @@ -0,0 +1,34 @@ +package com.coderising.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/liuxin/data-structure/assignment/src/com/coderising/litestruts/StrutsTest.java b/liuxin/data-structure/assignment/src/com/coderising/litestruts/StrutsTest.java new file mode 100644 index 0000000000..b8c81faf3c --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coderising/litestruts/View.java b/liuxin/data-structure/assignment/src/com/coderising/litestruts/View.java new file mode 100644 index 0000000000..07df2a5dab --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/BinaryTreeNode.java b/liuxin/data-structure/assignment/src/com/coding/basic/BinaryTreeNode.java new file mode 100644 index 0000000000..d7ac820192 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/Iterator.java b/liuxin/data-structure/assignment/src/com/coding/basic/Iterator.java new file mode 100644 index 0000000000..06ef6311b2 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/List.java b/liuxin/data-structure/assignment/src/com/coding/basic/List.java new file mode 100644 index 0000000000..10d13b5832 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/array/ArrayList.java b/liuxin/data-structure/assignment/src/com/coding/basic/array/ArrayList.java new file mode 100644 index 0000000000..4576c016af --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/array/ArrayUtil.java b/liuxin/data-structure/assignment/src/com/coding/basic/array/ArrayUtil.java new file mode 100644 index 0000000000..45740e6d57 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LRUPageFrame.java b/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LRUPageFrame.java new file mode 100644 index 0000000000..994a241a3d --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LRUPageFrameTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LRUPageFrameTest.java new file mode 100644 index 0000000000..7fd72fc2b4 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LinkedList.java b/liuxin/data-structure/assignment/src/com/coding/basic/linklist/LinkedList.java new file mode 100644 index 0000000000..f4c7556a2e --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java new file mode 100644 index 0000000000..1ac659da3d --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/queue/CircleQueue.java @@ -0,0 +1,5 @@ +package com.coding.basic.queue; + +public class CircleQueue { + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/Josephus.java new file mode 100644 index 0000000000..d629d847f4 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/JosephusTest.java new file mode 100644 index 0000000000..7d90318b51 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/queue/Queue.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/Queue.java new file mode 100644 index 0000000000..c4c4b7325e --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java b/liuxin/data-structure/assignment/src/com/coding/basic/queue/QueueWithTwoStacks.java new file mode 100644 index 0000000000..bbd4715ca6 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/Stack.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/Stack.java new file mode 100644 index 0000000000..fedb243604 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtil.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtil.java new file mode 100644 index 0000000000..b0ec38161d --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtil.java @@ -0,0 +1,48 @@ +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) { + + + + } + + /** + * 删除栈中的某个元素 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * + * @param o + */ + public static void remove(Stack s,Object o) { + + } + + /** + * 从栈顶取得len个元素, 原来的栈中元素保持不变 + * 注意:只能使用Stack的基本操作,即push,pop,peek,isEmpty, 可以使用另外一个栈来辅助 + * @param len + * @return + */ + public static Object[] getTop(Stack s,int len) { + return null; + } + /** + * 字符串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){ + return false; + } + + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtilTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtilTest.java new file mode 100644 index 0000000000..76f2cb7668 --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/StackUtilTest.java @@ -0,0 +1,65 @@ +package com.coding.basic.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})")); + } + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixExpr.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixExpr.java new file mode 100644 index 0000000000..ef85ff007f --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixExprTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixExprTest.java new file mode 100644 index 0000000000..20e34e8852 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixToPostfix.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/InfixToPostfix.java new file mode 100644 index 0000000000..96a2194a67 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PostfixExpr.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PostfixExpr.java new file mode 100644 index 0000000000..dcbb18be4b --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PostfixExpr.java @@ -0,0 +1,18 @@ +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() { + return 0.0f; + } + + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PostfixExprTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PostfixExprTest.java new file mode 100644 index 0000000000..c0435a2db5 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PrefixExpr.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PrefixExpr.java new file mode 100644 index 0000000000..956927e2df --- /dev/null +++ b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PrefixExpr.java @@ -0,0 +1,18 @@ +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() { + return 0.0f; + } + + +} diff --git a/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PrefixExprTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/PrefixExprTest.java new file mode 100644 index 0000000000..5cec210e75 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/Token.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/Token.java new file mode 100644 index 0000000000..8579743fe9 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/TokenParser.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/TokenParser.java new file mode 100644 index 0000000000..d3b0f167e1 --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/TokenParserTest.java b/liuxin/data-structure/assignment/src/com/coding/basic/stack/expr/TokenParserTest.java new file mode 100644 index 0000000000..399d3e857e --- /dev/null +++ b/liuxin/data-structure/assignment/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/liuxin/data-structure/src/com/coderising/download/api/ConnectionManager.java b/liuxin/data-structure/src/com/coderising/download/api/ConnectionManager.java deleted file mode 100644 index ce045393b1..0000000000 --- a/liuxin/data-structure/src/com/coderising/download/api/ConnectionManager.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.coderising.download.api; - -public interface ConnectionManager { - /** - * 给定一个url , 打开一个连接 - * @param url - * @return - */ - public Connection open(String url) throws ConnectionException; -} diff --git a/liuxin/data-structure/src/com/coderising/download/api/DownloadListener.java b/liuxin/data-structure/src/com/coderising/download/api/DownloadListener.java deleted file mode 100644 index bf9807b307..0000000000 --- a/liuxin/data-structure/src/com/coderising/download/api/DownloadListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.coderising.download.api; - -public interface DownloadListener { - public void notifyFinished(); -} diff --git a/liuxin/data-structure/src/com/coding/basic/Queue.java b/liuxin/data-structure/src/com/coding/basic/Queue.java deleted file mode 100644 index 36e516e266..0000000000 --- a/liuxin/data-structure/src/com/coding/basic/Queue.java +++ /dev/null @@ -1,19 +0,0 @@ -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/liuxin/data-structure/src/com/coding/basic/stack/Stack.java b/liuxin/data-structure/src/com/coding/basic/stack/Stack.java deleted file mode 100644 index 4f4b9af52e..0000000000 --- a/liuxin/data-structure/src/com/coding/basic/stack/Stack.java +++ /dev/null @@ -1,24 +0,0 @@ -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/liuxin/data-structure/src/com/coding/basic/stack/StackUtil.java b/liuxin/data-structure/src/com/coding/basic/stack/StackUtil.java deleted file mode 100644 index d4c496a2f9..0000000000 --- a/liuxin/data-structure/src/com/coding/basic/stack/StackUtil.java +++ /dev/null @@ -1,136 +0,0 @@ -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/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java b/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java deleted file mode 100644 index 0a145ff047..0000000000 --- a/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExpr.java +++ /dev/null @@ -1,18 +0,0 @@ -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/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java b/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java deleted file mode 100644 index 92d130cddd..0000000000 --- a/liuxin/data-structure/src/com/coding/basic/stack/expr/InfixExprTest.java +++ /dev/null @@ -1,48 +0,0 @@ -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/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/AttributeInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/AttributeInfo.java new file mode 100644 index 0000000000..88f60c77f6 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java new file mode 100644 index 0000000000..03df78f541 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/CodeAttr.java @@ -0,0 +1,121 @@ +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/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/LocalVariableItem.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/LocalVariableTable.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..88f677b2c8 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/StackMapTable.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/AccessFlag.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/ClassFile.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..58424f3c0b --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/ClassFile.java @@ -0,0 +1,120 @@ +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(){ + 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/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/ClassIndex.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/BiPushCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..0410f9d061 --- /dev/null +++ b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/CommandParser.java @@ -0,0 +1,155 @@ +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 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 (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()); + // System.out.println( cmd.toString(clzFile.getConstPool())); + 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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/OneOperandCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ClassInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ConstantInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ConstantPool.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/FieldRefInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/NullConstantInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/StringInfo.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/UTF8Info.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/loader/ByteCodeIterator.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/loader/ClassFileLoader.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/EmployeeV1.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/liuxin/mini-jvm/answer/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/liuxin/mini-jvm/answer/src/com/coderising/jvm/util/Util.java b/liuxin/mini-jvm/answer/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/liuxin/mini-jvm/answer/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 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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/LocalVariableItem.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/LocalVariableItem.java new file mode 100644 index 0000000000..962c3b8bc4 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/LocalVariableTable.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/LocalVariableTable.java new file mode 100644 index 0000000000..14db5dca46 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/StackMapTable.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/attr/StackMapTable.java new file mode 100644 index 0000000000..18f2ad0360 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/AccessFlag.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/AccessFlag.java new file mode 100644 index 0000000000..faae056835 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/ClassFile.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/ClassFile.java new file mode 100644 index 0000000000..2a8dfb6123 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/ClassIndex.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/clz/ClassIndex.java new file mode 100644 index 0000000000..e424f284b3 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/BiPushCmd.java new file mode 100644 index 0000000000..cd0fbd4848 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/ByteCodeCommand.java new file mode 100644 index 0000000000..a3abeacc82 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/CommandParser.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/CommandParser.java new file mode 100644 index 0000000000..2bb36340f5 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetFieldCmd.java new file mode 100644 index 0000000000..2e6061edd2 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/GetStaticFieldCmd.java new file mode 100644 index 0000000000..e6cf9d5960 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeSpecialCmd.java new file mode 100644 index 0000000000..ac228d0e4d --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/InvokeVirtualCmd.java new file mode 100644 index 0000000000..c15d827797 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/LdcCmd.java new file mode 100644 index 0000000000..ffb66f811c --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NewObjectCmd.java new file mode 100644 index 0000000000..33813b5d59 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/NoOperandCmd.java new file mode 100644 index 0000000000..56c28fefe2 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/OneOperandCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/OneOperandCmd.java new file mode 100644 index 0000000000..963d064257 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/PutFieldCmd.java new file mode 100644 index 0000000000..85bb369c19 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/TwoOperandCmd.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/cmd/TwoOperandCmd.java new file mode 100644 index 0000000000..6c0cf53082 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ClassInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ClassInfo.java new file mode 100644 index 0000000000..c8e65ff493 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ConstantInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ConstantInfo.java new file mode 100644 index 0000000000..88353df2d3 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ConstantPool.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/ConstantPool.java new file mode 100644 index 0000000000..7130eb3a9f --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/FieldRefInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/FieldRefInfo.java new file mode 100644 index 0000000000..7ae71396ef --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/MethodRefInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/MethodRefInfo.java new file mode 100644 index 0000000000..036e6d9055 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/NameAndTypeInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/NameAndTypeInfo.java new file mode 100644 index 0000000000..5cbbba6033 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/NullConstantInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/NullConstantInfo.java new file mode 100644 index 0000000000..41e0fd7e7a --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/StringInfo.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/StringInfo.java new file mode 100644 index 0000000000..6bfcb47273 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/UTF8Info.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/constant/UTF8Info.java new file mode 100644 index 0000000000..7db88a939e --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/field/Field.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/field/Field.java new file mode 100644 index 0000000000..c6eb0196f8 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/loader/ByteCodeIterator.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/loader/ByteCodeIterator.java new file mode 100644 index 0000000000..6fb5570dff --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/loader/ClassFileLoader.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/loader/ClassFileLoader.java new file mode 100644 index 0000000000..33185d8175 --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/EmployeeV1.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/test/EmployeeV1.java new file mode 100644 index 0000000000..12e3d7efdd --- /dev/null +++ b/liuxin/mini-jvm/assignment/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/liuxin/mini-jvm/assignment/src/com/coderising/jvm/util/Util.java b/liuxin/mini-jvm/assignment/src/com/coderising/jvm/util/Util.java new file mode 100644 index 0000000000..0c4cc8c57c --- /dev/null +++ b/liuxin/mini-jvm/assignment/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 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/liuxin/mini-jvm/src/com/coderising/jvm/field/Field.java b/liuxin/mini-jvm/src/com/coderising/jvm/field/Field.java deleted file mode 100644 index 09bae5a1ae..0000000000 --- a/liuxin/mini-jvm/src/com/coderising/jvm/field/Field.java +++ /dev/null @@ -1,33 +0,0 @@ -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){ - - return null; - } - -} diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java b/liuxin/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java deleted file mode 100644 index 5c5173fbe8..0000000000 --- a/liuxin/mini-jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java +++ /dev/null @@ -1,57 +0,0 @@ -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/liuxin/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java b/liuxin/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java deleted file mode 100644 index 444ec4c60d..0000000000 --- a/liuxin/mini-jvm/src/com/coderising/jvm/loader/ClassFileParser.java +++ /dev/null @@ -1,151 +0,0 @@ -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; -import com.coderising.jvm.field.Field; -import com.coderising.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); - - - 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) { - 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) { - // 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, 这里需要解析 - } - - - -} diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/method/Method.java b/liuxin/mini-jvm/src/com/coderising/jvm/method/Method.java deleted file mode 100644 index ba5f7848d1..0000000000 --- a/liuxin/mini-jvm/src/com/coderising/jvm/method/Method.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.coderising.jvm.method; - -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 static Method parse(ClassFile clzFile, ByteCodeIterator iter){ - return null; - - } -} diff --git a/liuxin/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java b/liuxin/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java deleted file mode 100644 index c29ff5181f..0000000000 --- a/liuxin/mini-jvm/src/com/coderising/jvm/test/ClassFileloaderTest.java +++ /dev/null @@ -1,277 +0,0 @@ -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.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 = "C:\\Users\\liuxin\\git\\coding2017\\liuxin\\mini-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); - 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); - } - - - - 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); - } - - -}