Skip to content

Commit

Permalink
完成常量池解析
Browse files Browse the repository at this point in the history
  • Loading branch information
miniyk2012 committed Apr 9, 2017
1 parent 15447d7 commit 63c46f3
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 45 deletions.
7 changes: 6 additions & 1 deletion group02/812350401/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ public void setConstPool(ConstantPool pool) {
public void setClassIndex(ClassIndex clzIndex) {
this.clzIndex = clzIndex;
}





public void print(){

Expand All @@ -60,8 +58,7 @@ public void print(){
System.out.println("Class Name:"+ getClassName());

System.out.println("Super Class Name:"+ getSuperClassName());



}

private String getClassName(){
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.github.miniyk2012.coding2017.coderising.jvm.constant;

import com.github.miniyk2012.coding2017.coderising.jvm.loader.ByteCodeIterator;

import java.util.ArrayList;
import java.util.List;

public class ConstantPool {

private List<ConstantInfo> constantInfos = new ArrayList<ConstantInfo>();



public ConstantPool(){

}

public void addConstantInfo(ConstantInfo info){

this.constantInfos.add(info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ public String toString(){
}

public String getClassName(){

ClassInfo classInfo = (ClassInfo) this.getConstantInfo(this.getClassInfoIndex());

UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index());

return utf8Info.getValue();
// UTF8Info utf8Info = (UTF8Info)this.getConstantInfo(classInfo.getUtf8Index());
// return utf8Info.getValue();
return classInfo.getClassName();

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,28 @@ public void setNameAndTypeIndex(int nameAndTypeIndex) {
}

public String toString(){

return getClassName() +" : "+ this.getMethodName() + " : " + this.getParamAndReturnType() ;
}

public String getClassName(){
ConstantPool pool = this.getConstantPool();
ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex());
// ConstantPool pool = this.getConstantPool();
// ClassInfo clzInfo = (ClassInfo)pool.getConstantInfo(this.getClassInfoIndex());
ClassInfo clzInfo = (ClassInfo)this.getConstantInfo(classInfoIndex);
return clzInfo.getClassName();
}

public String getMethodName(){
ConstantPool pool = this.getConstantPool();
NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex());
// ConstantPool pool = this.getConstantPool();
// NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex());
NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(nameAndTypeIndex);
return typeInfo.getName();
}

public String getParamAndReturnType(){
ConstantPool pool = this.getConstantPool();
NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex());
// ConstantPool pool = this.getConstantPool();
// NameAndTypeInfo typeInfo = (NameAndTypeInfo)pool.getConstantInfo(this.getNameAndTypeIndex());
NameAndTypeInfo typeInfo = (NameAndTypeInfo)this.getConstantInfo(nameAndTypeIndex);
return typeInfo.getTypeInfo();
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ public int getType() {


public String getName(){
ConstantPool pool = this.getConstantPool();
UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1);
// ConstantPool pool = this.getConstantPool();
// UTF8Info utf8Info1 = (UTF8Info)pool.getConstantInfo(index1);
UTF8Info utf8Info1 = (UTF8Info)getConstantInfo(index1);
return utf8Info1.getValue();
}

public String getTypeInfo(){
ConstantPool pool = this.getConstantPool();
UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2);
// ConstantPool pool = this.getConstantPool();
// UTF8Info utf8Info2 = (UTF8Info)pool.getConstantInfo(index2);
UTF8Info utf8Info2 = (UTF8Info)getConstantInfo(index2);
return utf8Info2.getValue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,5 @@ public String getValue() {
public void setValue(String value) {
this.value = value;
}



}
Original file line number Diff line number Diff line change
@@ -1,5 +1,79 @@
package com.github.miniyk2012.coding2017.coderising.jvm.loader;

import com.github.miniyk2012.coding2017.coderising.jvm.util.Util;
import org.apache.commons.lang3.ArrayUtils;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class ByteCodeIterator {
private byte[] codes;
private int point = 0;

public ByteCodeIterator(byte[] codes) {
this.codes = codes;
}

public int nextU1toInt() {
byte[] u1 = new byte[] {codes[point++]};
return Util.byteToInt(u1);
}

public int nextU2toInt() {
byte[] u2 = new byte[] {codes[point++], codes[point++]};
return Util.byteToInt(u2);
}

/**
* 读取n个字节,并编码成UTF-8输出,point自动增加
* @param n
* @return
*/
public String readUtf8(int n)
{
byte[] info = Arrays.copyOfRange(codes, point, point+n);
String utf8;
try {
utf8 = new String(info, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("常量池UTF-8编码错误");
}
point += n;
return utf8;
}

/**
* 返回当前位置
* @return
*/
public int position() {
return point;
}

/**
* n可正可负
* @param n
*/
public void skip(int n) {
point = point + n;
}

public void seek(int n) {
if (n >= codes.length || n < 0) throw new IndexOutOfBoundsException();
point = n;
}

public static void main(String[] args) throws UnsupportedEncodingException {
byte[] codes = {0x00, 0x34, 0x00};
ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes);
System.out.println(byteCodeIterator.nextU2toInt());
System.out.println(byteCodeIterator.nextU1toInt());

byte[] codes2 = "Employee".getBytes("UTF-8");
byte[] codes3 = ArrayUtils.addAll(codes2, codes);
byteCodeIterator = new ByteCodeIterator(codes3);
System.out.println(byteCodeIterator.readUtf8(codes2.length));
System.out.println(byteCodeIterator.nextU2toInt());
System.out.println(byteCodeIterator.nextU1toInt());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,110 @@
import com.github.miniyk2012.coding2017.coderising.jvm.clz.AccessFlag;
import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassFile;
import com.github.miniyk2012.coding2017.coderising.jvm.clz.ClassIndex;
import com.github.miniyk2012.coding2017.coderising.jvm.constant.ConstantPool;

import java.io.UnsupportedEncodingException;
import com.github.miniyk2012.coding2017.coderising.jvm.constant.*;


public class ClassFileParser {

public ClassFile parse(byte[] codes) {



ClassFile clzFile = new ClassFile();
ByteCodeIterator byteCodeIterator = new ByteCodeIterator(codes);
byteCodeIterator.skip(4); // skip magic
int minorVersion = byteCodeIterator.nextU2toInt();
int majorVersion = byteCodeIterator.nextU2toInt();
ConstantPool constantPool = parseConstantPool(byteCodeIterator);
AccessFlag accessFlag = parseAccessFlag(byteCodeIterator);
ClassIndex classIndex = parseClassInfex(byteCodeIterator);

return null;
clzFile.setMinorVersion(minorVersion);
clzFile.setMajorVersion(majorVersion);
clzFile.setConstPool(constantPool);
clzFile.setAccessFlag(accessFlag);
clzFile.setClassIndex(classIndex);
return clzFile;
}

private AccessFlag parseAccessFlag(ByteCodeIterator iter) {

return null;
protected AccessFlag parseAccessFlag(ByteCodeIterator iter) {
int access_flags = iter.nextU2toInt();
AccessFlag accessFlag = new AccessFlag(access_flags);
return accessFlag;
}

private ClassIndex parseClassInfex(ByteCodeIterator iter) {

return null;

protected ClassIndex parseClassInfex(ByteCodeIterator iter) {
ClassIndex classIndex = new ClassIndex();
int thisClassIndex = iter.nextU2toInt();
int superClassIndex = iter.nextU2toInt();
classIndex.setThisClassIndex(thisClassIndex);
classIndex.setSuperClassIndex(superClassIndex);
return classIndex;
}

private ConstantPool parseConstantPool(ByteCodeIterator iter) {

return null;
protected ConstantPool parseConstantPool(ByteCodeIterator iter) {
ConstantPool constantPool = new ConstantPool();
int constant_pool_count = iter.nextU2toInt();
ConstantInfo constantInfo;
constantPool.addConstantInfo(new NullConstantInfo());
for (int i=1; i<constant_pool_count; i++) {
int tag = iter.nextU1toInt();
constantInfo = getConstantInfo(iter, tag, constantPool);
constantPool.addConstantInfo(constantInfo);
}
return constantPool;
}


protected ConstantInfo getConstantInfo(ByteCodeIterator iter, int tag, ConstantPool pool) {
switch (tag) {
case ConstantInfo.UTF8_INFO: {
UTF8Info utf8Info = new UTF8Info(pool);
int length = iter.nextU2toInt();
String value = iter.readUtf8(length);
utf8Info.setLength(length);
utf8Info.setValue(value);
return utf8Info;
}
case ConstantInfo.FLOAT_INFO: {
throw new RuntimeException(String.format("FLOAT_INFO常量池类型[%d]还未实现", tag));
}
case ConstantInfo.CLASS_INFO: {
ClassInfo classInfo = new ClassInfo(pool);
int utf8Index = iter.nextU2toInt();
classInfo.setUtf8Index(utf8Index);
return classInfo;
}
case ConstantInfo.FIELD_INFO: {
FieldRefInfo fieldRefInfo = new FieldRefInfo(pool);
int classInfoIndex = iter.nextU2toInt();
fieldRefInfo.setClassInfoIndex(classInfoIndex);
int nameAndTypeIndex = iter.nextU2toInt();
fieldRefInfo.setNameAndTypeIndex(nameAndTypeIndex);
return fieldRefInfo;
}
case ConstantInfo.METHOD_INFO: {
MethodRefInfo methodRefInfo = new MethodRefInfo(pool);
int classInfoIndex = iter.nextU2toInt();
int nameAndTypeIndex = iter.nextU2toInt();
methodRefInfo.setClassInfoIndex(classInfoIndex);
methodRefInfo.setNameAndTypeIndex(nameAndTypeIndex);
return methodRefInfo;
}
case ConstantInfo.NAME_AND_TYPE_INFO: {
NameAndTypeInfo nameAndTypeInfo = new NameAndTypeInfo(pool);
int index1 = iter.nextU2toInt();
int index2 = iter.nextU2toInt();
nameAndTypeInfo.setIndex1(index1);
nameAndTypeInfo.setIndex2(index2);
return nameAndTypeInfo;
}
case ConstantInfo.STRING_INFO: {
StringInfo stringInfo = new StringInfo(pool);
int index = iter.nextU2toInt();
stringInfo.setIndex(index);
return stringInfo;
}
default: {
throw new RuntimeException(String.format("该常量池类型[%d]还未实现", tag));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ public class ClassFileloaderTest {
static String path2 = ClassFileloaderTest.class.getClassLoader().getResource("jvm").getPath();
static ClassFile clzFile = null;

static {
ClassFileLoader loader = new ClassFileLoader();
loader.addClassPath(path1);
loader.addClassPath(path2);
String className = "com.github.miniyk2012.coding2017.jvm.test.EmployeeV1";

clzFile = loader.loadClass(className);
clzFile.print();
}

@Before
public void setUp() throws Exception {
}
Expand Down Expand Up @@ -51,7 +61,7 @@ public void testClassFileLength() {
byte[] byteCodes = loader.readBinaryCode(className);

// 注意:这个字节数可能和你的JVM版本有关系, 你可以看看编译好的类到底有多大
Assert.assertEquals(1114, byteCodes.length);
Assert.assertEquals(1056, byteCodes.length);

}

Expand Down
Binary file not shown.
Loading

0 comments on commit 63c46f3

Please sign in to comment.