From 835b35677aebeac317a69988f766104d0b799743 Mon Sep 17 00:00:00 2001 From: sdnb Date: Mon, 10 Apr 2017 23:25:03 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=AC=AC=E4=BA=94=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coderising/jvm/clz/AccessFlag.java | 25 ++++ .../src/com/coderising/jvm/clz/ClassFile.java | 76 +++++++++++ .../com/coderising/jvm/clz/ClassIndex.java | 19 +++ .../coderising/jvm/constant/ClassInfo.java | 24 ++++ .../coderising/jvm/constant/ConstantInfo.java | 29 +++++ .../coderising/jvm/constant/ConstantPool.java | 36 +++++ .../coderising/jvm/constant/FieldRefInfo.java | 54 ++++++++ .../jvm/constant/MethodRefInfo.java | 55 ++++++++ .../jvm/constant/NameAndTypeInfo.java | 45 +++++++ .../jvm/constant/NullConstantInfo.java | 13 ++ .../coderising/jvm/constant/StringInfo.java | 26 ++++ .../com/coderising/jvm/constant/UTF8Info.java | 32 +++++ .../jvm/loader/ByteCodeIterator.java | 52 ++++++++ .../jvm/loader/ClassFileLoader.java | 53 +++++--- .../jvm/loader/ClassFileParser.java | 103 +++++++++++++++ .../src/com/coderising/jvm/util/Util.java | 40 ++++++ .../src/main/java/com/coding/weak1/Stack.java | 14 ++ .../com/coding/week5/stack/StackUtil.java | 111 ++++++++++++++++ .../mini_jvm/test/ClassFileloaderTest.java | 123 +++++++++++++++--- .../com/coding/week5/stack/StackUtilTest.java | 56 ++++++++ 20 files changed, 945 insertions(+), 41 deletions(-) create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/AccessFlag.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassFile.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/clz/ClassIndex.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ClassInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/ConstantPool.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/FieldRefInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/MethodRefInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NameAndTypeInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/NullConstantInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/StringInfo.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/constant/UTF8Info.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ByteCodeIterator.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileParser.java create mode 100644 group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/util/Util.java create mode 100644 group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java create mode 100644 group24/494800949/src/test/java/com/coding/week5/stack/StackUtilTest.java 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 index 1ca7cc8ece..452f6bce7d 100644 --- a/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java +++ b/group24/494800949/src/main/java/com/coding/mini_jvm/src/com/coderising/jvm/loader/ClassFileLoader.java @@ -1,6 +1,11 @@ package com.coding.mini_jvm.src.com.coderising.jvm.loader; -import java.io.*; +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; @@ -14,29 +19,35 @@ public class ClassFileLoader { public byte[] readBinaryCode(String className) { String classPath = getClassPath(); String[] paths = classPath.split(File.pathSeparator); - className = className.replaceAll("\\.", "\\"+File.separator) ; + className = className.replace('.', File.separatorChar) ; for (String path : paths) { - String filename = path + File.separator + className + CLASS_FILE_SUFFIX; - File file = new File(filename); - if (file.exists()) { - try { - FileInputStream fis = new FileInputStream(file); - BufferedInputStream bis = new BufferedInputStream(fis); - byte[] data = new byte[bis.available()]; - bis.read(data); - return data; - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } + 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); } @@ -52,8 +63,10 @@ public String getClassPath(){ 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/week5/stack/StackUtil.java b/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java new file mode 100644 index 0000000000..d893fcaa24 --- /dev/null +++ b/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java @@ -0,0 +1,111 @@ +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(); + Stack stack1 = new Stack(); + char[] chars = s.toCharArray(); + for (char c : chars) { + if ( c >= 'a' && c <= 'z') { + continue; + } + stack.push(c); + stack1.push(c); + } + reverse(stack); + while (!stack.isEmpty()) { + if (!isPair((char)stack1.pop(), (char)stack.pop())) { + return false; + } + } + return true; + } + + private static boolean isPair(char c1, char c2) { + switch (c1) { + case '{': + return c2 == '}'; + case '}': + return c2 == '{'; + case '[': + return c2 == ']'; + case ']': + return c2 == '['; + case '(': + return c2 == ')'; + case ')': + return c2 == '('; + 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 index 830d0b7efe..a03f29c0c3 100644 --- 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 @@ -1,6 +1,10 @@ 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; @@ -16,9 +20,19 @@ 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 { } @@ -65,28 +79,95 @@ public void testMagicNumber(){ byte[] codes = new byte[]{byteCodes[0],byteCodes[1],byteCodes[2],byteCodes[3]}; - String acctualValue = this.byteToHexString(codes); + String acctualValue = Util.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()); } - return buffer.toString(); } + @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/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 From 830964bc3a6bed90149d85b68641c04907d61aa2 Mon Sep 17 00:00:00 2001 From: sdnb Date: Tue, 11 Apr 2017 00:05:27 +0800 Subject: [PATCH 2/2] =?UTF-8?q?stackUtil=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/coding/week5/stack/StackUtil.java | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) 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 index d893fcaa24..7b750b3549 100644 --- a/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java +++ b/group24/494800949/src/main/java/com/coding/week5/stack/StackUtil.java @@ -71,38 +71,30 @@ public static Object[] getTop(Stack s,int len) { */ public static boolean isValidPairs(String s){ Stack stack = new Stack(); - Stack stack1 = new Stack(); char[] chars = s.toCharArray(); for (char c : chars) { - if ( c >= 'a' && c <= 'z') { - continue; - } - stack.push(c); - stack1.push(c); - } - reverse(stack); - while (!stack.isEmpty()) { - if (!isPair((char)stack1.pop(), (char)stack.pop())) { - return false; + 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 true; + return stack.isEmpty(); } - private static boolean isPair(char c1, char c2) { - switch (c1) { + private static boolean isPair(char left, char right) { + switch (left) { case '{': - return c2 == '}'; - case '}': - return c2 == '{'; + return right == '}'; case '[': - return c2 == ']'; - case ']': - return c2 == '['; + return right == ']'; case '(': - return c2 == ')'; - case ')': - return c2 == '('; + return right == ')'; default: return false; }