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;
public class ClassFileParser {
/**
* 读取ClassFile对象
*
* @param codes
* @return
*/
public ClassFile parse(byte[] codes) {
ClassFile cf = new ClassFile();
ByteCodeIterator itr = new ByteCodeIterator(codes);
String magicNumber = itr.nextUxtoHexString(4);// 1读取魔数
if (!magicNumber.equals("cafebabe")) {
throw new RuntimeException("magicNum not ok");
}
cf.setMinorVersion(itr.nextU2toInt());// 3读取次版本号
cf.setMajorVersion(itr.nextU2toInt());// 2读取主版本号
ConstantPool pool = parseConstantPool(itr);// 4、5读取常量池
pool.print();// 打印常量池
cf.setPool(pool);
cf.setAccessFlag(new AccessFlag(itr.nextU2toInt()));// 6读取访问标志
ClassIndex classIndex = parseClassIndex(itr);// 读取类引用7this和8super
cf.setClzIndex(classIndex);
int interfaceCount = itr.nextU2toInt();//读取接口信息
if (interfaceCount != 0) {
throw new RuntimeException(
"the interface isn't 0,parser has not been implemented yet.");
}
int FieldCount = itr.nextU2toInt();//读取字段信息
for (int i = 0; i < FieldCount; i++) {
Field f = Field.parse(pool, itr);
cf.addFields(f);
}
int MethodCount = itr.nextU2toInt();
for (int i = 0; i < MethodCount; i++) {//读取方法信息
Method m = Method.parse(pool, itr);
cf.addMethods(m);
}
return cf;
}
/**
* 读取this super对象引用<br/>
* classIndex_Info {<br/>
* u2 this_class,<br/>
* u2 super_class<br/>
* }
*
* @param itr
* @return
*/
public ClassIndex parseClassIndex(ByteCodeIterator itr) {
ClassIndex classIndex = new ClassIndex();
classIndex.setThisClassIndex(itr.nextU2toInt());
classIndex.setSuperClassIndex(itr.nextU2toInt());
return classIndex;
}
/**
* 读取常量池
*
* @param itr
* @return
*/
public ConstantPool parseConstantPool(ByteCodeIterator itr) {
int count = itr.nextU2toInt();
ConstantPool pool = new ConstantPool();
pool.addConstantInfo(new NullConstantInfo());// 占住常量池的第一个,常量池是的index从1开始
for (int i = 1; i < count; i++) {
int tag = itr.nextU1toInt();
switch (tag) {
case ConstantInfo.CLASS_INFO:
ClassInfo classInfo = new ClassInfo(pool);
classInfo.setUtf8Index(itr.nextU2toInt());
pool.addConstantInfo(classInfo);
/*
* System.out.println(i + ". u1 tag:" +
* classInfo.getType()+" ClassInfo" + ",u2 name_index:" +
* classInfo.getUtf8Index());
*/
break;
case ConstantInfo.UTF8_INFO:
UTF8Info utf8Info = new UTF8Info(pool);
int length = itr.nextU2toInt();
String value = itr.nextUxtoAscii(length);
utf8Info.setLength(length);
utf8Info.setValue(value);
pool.addConstantInfo(utf8Info);
/*
* System.out.println(i + ". u1 tag:" + utf8Info.getType() +
* " UTF8Info" + ",u2 length:" + utf8Info.getLength() +
* ",u1 bytes[" + utf8Info.getLength() + "] " +
* utf8Info.getValue());
*/
break;
case ConstantInfo.STRING_INFO:
StringInfo si = new StringInfo(pool);
si.setString_index(itr.nextU2toInt());
pool.addConstantInfo(si);
/*
* System.out.println(i + ". u1 tag:" +
* si.getType()+" StringInfo" + ",u2 string_index:" +
* si.getString_index());
*/
break;
case ConstantInfo.NAME_AND_TYPE_INFO:
NameAndTypeInfo nt = new NameAndTypeInfo(pool);
nt.setName_index(itr.nextU2toInt());
nt.setDescriptor_index(itr.nextU2toInt());
pool.addConstantInfo(nt);
/*
* System.out.println(i + ". u1 tag:" + nt.getType()+
* " NameAndTypeInfo" + ",u2 name_index:" + nt.getName_index() +
* ",u2 descriptor_index:" + nt.getDescriptor_index());
*/
break;
case ConstantInfo.METHOD_INFO:
MethodRefInfo m = new MethodRefInfo(pool);
m.setClassInfoIndex(itr.nextU2toInt());
m.setNameAndTypeIndex(itr.nextU2toInt());
pool.addConstantInfo(m);
/*
* System.out.println(i + ". u1 tag:" + m.getType()+
* " MethodInfo" + ",u2 class_index:" + m.getClassInfoIndex() +
* ",u2 name_and_type_index" + m.getNameAndTypeIndex());
*/
break;
case ConstantInfo.FIELD_INFO:
FieldRefInfo f = new FieldRefInfo(pool);
f.setClass_index(itr.nextU2toInt());
f.setName_and_type_index(itr.nextU2toInt());
pool.addConstantInfo(f);
/*
* System.out.println(i + ". u1 tag:" + f.getType()+
* " FieldInfo" + ",u2 class_index:" + f.getClass_index() +
* ",u2 name_and_type_index:" + f.getName_and_type_index());
*/
break;
/*
* case ConstantInfo.FLOAT_INFO:
*
* break;
*
* case ConstantInfo.INTEGER_INFO: break;
*
* case ConstantInfo.DOUBLE_INFO: break;
*
* case ConstantInfo.LONG_INFO: break;
*/
default:
throw new RuntimeException("the constant pool tag " + tag
+ " has not been implemented yet.");
}
}
return pool;
}
}