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 jvm.engine.JavaObject; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Created by Haochen on 2017/4/9. * TODO: */ public class ClassFile { ClassIndex classIndex; AccessFlag accessFlag; ConstantPool constantPool; int minorVersion; int majorVersion; List<ClassInfo> interfaces = new ArrayList<>(); List<Field> fields = new ArrayList<>(); List<Method> methods = new ArrayList<>(); List<AttributeInfo> attributes = new ArrayList<>(); Map<String, JavaObject> staticFieldValues = new HashMap<>(); public AccessFlag getAccessFlag() { return accessFlag; } public List<ClassInfo> getInterfaces() { return this.interfaces; } public List<Field> getFields() { return this.fields; } public List<Method> getMethods() { return methods; } public List<AttributeInfo> getAttributes() { return attributes; } public void print() { if(this.accessFlag.isPublic()){ 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.classIndex.getThisClassIndex(); ClassInfo thisClass = (ClassInfo)this.getConstantPool().getConstantInfo(thisClassIndex); return thisClass.getClassName(); } public 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; } public Method getMethod(String methodName, String paramAndReturnType) { return methods.stream().filter(m -> methodName.equals(m.getName()) && paramAndReturnType.equals(m.getParamAndReturnType())) .findFirst().orElse(null); } public Method getMainMethod() { return getMethod("main", "([Ljava/lang/String;)V"); } public Field getField(String name) { return fields.stream() .filter(f -> f.getName().equals(name)) .findFirst() .orElse(null); } public JavaObject getStaticFieldValue(String name) { return staticFieldValues.get(name); } public void putStaticFieldValue(String name, JavaObject object) { java.lang.reflect.Field field; try { Class<?> clazz = Class.forName(this.getClassName().replace('/', '.')); field = clazz.getDeclaredField(name); field.setAccessible(true); if (object == null) { staticFieldValues.remove(name); field.set(null, null); } else { staticFieldValues.put(name, object); field.set(null, object); } } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException("Static field " + getClassName() + "." + name + "not found"); } } }