ClassLoader
This commit is contained in:
parent
6233862b56
commit
675d9fd807
@ -14,6 +14,7 @@ import com.gabongao.jvm.classfile.MemberInfo;
|
||||
import com.gabongao.jvm.instructions.*;
|
||||
import com.gabongao.jvm.rtda.Frame;
|
||||
import com.gabongao.jvm.rtda.Thread;
|
||||
import com.gabongao.jvm.rtda.heap.Method;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
@ -58,6 +59,20 @@ public class Interpreter {
|
||||
}
|
||||
}
|
||||
|
||||
public void doInterpreter(Method method) {
|
||||
Thread thread = new Thread();
|
||||
Frame frame = new Frame(thread, method);
|
||||
thread.pushFrame(frame);
|
||||
try {
|
||||
loop(thread, method.getCode());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println();
|
||||
System.out.printf("LocalVars: %s\n", frame.getLocalVars());
|
||||
System.out.printf("OperandStack: %s\n", frame.getOperandStack());
|
||||
}
|
||||
}
|
||||
|
||||
public void loop(Thread thread, byte[] byteCode) {
|
||||
Frame frame = thread.popFrame();
|
||||
BytecodeReader bytecodeReader = new BytecodeReader();
|
||||
@ -65,13 +80,13 @@ public class Interpreter {
|
||||
for (; ; ) {
|
||||
int pc = frame.getNextPc();
|
||||
thread.setPc(pc);
|
||||
System.out.printf("loop: %2d\t", n);
|
||||
System.out.printf("loop: %6d\t", n);
|
||||
bytecodeReader.reset(byteCode, pc);
|
||||
char opcode = (char) bytecodeReader.readInt8();
|
||||
Instruction instruction = Factory.newInstruction((byte) opcode);
|
||||
instruction.fetchOperands(bytecodeReader);
|
||||
frame.setNextPc(bytecodeReader.getPc());
|
||||
System.out.printf("pc:%2d\t inst:%s\n", pc, instruction.getClass().getName());
|
||||
System.out.printf("pc:%3d\t inst:%s\n", pc, instruction.getClass().getName());
|
||||
instruction.execute(frame);
|
||||
n++;
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@ import com.gabongao.jvm.classpath.ClassPath;
|
||||
import com.gabongao.jvm.rtda.Frame;
|
||||
import com.gabongao.jvm.rtda.LocalVars;
|
||||
import com.gabongao.jvm.rtda.OperandStack;
|
||||
import com.gabongao.jvm.rtda.heap.ClassLoader;
|
||||
import com.gabongao.jvm.rtda.heap.ClassStruct;
|
||||
import com.gabongao.jvm.rtda.heap.Method;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
@ -52,11 +55,11 @@ public class Jvm {
|
||||
/* ch02
|
||||
ClassPath cp = new ClassPath();
|
||||
cp.parse(cmd.jreOption, cmd.cpOption);
|
||||
System.out.printf("classpath: %s\tclass: %s\targs: %s\n",cmd.cpOption,cmd.className, Arrays.asList(cmd.args));
|
||||
String className = cmd.className.replace(".", "/").concat(".class");
|
||||
byte[] classData = cp.readClass(className);
|
||||
System.out.printf("classpath: %s\tclass: %s\targs: %s\n",cmd.cpOption,cmd.getClassName, Arrays.asList(cmd.args));
|
||||
String getClassName = cmd.getClassName.replace(".", "/").concat(".class");
|
||||
byte[] classData = cp.readClass(getClassName);
|
||||
if (classData == null) {
|
||||
System.out.printf("Could not load main class %s\n",className);
|
||||
System.out.printf("Could not load main class %s\n",getClassName);
|
||||
System.exit(1);
|
||||
}
|
||||
for (byte b:classData
|
||||
@ -69,10 +72,10 @@ public class Jvm {
|
||||
/* ch03
|
||||
ClassPath cp = new ClassPath();
|
||||
cp.parse(cmd.jreOption, cmd.cpOption);
|
||||
String className = cmd.className.replace(".", "/").concat(".class");
|
||||
ClassFile classFile = new ClassFile(cp.readClass(className));
|
||||
String getClassName = cmd.getClassName.replace(".", "/").concat(".class");
|
||||
ClassFile classFile = new ClassFile(cp.readClass(getClassName));
|
||||
classFile.read();
|
||||
System.out.println(cmd.className);
|
||||
System.out.println(cmd.getClassName);
|
||||
printClassInfo(classFile);
|
||||
}
|
||||
|
||||
@ -95,24 +98,48 @@ public class Jvm {
|
||||
}
|
||||
*/
|
||||
|
||||
/* ch04
|
||||
// ch04
|
||||
/*
|
||||
Frame frame = new Frame(100, 100);
|
||||
testLocalVars(frame.getLocalVars());
|
||||
testOperandStack(frame.getOperandStack());
|
||||
*/
|
||||
|
||||
//ch05
|
||||
|
||||
// Interpreter interpreter = new Interpreter();
|
||||
// ClassPath cp = new ClassPath();
|
||||
// cp.parse(cmd.jreOption, cmd.cpOption);
|
||||
// String className = cmd.className.replace(".", "/").concat(".class");
|
||||
// ClassFile classFile = loadClass(className, cp);
|
||||
// classFile.read();
|
||||
// MemberInfo mainMethod = getMainMethod(classFile);
|
||||
// if (mainMethod != null) {
|
||||
// interpreter.doInterpreter(mainMethod);
|
||||
// } else {
|
||||
// System.out.printf("Main method not found in class %s\n", className);
|
||||
// }
|
||||
|
||||
|
||||
Interpreter interpreter = new Interpreter();
|
||||
ClassPath cp = new ClassPath();
|
||||
|
||||
ClassLoader classLoader = new ClassLoader(cp);
|
||||
cp.parse(cmd.jreOption, cmd.cpOption);
|
||||
String className = cmd.className.replace(".", "/").concat(".class");
|
||||
ClassFile classFile = loadClass(className, cp);
|
||||
classFile.read();
|
||||
MemberInfo mainMethod = getMainMethod(classFile);
|
||||
// String className = cmd.className.replace(".", "/").concat(".class");
|
||||
String className = cmd.className;
|
||||
ClassStruct mainClass = classLoader.loadClass(className);
|
||||
Method mainMethod = mainClass.getMainMethod();
|
||||
// ClassFile classFile = loadClass(className, cp);
|
||||
// classFile.read();
|
||||
// MemberInfo mainMethod = getMainMethod(classFile);
|
||||
if (mainMethod != null) {
|
||||
interpreter.doInterpreter(mainMethod);
|
||||
} else {
|
||||
System.out.printf("Main method not found in class %s\n", className);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static MemberInfo getMainMethod(ClassFile classFile) {
|
||||
|
||||
@ -33,30 +33,30 @@ package com.gabongao.jvm.classfile;
|
||||
* Created by Imgaojp on 2017/2/18.
|
||||
*/
|
||||
public class ClassFile {
|
||||
static final int CONSTANT_Class = 7;
|
||||
static final int CONSTANT_Fieldref = 9;
|
||||
static final int CONSTANT_Methodref = 10;
|
||||
static final int CONSTANT_InterfaceMethodref = 11;
|
||||
static final int CONSTANT_String = 8;
|
||||
static final int CONSTANT_Integer = 3;
|
||||
static final int CONSTANT_Float = 4;
|
||||
static final int CONSTANT_Long = 5;
|
||||
static final int CONSTANT_Double = 6;
|
||||
static final int CONSTANT_NameAndType = 12;
|
||||
static final int CONSTANT_Utf8 = 1;
|
||||
static final int CONSTANT_MethodHandle = 15;
|
||||
static final int CONSTANT_MethodType = 16;
|
||||
static final int CONSTANT_InvokeDynamic = 18;
|
||||
char majorVersion;
|
||||
ConstantPool constantPool;
|
||||
char accessFlags;
|
||||
char thisClass;
|
||||
char superClass;
|
||||
char[] interfaces;
|
||||
MemberInfo[] fields;
|
||||
MemberInfo[] methods;
|
||||
AttributeInfo[] attributes;
|
||||
ClassReader classReader;
|
||||
private static final int CONSTANT_Class = 7;
|
||||
private static final int CONSTANT_Fieldref = 9;
|
||||
private static final int CONSTANT_Methodref = 10;
|
||||
private static final int CONSTANT_InterfaceMethodref = 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_NameAndType = 12;
|
||||
private static final int CONSTANT_Utf8 = 1;
|
||||
private char majorVersion;
|
||||
private ConstantPool constantPool;
|
||||
private char accessFlags;
|
||||
private char thisClass;
|
||||
private char superClass;
|
||||
private char[] interfaces;
|
||||
private MemberInfo[] fields;
|
||||
private MemberInfo[] methods;
|
||||
private AttributeInfo[] attributes;
|
||||
private ClassReader classReader;
|
||||
private char minorVersion;
|
||||
|
||||
public ClassFile(byte[] classData) {
|
||||
@ -107,6 +107,7 @@ public class ClassFile {
|
||||
public void read() {
|
||||
readAndCheckMagic();
|
||||
readAndCheckVersion();
|
||||
constantPool = new ConstantPool();
|
||||
constantPool = readConstantPool();
|
||||
accessFlags = classReader.readUint16();
|
||||
thisClass = classReader.readUint16();
|
||||
@ -136,16 +137,17 @@ public class ClassFile {
|
||||
|
||||
public ConstantPool readConstantPool() {
|
||||
int cpCount = classReader.readUint16();
|
||||
// constantPool.constantInfos = new ConstantInfo[cpCount];
|
||||
ConstantInfo[] constantInfos = new ConstantInfo[cpCount];
|
||||
// ConstantPool cp = new ConstantPool();
|
||||
for (int i = 1; i < cpCount; i++) {
|
||||
constantInfos[i] = readConstantInfo();
|
||||
if (constantInfos[i] instanceof ConstantLongInfo || constantInfos[i] instanceof ConstantDoubleInfo) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
ConstantPool cp = new ConstantPool();
|
||||
cp.setConstantInfos(constantInfos);
|
||||
return cp;
|
||||
constantPool.setConstantInfos(constantInfos);
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public ConstantInfo readConstantInfo() {
|
||||
@ -176,7 +178,7 @@ public class ClassFile {
|
||||
case CONSTANT_Methodref:
|
||||
return new ConstantMethodrefInfo(constantPool);
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
return new ConstantInterfaceMemberrefInfo(constantPool);
|
||||
return new ConstantInterfaceMethodrefInfo(constantPool);
|
||||
case CONSTANT_NameAndType:
|
||||
return new ConstantNameAndTypeInfo();
|
||||
// case CONSTANT_MethodType:
|
||||
@ -223,12 +225,16 @@ public class ClassFile {
|
||||
return "";
|
||||
}
|
||||
|
||||
//todo:return null
|
||||
public String[] interfaceNames() {
|
||||
String[] interfaceNames = new String[interfaces.length];
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
interfaceNames[i] = constantPool.getClassName(interfaces[i]);
|
||||
if ((interfaces != null)) {
|
||||
String[] interfaceNames = new String[interfaces.length];
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
interfaceNames[i] = constantPool.getClassName(interfaces[i]);
|
||||
}
|
||||
return interfaceNames;
|
||||
}
|
||||
return interfaceNames;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -32,8 +32,8 @@ package com.gabongao.jvm.classfile;
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/18.
|
||||
*/
|
||||
public class ConstantInterfaceMemberrefInfo extends ConstantMemberrefInfo {
|
||||
public ConstantInterfaceMemberrefInfo(ConstantPool constantPool) {
|
||||
public class ConstantInterfaceMethodrefInfo extends ConstantMemberrefInfo {
|
||||
public ConstantInterfaceMethodrefInfo(ConstantPool constantPool) {
|
||||
super(constantPool);
|
||||
}
|
||||
}
|
||||
@ -50,7 +50,7 @@ public class ConstantMemberrefInfo extends ConstantInfo {
|
||||
nameAndTypeIndex = classReader.readUint16();
|
||||
}
|
||||
|
||||
public String className() {
|
||||
public String getClassName() {
|
||||
return constantPool.getClassName(classIndex);
|
||||
}
|
||||
|
||||
|
||||
@ -46,6 +46,16 @@ public class MemberInfo {
|
||||
this.attributes = ClassFile.readAttributes(classReader, cp);
|
||||
}
|
||||
|
||||
public AttrConstantValue getConstantValueAttribute() {
|
||||
for (AttributeInfo attr : attributes
|
||||
) {
|
||||
if (attr instanceof AttrConstantValue) {
|
||||
return (AttrConstantValue) attr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttrCode getCodeAttribure() {
|
||||
for (AttributeInfo attr : attributes
|
||||
) {
|
||||
|
||||
@ -39,6 +39,8 @@ public class ClassPath {
|
||||
}
|
||||
|
||||
public byte[] readClass(String className) {
|
||||
|
||||
className = className.concat(".class");
|
||||
byte[] bytes = bootClasspath.readClass(className);
|
||||
if ( bytes!= null) {
|
||||
return bytes;
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
package com.gabongao.jvm.instructions;
|
||||
|
||||
import com.gabongao.jvm.rtda.Frame;
|
||||
import com.gabongao.jvm.rtda.Object;
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
import com.gabongao.jvm.rtda.OperandStack;
|
||||
|
||||
/**
|
||||
@ -48,7 +48,6 @@ public class BranchInstruction implements Instruction {
|
||||
public void execute(Frame frame) {
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public void branch(Frame frame, int offset) {
|
||||
int pc = frame.getThread().getPc();
|
||||
|
||||
@ -37,6 +37,7 @@ public class Factory {
|
||||
static OperandsInstruction operandsInstruction = new OperandsInstruction();
|
||||
static BranchInstruction branchInstruction = new BranchInstruction();
|
||||
static Index8Instruction index8Instruction = new Index8Instruction();
|
||||
static Index16Instruction index16Instruction = new Index16Instruction();
|
||||
|
||||
public static Instruction newInstruction(byte opcode) {
|
||||
switch (Byte.toUnsignedInt(opcode)) {
|
||||
@ -76,12 +77,12 @@ public class Factory {
|
||||
return operandsInstruction.new Bipush();
|
||||
case 0x11:
|
||||
return operandsInstruction.new Sipush();
|
||||
//case 0x12:
|
||||
// return &LDC{}
|
||||
//case 0x13:
|
||||
// return &LDC_W{}
|
||||
//case 0x14:
|
||||
// return &LDC2_W{}
|
||||
case 0x12:
|
||||
return index8Instruction.new Ldc();
|
||||
case 0x13:
|
||||
return index8Instruction.new Ldc().new Ldc_W();
|
||||
case 0x14:
|
||||
return index8Instruction.new Ldc().new Ldc2_W();
|
||||
case 0x15:
|
||||
return index8Instruction.new Iload();
|
||||
case 0x16:
|
||||
@ -403,26 +404,26 @@ public class Factory {
|
||||
// return areturn
|
||||
// case 0xb1:
|
||||
// return _return
|
||||
//case 0xb2:
|
||||
// return &GET_STATIC{}
|
||||
//case 0xb3:
|
||||
// return &PUT_STATIC{}
|
||||
//case 0xb4:
|
||||
// return &GET_FIELD{}
|
||||
//case 0xb5:
|
||||
// return &PUT_FIELD{}
|
||||
//case 0xb6:
|
||||
// return &INVOKE_VIRTUAL{}
|
||||
//case 0xb7:
|
||||
// return &INVOKE_SPECIAL{}
|
||||
case 0xb2:
|
||||
return index16Instruction.new GetStatic();
|
||||
case 0xb3:
|
||||
return index16Instruction.new PutStatic();
|
||||
case 0xb4:
|
||||
return index16Instruction.new GetField();
|
||||
case 0xb5:
|
||||
return index16Instruction.new PutField();
|
||||
case 0xb6:
|
||||
return index16Instruction.new InvokeVirtual();
|
||||
case 0xb7:
|
||||
return index16Instruction.new InvokeSpecial();
|
||||
//case 0xb8:
|
||||
// return &INVOKE_STATIC{}
|
||||
//case 0xb9:
|
||||
// return &INVOKE_INTERFACE{}
|
||||
//case 0xba:
|
||||
// return &INVOKE_DYNAMIC{}
|
||||
//case 0xbb:
|
||||
// return &NEW{}
|
||||
case 0xbb:
|
||||
return index16Instruction.new New();
|
||||
//case 0xbc:
|
||||
// return &NEW_ARRAY{}
|
||||
//case 0xbd:
|
||||
@ -431,10 +432,10 @@ public class Factory {
|
||||
// return arraylength
|
||||
//case 0xbf:
|
||||
// return athrow
|
||||
//case 0xc0:
|
||||
// return &CHECK_CAST{}
|
||||
//case 0xc1:
|
||||
// return &INSTANCE_OF{}
|
||||
case 0xc0:
|
||||
return index16Instruction.new CheckCast();
|
||||
case 0xc1:
|
||||
return index16Instruction.new InstanceOf();
|
||||
//case 0xc2:
|
||||
// return monitorenter
|
||||
//case 0xc3:
|
||||
@ -461,6 +462,5 @@ public class Factory {
|
||||
default:
|
||||
throw new RuntimeException(String.format("Bad opcode: 0X%X", opcode));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,11 @@
|
||||
|
||||
package com.gabongao.jvm.instructions;
|
||||
|
||||
import com.gabongao.jvm.rtda.Frame;
|
||||
import com.gabongao.jvm.rtda.OperandStack;
|
||||
import com.gabongao.jvm.rtda.heap.*;
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
@ -32,11 +37,323 @@ package com.gabongao.jvm.instructions;
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/18.
|
||||
*/
|
||||
public abstract class Index16Instruction implements Instruction {
|
||||
private char Index;
|
||||
public class Index16Instruction implements Instruction {
|
||||
protected char index;
|
||||
|
||||
@Override
|
||||
public void fetchOperands(BytecodeReader bytecodeReader) {
|
||||
Index = bytecodeReader.readUint16();
|
||||
index = bytecodeReader.readUint16();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
}
|
||||
|
||||
public class New extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
ClassRef classRef = (ClassRef) cp.getConstant(index).getObject();
|
||||
ClassStruct classStruct = classRef.resolvedClass();
|
||||
|
||||
if (classStruct.IsInterface() || classStruct.IsAbstract()) {
|
||||
throw new RuntimeException("InstantiationError");
|
||||
}
|
||||
Object ref = classStruct.newObject();
|
||||
frame.getOperandStack().pushRef(ref);
|
||||
}
|
||||
|
||||
//todo: index传值失败,父类的index为private,子类不能访问父类的值,因此默认初始值0.
|
||||
@Override
|
||||
public void fetchOperands(BytecodeReader bytecodeReader) {
|
||||
super.fetchOperands(bytecodeReader);
|
||||
}
|
||||
}
|
||||
|
||||
public class PutStatic extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Method currentMethod = frame.getMethod();
|
||||
ClassStruct currentClass = currentMethod.getClassMember().getClassStruct();
|
||||
ConstantPool cp = currentClass.getConstantPool();
|
||||
FieldRef fieldRef = (FieldRef) cp.getConstant(index).getObject();
|
||||
Field field = fieldRef.resolvedField();
|
||||
ClassStruct classStruct = field.getClassStruct();
|
||||
if (!field.IsStatic()) {
|
||||
throw new RuntimeException("IncompatibleClassChangeError");
|
||||
}
|
||||
if (field.IsFinal()) {
|
||||
if (currentClass != classStruct || !currentMethod.getClassMember().getName().equals("<clinit>")) {
|
||||
throw new RuntimeException("IllegalAccessError");
|
||||
}
|
||||
}
|
||||
String descriptor = field.getDescriptor();
|
||||
int slotId = field.getSlotId();
|
||||
Slots slots = classStruct.getStaticVars();
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
char[] des = descriptor.toCharArray();
|
||||
switch (des[0]) {
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'I':
|
||||
slots.setInt(slotId, operandStack.popInt());
|
||||
break;
|
||||
case 'F':
|
||||
slots.setFloat(slotId, operandStack.popFloat());
|
||||
break;
|
||||
case 'J':
|
||||
slots.setLong(slotId, operandStack.popLong());
|
||||
break;
|
||||
case 'D':
|
||||
slots.setDouble(slotId, operandStack.popDouble());
|
||||
break;
|
||||
case 'L':
|
||||
case '[':
|
||||
slots.setRef(slotId, operandStack.popRef());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GetStatic extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
FieldRef fieldRef = (FieldRef) cp.getConstant(index).getObject();
|
||||
Field field = fieldRef.resolvedField();
|
||||
ClassStruct classStruct = field.getClassStruct();
|
||||
if (!field.IsStatic()) {
|
||||
throw new RuntimeException("IncompatibleClassChangeError");
|
||||
}
|
||||
String descriptor = field.getDescriptor();
|
||||
int slotId = field.getSlotId();
|
||||
Slots slots = classStruct.getStaticVars();
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
char[] des = descriptor.toCharArray();
|
||||
switch (des[0]) {
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'I':
|
||||
operandStack.pushInt(slots.getInt(slotId));
|
||||
break;
|
||||
case 'F':
|
||||
operandStack.pushFloat(slots.getFloat(slotId));
|
||||
break;
|
||||
case 'J':
|
||||
operandStack.pushLong(slots.getLong(slotId));
|
||||
break;
|
||||
case 'D':
|
||||
operandStack.pushDouble(slots.getDouble(slotId));
|
||||
break;
|
||||
case 'L':
|
||||
case '[':
|
||||
operandStack.pushRef(slots.getRef(slotId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PutField extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
Method currentMethod = frame.getMethod();
|
||||
ClassStruct currentClass = currentMethod.getClassMember().getClassStruct();
|
||||
ConstantPool cp = currentClass.getConstantPool();
|
||||
FieldRef fieldRef = (FieldRef) cp.getConstant(index).getObject();
|
||||
Field field = fieldRef.resolvedField();
|
||||
if (field.IsStatic()) {
|
||||
throw new RuntimeException("IncompatibleClassChangeError");
|
||||
}
|
||||
if (field.IsFinal()) {
|
||||
if (currentClass != field.getClassStruct() || !currentMethod.getClassMember().getName().equals("<init>")) {
|
||||
throw new RuntimeException("IllegalAccessError");
|
||||
}
|
||||
}
|
||||
String descriptor = field.getDescriptor();
|
||||
int slotId = field.getSlotId();
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
char[] des = descriptor.toCharArray();
|
||||
switch (des[0]) {
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'I':
|
||||
int vali = operandStack.popInt();
|
||||
Object refi = operandStack.popRef();
|
||||
if (refi == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
refi.getFields().setInt(slotId, vali);
|
||||
break;
|
||||
case 'F':
|
||||
float valf = operandStack.popFloat();
|
||||
Object reff = operandStack.popRef();
|
||||
if (reff == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
reff.getFields().setFloat(slotId, valf);
|
||||
break;
|
||||
case 'J':
|
||||
long vall = operandStack.popLong();
|
||||
Object refl = operandStack.popRef();
|
||||
if (refl == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
refl.getFields().setLong(slotId, vall);
|
||||
break;
|
||||
case 'D':
|
||||
double vald = operandStack.popDouble();
|
||||
Object refd = operandStack.popRef();
|
||||
if (refd == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
refd.getFields().setDouble(slotId, vald);
|
||||
break;
|
||||
case 'L':
|
||||
case '[':
|
||||
Object valr = operandStack.popRef();
|
||||
Object ref = operandStack.popRef();
|
||||
if (ref == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
ref.getFields().setRef(slotId, valr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GetField extends Index16Instruction {
|
||||
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
FieldRef fieldRef = (FieldRef) cp.getConstant(index).getObject();
|
||||
Field field = fieldRef.resolvedField();
|
||||
if (field.IsStatic()) {
|
||||
throw new RuntimeException("IncompatibleClassChangeError");
|
||||
}
|
||||
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
Object ref = operandStack.popRef();
|
||||
if (ref == null) {
|
||||
throw new RuntimeException("NullPointerException");
|
||||
}
|
||||
String descriptor = field.getDescriptor();
|
||||
int slotId = field.getSlotId();
|
||||
Slots slots = ref.getFields();
|
||||
char[] des = descriptor.toCharArray();
|
||||
|
||||
switch (des[0]) {
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'S':
|
||||
case 'I':
|
||||
operandStack.pushInt(slots.getInt(slotId));
|
||||
break;
|
||||
case 'F':
|
||||
operandStack.pushFloat(slots.getFloat(slotId));
|
||||
break;
|
||||
case 'J':
|
||||
operandStack.pushLong(slots.getLong(slotId));
|
||||
break;
|
||||
case 'D':
|
||||
operandStack.pushDouble(slots.getDouble(slotId));
|
||||
break;
|
||||
case 'L':
|
||||
case '[':
|
||||
operandStack.pushRef(slots.getRef(slotId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InstanceOf extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
Object ref = operandStack.popRef();
|
||||
if (ref == null) {
|
||||
operandStack.pushInt(0);
|
||||
}
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
ClassRef classRef = (ClassRef) cp.getConstant(index).getObject();
|
||||
ClassStruct classStruct = classRef.resolvedClass();
|
||||
if (ref.isInstanceOf(classStruct)) {
|
||||
operandStack.pushInt(1);
|
||||
} else {
|
||||
operandStack.pushInt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CheckCast extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
Object ref = operandStack.popRef();
|
||||
operandStack.pushRef(ref);
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
ClassRef classRef = (ClassRef) cp.getConstant(index).getObject();
|
||||
ClassStruct classStruct = classRef.resolvedClass();
|
||||
if (!ref.isInstanceOf(classStruct)) {
|
||||
throw new RuntimeException("ClassCastException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class InvokeSpecial extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
frame.getOperandStack().popRef();
|
||||
}
|
||||
}
|
||||
|
||||
public class InvokeVirtual extends Index16Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
MethodRef methodRef = (MethodRef) cp.getConstant(index).getObject();
|
||||
if (methodRef.getName().equals("println")) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
switch (methodRef.getDescriptor()) {
|
||||
case "(Z)V":
|
||||
System.out.println(operandStack.popInt() != 0);
|
||||
break;
|
||||
case "(C)V":
|
||||
System.out.printf("%c\n", operandStack.popInt());
|
||||
break;
|
||||
case "(B)V":
|
||||
System.out.println(operandStack.popInt());
|
||||
break;
|
||||
case "(S)V":
|
||||
System.out.println(operandStack.popInt());
|
||||
break;
|
||||
case "(I)V":
|
||||
System.out.println(operandStack.popInt());
|
||||
break;
|
||||
case "(J)V":
|
||||
System.out.println(operandStack.popLong());
|
||||
break;
|
||||
case "(F)V":
|
||||
System.out.println(operandStack.popFloat());
|
||||
break;
|
||||
case "(D)V":
|
||||
System.out.println(operandStack.popDouble());
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("println:" + methodRef.getDescriptor());
|
||||
}
|
||||
operandStack.popRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,9 @@ package com.gabongao.jvm.instructions;
|
||||
|
||||
import com.gabongao.jvm.rtda.Frame;
|
||||
import com.gabongao.jvm.rtda.LocalVars;
|
||||
import com.gabongao.jvm.rtda.Object;
|
||||
import com.gabongao.jvm.rtda.OperandStack;
|
||||
import com.gabongao.jvm.rtda.heap.ConstantPool;
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
@ -685,4 +687,55 @@ public class Index8Instruction implements Instruction {
|
||||
localVars.setInt(super.getIndex(), localVars.getInt(super.getIndex()) + constVal);
|
||||
}
|
||||
}
|
||||
|
||||
public class Ldc extends Index8Instruction {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
_ldc(frame, super.getIndex());
|
||||
}
|
||||
|
||||
public void _ldc(Frame frame, int index) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
java.lang.Object c = cp.getConstant(index).getObject();
|
||||
if (c instanceof Integer) {
|
||||
operandStack.pushInt((int) c);
|
||||
} else if (c instanceof Float) {
|
||||
operandStack.pushFloat((float) c);
|
||||
} else {
|
||||
throw new RuntimeException("todo : ldc");
|
||||
} //todo
|
||||
}
|
||||
}
|
||||
|
||||
public class Ldc_W extends Ldc {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
super.execute(frame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchOperands(BytecodeReader bytecodeReader) {
|
||||
Index = bytecodeReader.readUint16();
|
||||
}
|
||||
}
|
||||
|
||||
public class Ldc2_W extends Ldc_W {
|
||||
@Override
|
||||
public void execute(Frame frame) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
ConstantPool cp = frame.getMethod().getClassMember().getClassStruct().getConstantPool();
|
||||
java.lang.Object c = cp.getConstant(Index).getObject();
|
||||
if (c instanceof Long) {
|
||||
operandStack.pushLong((long) c);
|
||||
} else if (c instanceof Double) {
|
||||
operandStack.pushDouble((double) c);
|
||||
} else {
|
||||
throw new RuntimeException("ClassFormatError");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -42,7 +42,6 @@ import sun.awt.OSInfo;
|
||||
public class OperandsInstruction implements Instruction {
|
||||
@Override
|
||||
public void fetchOperands(BytecodeReader bytecodeReader) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void execute(Frame frame) {
|
||||
@ -294,9 +293,15 @@ public class OperandsInstruction implements Instruction {
|
||||
public void execute(Frame frame) {
|
||||
OperandStack operandStack = frame.getOperandStack();
|
||||
Slot slot = operandStack.popSlot();
|
||||
Slot slot1 = slot.copySlot();
|
||||
operandStack.pushSlot(slot);
|
||||
operandStack.pushSlot(slot);
|
||||
operandStack.pushSlot(slot1);
|
||||
}
|
||||
|
||||
//todo:dup 指令传入两个相同的引用,要先拷贝一份。
|
||||
// Slot slot = operandStack.popSlot();
|
||||
// operandStack.pushSlot(slot);
|
||||
// operandStack.pushSlot(slot);
|
||||
}
|
||||
|
||||
public class Dup_X1 extends OperandsInstruction {
|
||||
@ -307,7 +312,7 @@ public class OperandsInstruction implements Instruction {
|
||||
Slot slot2 = operandStack.popSlot();
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot1.copySlot());
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,7 +326,7 @@ public class OperandsInstruction implements Instruction {
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot3);
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot1.copySlot());
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +339,7 @@ public class OperandsInstruction implements Instruction {
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot1.copySlot());
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,8 +353,8 @@ public class OperandsInstruction implements Instruction {
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot3);
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot2.copySlot());
|
||||
operandStack.pushSlot(slot1.copySlot());
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,8 +370,8 @@ public class OperandsInstruction implements Instruction {
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot4);
|
||||
operandStack.pushSlot(slot3);
|
||||
operandStack.pushSlot(slot2);
|
||||
operandStack.pushSlot(slot1);
|
||||
operandStack.pushSlot(slot2.copySlot());
|
||||
operandStack.pushSlot(slot1.copySlot());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
package com.gabongao.jvm.rtda;
|
||||
|
||||
import com.gabongao.jvm.rtda.heap.Method;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
@ -37,6 +39,7 @@ public class Frame {
|
||||
private LocalVars localVars;
|
||||
private OperandStack operandStack;
|
||||
private Thread thread;
|
||||
private Method method;
|
||||
private int nextPc;
|
||||
|
||||
public Frame(Thread thread, int maxLocals, int maxStack) {
|
||||
@ -45,6 +48,17 @@ public class Frame {
|
||||
operandStack = new OperandStack(maxStack);
|
||||
}
|
||||
|
||||
public Frame(Thread thread, Method method) {
|
||||
this.thread = thread;
|
||||
this.method = method;
|
||||
this.localVars = new LocalVars(method.getMaxLocals());
|
||||
this.operandStack = new OperandStack(method.getMaxStack());
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public LocalVars getLocalVars() {
|
||||
return localVars;
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
package com.gabongao.jvm.rtda;
|
||||
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@ -37,16 +39,19 @@ import java.util.Arrays;
|
||||
public class LocalVars {
|
||||
private Slot[] slots;
|
||||
|
||||
LocalVars(int maxLocals) {
|
||||
if (maxLocals > 0) {
|
||||
public LocalVars(int maxLocals) {
|
||||
if (maxLocals >= 0) {
|
||||
slots = new Slot[maxLocals];
|
||||
for (int i = 0; i < maxLocals; i++) {
|
||||
slots[i] = new Slot();
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("LocalVars Count Error");
|
||||
}
|
||||
}
|
||||
|
||||
public void setInt(int index, int val) {
|
||||
slots[index] = new Slot();
|
||||
// slots[index] = new Slot();
|
||||
slots[index].setNum(val);
|
||||
}
|
||||
|
||||
@ -55,7 +60,7 @@ public class LocalVars {
|
||||
}
|
||||
|
||||
public void setFloat(int index, float val) {
|
||||
slots[index] = new Slot();
|
||||
// slots[index] = new Slot();
|
||||
slots[index].setNum(Float.floatToRawIntBits(val));
|
||||
}
|
||||
|
||||
@ -64,7 +69,7 @@ public class LocalVars {
|
||||
}
|
||||
|
||||
public void setLong(int index, long val) {
|
||||
slots[index] = new Slot();
|
||||
// slots[index] = new Slot();
|
||||
slots[index].setNum((int) val);
|
||||
slots[index + 1] = new Slot();
|
||||
slots[index + 1].setNum((int) (val >> 32));
|
||||
@ -77,7 +82,7 @@ public class LocalVars {
|
||||
}
|
||||
|
||||
public void setRef(int index, Object ref) {
|
||||
slots[index] = new Slot();
|
||||
// slots[index] = new Slot();
|
||||
slots[index].setRef(ref);
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
package com.gabongao.jvm.rtda;
|
||||
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@ -41,6 +43,9 @@ public class OperandStack {
|
||||
public OperandStack(int maxStacks) {
|
||||
if (maxStacks > 0) {
|
||||
slots = new Slot[maxStacks];
|
||||
for (int i = 0; i < maxStacks; i++) {
|
||||
slots[i] = new Slot();
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Operands Count Error");
|
||||
}
|
||||
@ -55,7 +60,7 @@ public class OperandStack {
|
||||
}
|
||||
|
||||
public void pushInt(int val) {
|
||||
slots[size] = new Slot();
|
||||
// slots[size] = new Slot();
|
||||
slots[size].setNum(val);
|
||||
size++;
|
||||
}
|
||||
@ -66,7 +71,7 @@ public class OperandStack {
|
||||
}
|
||||
|
||||
public void pushFloat(float val) {
|
||||
slots[size] = new Slot();
|
||||
// slots[size] = new Slot();
|
||||
slots[size].setNum(Float.floatToRawIntBits(val));
|
||||
size++;
|
||||
}
|
||||
@ -77,9 +82,9 @@ public class OperandStack {
|
||||
}
|
||||
|
||||
public void pushLong(long val) {
|
||||
slots[size] = new Slot();
|
||||
// slots[size] = new Slot();
|
||||
slots[size].setNum((int) val);
|
||||
slots[size + 1] = new Slot();
|
||||
// slots[size + 1] = new Slot();
|
||||
slots[size + 1].setNum((int) (val >> 32));
|
||||
size += 2;
|
||||
}
|
||||
@ -92,7 +97,7 @@ public class OperandStack {
|
||||
}
|
||||
|
||||
public void pushRef(Object ref) {
|
||||
slots[size] = new Slot();
|
||||
// slots[size] = new Slot();
|
||||
slots[size].setRef(ref);
|
||||
size++;
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
|
||||
package com.gabongao.jvm.rtda;
|
||||
|
||||
import com.gabongao.jvm.rtda.heap.Object;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
@ -36,6 +38,11 @@ public class Slot {
|
||||
private int num;
|
||||
private Object ref;
|
||||
|
||||
public Slot() {
|
||||
this.num = 0;
|
||||
this.ref = new Object();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Slot{" +
|
||||
@ -59,4 +66,12 @@ public class Slot {
|
||||
public void setRef(Object ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
public Slot copySlot() {
|
||||
Slot s = new Slot();
|
||||
s.setNum(this.getNum());
|
||||
s.setRef(this.getRef());
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
64
src/com/gabongao/jvm/rtda/heap/AccessFlags.java
Normal file
64
src/com/gabongao/jvm/rtda/heap/AccessFlags.java
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public enum AccessFlags {
|
||||
ACCESS_PUBLIC(0X0001), //class field method
|
||||
ACCESS_PRIVATE(0X0002), // field method
|
||||
ACCESS_PROTECTED(0X0004), // field method
|
||||
ACCESS_STATIC(0X0008), // field method
|
||||
ACCESS_FINAL(0X0010), //class field method
|
||||
ACCESS_SUPER(0X0020), //class
|
||||
ACCESS_SYNCHRONIZED(0X0020), // method
|
||||
ACCESS_VOLATILE(0X0040), // field
|
||||
ACCESS_BRIDGE(0X0040), // method
|
||||
ACCESS_TRANSIENT(0X0080), // field
|
||||
ACCESS_VARARGS(0X0080), // method
|
||||
ACCESS_NATIVE(0X0100), // method
|
||||
ACCESS_INTERFACE(0X0200), //class
|
||||
ACCESS_ABSTRACT(0X0400), //class method
|
||||
ACCESS_STRICT(0X0800), // method
|
||||
ACCESS_SYNTHETIC(0X1000), //class field method
|
||||
ACCESS_ANNOTATION(0X2000), //class
|
||||
ACCESS_ENUM(0X4000), //class field
|
||||
;
|
||||
private int value;
|
||||
|
||||
AccessFlags(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
191
src/com/gabongao/jvm/rtda/heap/ClassLoader.java
Normal file
191
src/com/gabongao/jvm/rtda/heap/ClassLoader.java
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ClassFile;
|
||||
import com.gabongao.jvm.classpath.ClassPath;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class ClassLoader {
|
||||
private ClassPath classPath;
|
||||
private HashMap<String, ClassStruct> classStructHashMap;
|
||||
|
||||
public ClassLoader(ClassPath classPath) {
|
||||
this.classPath = classPath;
|
||||
classStructHashMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public ClassStruct loadClass(String name) {
|
||||
ClassStruct classStruct = classStructHashMap.get(name);
|
||||
if (classStruct == null) {
|
||||
return loadNonArrayClass(name);
|
||||
}
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
private ClassStruct loadNonArrayClass(String name) {
|
||||
byte[] classData = classPath.readClass(name);
|
||||
ClassStruct classStruct = defineClass(classData);
|
||||
link(classStruct);
|
||||
System.out.printf("Loaded class %s \n", name);
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
private ClassStruct defineClass(byte[] classData) {
|
||||
ClassStruct classStruct = parseClass(classData);
|
||||
classStruct.setClassLoader(this);
|
||||
resolveSuperClass(classStruct);
|
||||
resolveInterfaces(classStruct);
|
||||
classStructHashMap.put(classStruct.getClassName(), classStruct);
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
private ClassStruct parseClass(byte[] classData) {
|
||||
ClassFile classFile = new ClassFile(classData);
|
||||
classFile.read();
|
||||
return new ClassStruct(classFile);
|
||||
}
|
||||
|
||||
private void resolveSuperClass(ClassStruct classStruct) {
|
||||
if (!classStruct.getClassName().equals("java/lang/Object")) {
|
||||
classStruct.setSuperClass(classStruct.getClassLoader().loadClass(classStruct.getSuperClassName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveInterfaces(ClassStruct classStruct) {
|
||||
int interfaceCount = classStruct.getInterfaceNames() == null ? 0 : classStruct.getInterfaceNames().length;
|
||||
if (interfaceCount > 0) {
|
||||
classStruct.setInterfaces(new ClassStruct[interfaceCount]);
|
||||
for (int i = 0; i < interfaceCount; i++) {
|
||||
classStruct.getInterfaces()[i] = classStruct.getClassLoader().loadClass(classStruct.getInterfaceNames()[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void link(ClassStruct classStruct) {
|
||||
verify(classStruct);
|
||||
prepare(classStruct);
|
||||
}
|
||||
|
||||
private void verify(ClassStruct classStruct) {
|
||||
//todo:verify class
|
||||
}
|
||||
|
||||
private void prepare(ClassStruct classStruct) {
|
||||
calcInstanceFieldSlotIds(classStruct);
|
||||
calcStaticFieldSlotIds(classStruct);
|
||||
allocAndInitStaticVars(classStruct);
|
||||
}
|
||||
|
||||
private void calcInstanceFieldSlotIds(ClassStruct classStruct) {
|
||||
int slotId = 0;
|
||||
if (classStruct.getSuperClassName() != null) {
|
||||
slotId = classStruct.getSuperClass() == null ? 0 : classStruct.getSuperClass().getInstanceSlotCount();
|
||||
}
|
||||
Field[] fields = classStruct.getFields();
|
||||
int len = fields.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!fields[i].IsStatic()) {
|
||||
fields[i].setSlotId(slotId);
|
||||
slotId++;
|
||||
if (fields[i].isLongOrDouble()) {
|
||||
slotId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
classStruct.setInstanceSlotCount(slotId);
|
||||
}
|
||||
|
||||
private void calcStaticFieldSlotIds(ClassStruct classStruct) {
|
||||
int slotId = 0;
|
||||
Field[] fields = classStruct.getFields();
|
||||
int len = fields.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (fields[i].IsStatic()) {
|
||||
fields[i].setSlotId(slotId);
|
||||
slotId++;
|
||||
if (fields[i].isLongOrDouble()) {
|
||||
slotId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
classStruct.setStaticSlotCount(slotId);
|
||||
}
|
||||
|
||||
private void allocAndInitStaticVars(ClassStruct classStruct) {
|
||||
classStruct.setStaticVars(new Slots(classStruct.getStaticSlotCount()));
|
||||
Field[] fields = classStruct.getFields();
|
||||
int len = fields.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (fields[i].IsStatic() && fields[i].IsFinal()) {
|
||||
initStaticFinalVar(classStruct, fields[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initStaticFinalVar(ClassStruct classStruct, Field field) {
|
||||
Slots slots = classStruct.getStaticVars();
|
||||
ConstantPool cp = classStruct.getConstantPool();
|
||||
int cpIndex = field.getConstValueIndex();
|
||||
int slotId = field.getSlotId();
|
||||
if (cpIndex > 0) {
|
||||
switch (field.getDescriptor()) {
|
||||
case "Z":
|
||||
case "B":
|
||||
case "C":
|
||||
case "S":
|
||||
case "I":
|
||||
int vali = (int) cp.getConstant(cpIndex).getObject();
|
||||
slots.setInt(slotId, vali);
|
||||
break;
|
||||
case "J":
|
||||
long vall = (Long) cp.getConstant(cpIndex).getObject();
|
||||
slots.setLong(slotId, vall);
|
||||
break;
|
||||
case "F":
|
||||
float valf = (Float) cp.getConstant(cpIndex).getObject();
|
||||
slots.setFloat(slotId, valf);
|
||||
break;
|
||||
case "D":
|
||||
double vald = (Double) cp.getConstant(cpIndex).getObject();
|
||||
slots.setDouble(cpIndex, vald);
|
||||
break;
|
||||
case "Ljava/lang/String;":
|
||||
throw new RuntimeException("todo");
|
||||
//todo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
119
src/com/gabongao/jvm/rtda/heap/ClassMember.java
Normal file
119
src/com/gabongao/jvm/rtda/heap/ClassMember.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.AttrConstantValue;
|
||||
import com.gabongao.jvm.classfile.MemberInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class ClassMember {
|
||||
protected char accessFlags;
|
||||
protected String name, descriptor;
|
||||
private ClassStruct classStruct;
|
||||
|
||||
public ClassMember(MemberInfo memberInfo) {
|
||||
this.accessFlags = memberInfo.getAccessFlags();
|
||||
this.name = memberInfo.getName();
|
||||
this.descriptor = memberInfo.getDescriptor();
|
||||
}
|
||||
|
||||
public boolean isAccessibleTo(ClassStruct d) {
|
||||
if (IsPublic()) {
|
||||
return true;
|
||||
}
|
||||
ClassStruct c = classStruct;
|
||||
if (IsProtected()) {
|
||||
return d.equals(c) || d.isSubClassOf(c) || c.getPackageName().equals(d.getPackageName());
|
||||
}
|
||||
if (!IsPrivate()) {
|
||||
return c.getPackageName().equals(d.getPackageName());
|
||||
}
|
||||
return d.equals(c);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public ClassStruct getClassStruct() {
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
public void setClassStruct(ClassStruct classStruct) {
|
||||
this.classStruct = classStruct;
|
||||
}
|
||||
|
||||
public char getAccessFlags() {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public boolean IsFinal() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_FINAL.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSynthetic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_SYNTHETIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsEnum() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_ENUM.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPublic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PUBLIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPrivate() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PRIVATE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsProtected() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PROTECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean IsStatic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_STATIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsVolatile() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_VOLATILE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsTransient() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_TRANSIENT.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
42
src/com/gabongao/jvm/rtda/heap/ClassRef.java
Normal file
42
src/com/gabongao/jvm/rtda/heap/ClassRef.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ConstantClassInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class ClassRef extends SymRef {
|
||||
public ClassRef(ConstantPool constantPool, ConstantClassInfo classInfo) {
|
||||
super(constantPool);
|
||||
setClassName(classInfo.getName());
|
||||
}
|
||||
}
|
||||
380
src/com/gabongao/jvm/rtda/heap/ClassStruct.java
Normal file
380
src/com/gabongao/jvm/rtda/heap/ClassStruct.java
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.*;
|
||||
|
||||
import java.lang.*;
|
||||
import java.lang.Object;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class ClassStruct {
|
||||
private char accessFlags;
|
||||
private String className, superClassName;
|
||||
private String[] interfaceNames;
|
||||
private ConstantPool constantPool;
|
||||
private Field[] fields;
|
||||
private Method[] methods;
|
||||
private ClassLoader classLoader;
|
||||
private ClassStruct superClass;
|
||||
private ClassStruct[] interfaces;
|
||||
private int instanceSlotCount, staticSlotCount;
|
||||
private Slots staticVars;
|
||||
|
||||
public ClassStruct(ClassFile classFile) {
|
||||
this.accessFlags = classFile.getAccessFlags();
|
||||
this.className = classFile.thisClassName();
|
||||
this.superClassName = classFile.superClassName();
|
||||
this.interfaceNames = classFile.interfaceNames();
|
||||
this.constantPool = newConstantPool(classFile.getConstantPool());
|
||||
this.fields = newFields(classFile.getFields());
|
||||
this.methods = newMethods(classFile.getMethods());
|
||||
}
|
||||
|
||||
public com.gabongao.jvm.rtda.heap.Object newObject() {
|
||||
return new com.gabongao.jvm.rtda.heap.Object(this);
|
||||
}
|
||||
|
||||
private ConstantPool newConstantPool(com.gabongao.jvm.classfile.ConstantPool cfCp) {
|
||||
int cpCount = cfCp.getConstantInfos().length;
|
||||
Constant[] constants = new Constant[cpCount];
|
||||
ConstantPool rtCp = new ConstantPool(this, constants);
|
||||
for (int i = 1; i < cpCount; i++) {
|
||||
ConstantInfo cpInfo = cfCp.getConstantInfos()[i];
|
||||
switch (cpInfo.getClass().getName()) {
|
||||
case "com.gabongao.jvm.classfile.ConstantIntegerInfo":
|
||||
ConstantIntegerInfo constantIntegerInfo = (ConstantIntegerInfo) cpInfo;
|
||||
constants[i] = new Constant(constantIntegerInfo.getVal());
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantLongInfo":
|
||||
ConstantLongInfo constantLongInfo = (ConstantLongInfo) cpInfo;
|
||||
constants[i] = new Constant(constantLongInfo.getVal());
|
||||
i++;
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantDoubleInfo":
|
||||
ConstantDoubleInfo constantDoubleInfo = (ConstantDoubleInfo) cpInfo;
|
||||
constants[i] = new Constant(constantDoubleInfo.getVal());
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantStringInfo":
|
||||
ConstantStringInfo constantStringInfo = (ConstantStringInfo) cpInfo;
|
||||
constants[i] = new Constant(constantStringInfo.getString());
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantClassInfo":
|
||||
ConstantClassInfo classInfo = (ConstantClassInfo) cpInfo;
|
||||
ClassRef classRef = new ClassRef(rtCp, classInfo);
|
||||
// classRef.setClassStruct(this);
|
||||
constants[i] = new Constant(classRef);
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantFieldrefInfo":
|
||||
ConstantFieldrefInfo fieldrefInfo = (ConstantFieldrefInfo) cpInfo;
|
||||
FieldRef ref = new FieldRef(rtCp, fieldrefInfo);
|
||||
// ref.setClassStruct(this);
|
||||
constants[i] = new Constant(ref);
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantMethodrefInfo":
|
||||
ConstantMethodrefInfo methodrefInfo = (ConstantMethodrefInfo) cpInfo;
|
||||
MethodRef methodRef = new MethodRef(rtCp, methodrefInfo);
|
||||
// methodRef.setClassStruct(this);
|
||||
constants[i] = new Constant(methodRef);
|
||||
break;
|
||||
case "com.gabongao.jvm.classfile.ConstantInterfaceMethodrefInfo":
|
||||
ConstantInterfaceMethodrefInfo interfaceMethodrefInfo = (ConstantInterfaceMethodrefInfo) cpInfo;
|
||||
InterfaceMethodRef interfaceMethodRef = new InterfaceMethodRef(rtCp, interfaceMethodrefInfo);
|
||||
// interfaceMethodRef.setClassStruct(this);
|
||||
constants[i] = new Constant(interfaceMethodRef);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rtCp;
|
||||
}
|
||||
|
||||
private Method[] newMethods(MemberInfo[] cfMethods) {
|
||||
Method[] methods = new Method[cfMethods.length];
|
||||
for (int i = 0; i < cfMethods.length; i++) {
|
||||
methods[i] = new Method(cfMethods[i]);
|
||||
methods[i].getClassMember().setClassStruct(this);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
private Field[] newFields(MemberInfo[] cfFields) {
|
||||
Field[] fields = new Field[cfFields.length];
|
||||
for (int i = 0; i < cfFields.length; i++) {
|
||||
fields[i] = new Field(cfFields[i]);
|
||||
fields[i].setClassStruct(this);
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
public boolean isAccessibleTo(ClassStruct other) {
|
||||
return this.IsPublic() || this.getPackageName().equals(other.getPackageName());
|
||||
}
|
||||
|
||||
public boolean isSubClassOf(ClassStruct other) {
|
||||
for (ClassStruct c = superClass; c != null; c = c.superClass) {
|
||||
if (c == other) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
int i = className.lastIndexOf("/");
|
||||
if (i >= 0) {
|
||||
return className.substring(0, i);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean IsPublic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PUBLIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsFinal() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_FINAL.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSuper() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_SUPER.getValue());
|
||||
}
|
||||
|
||||
public boolean IsInterface() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_INTERFACE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsAbstract() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_ABSTRACT.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSynthetic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_SYNTHETIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsAnnotation() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_ANNOTATION.getValue());
|
||||
}
|
||||
|
||||
public boolean IsEnum() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_ENUM.getValue());
|
||||
}
|
||||
|
||||
public char getAccessFlags() {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public void setAccessFlags(char accessFlags) {
|
||||
this.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public String getSuperClassName() {
|
||||
return superClassName;
|
||||
}
|
||||
|
||||
public void setSuperClassName(String superClassName) {
|
||||
this.superClassName = superClassName;
|
||||
}
|
||||
|
||||
public String[] getInterfaceNames() {
|
||||
return interfaceNames;
|
||||
}
|
||||
|
||||
public void setInterfaceNames(String[] interfaceNames) {
|
||||
this.interfaceNames = interfaceNames;
|
||||
}
|
||||
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public void setConstantPool(ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public Field[] getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void setFields(Field[] fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
public Method[] getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public void setMethods(Method[] methods) {
|
||||
this.methods = methods;
|
||||
}
|
||||
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public ClassStruct getSuperClass() {
|
||||
return superClass;
|
||||
}
|
||||
|
||||
public void setSuperClass(ClassStruct superClass) {
|
||||
this.superClass = superClass;
|
||||
}
|
||||
|
||||
public ClassStruct[] getInterfaces() {
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
public void setInterfaces(ClassStruct[] interfaces) {
|
||||
this.interfaces = interfaces;
|
||||
}
|
||||
|
||||
public int getInstanceSlotCount() {
|
||||
return instanceSlotCount;
|
||||
}
|
||||
|
||||
public void setInstanceSlotCount(int instanceSlotCount) {
|
||||
this.instanceSlotCount = instanceSlotCount;
|
||||
}
|
||||
|
||||
public int getStaticSlotCount() {
|
||||
return staticSlotCount;
|
||||
}
|
||||
|
||||
public void setStaticSlotCount(int staticSlotCount) {
|
||||
this.staticSlotCount = staticSlotCount;
|
||||
}
|
||||
|
||||
public Slots getStaticVars() {
|
||||
return staticVars;
|
||||
}
|
||||
|
||||
public void setStaticVars(Slots staticVars) {
|
||||
this.staticVars = staticVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ClassStruct)) return false;
|
||||
|
||||
ClassStruct that = (ClassStruct) o;
|
||||
|
||||
if (getAccessFlags() != that.getAccessFlags()) return false;
|
||||
if (getInstanceSlotCount() != that.getInstanceSlotCount()) return false;
|
||||
if (getStaticSlotCount() != that.getStaticSlotCount()) return false;
|
||||
if (!getClassName().equals(that.getClassName())) return false;
|
||||
if (!getSuperClassName().equals(that.getSuperClassName())) return false;
|
||||
if (!getConstantPool().equals(that.getConstantPool())) return false;
|
||||
if (!getClassLoader().equals(that.getClassLoader())) return false;
|
||||
if (!getSuperClass().equals(that.getSuperClass())) return false;
|
||||
return getStaticVars().equals(that.getStaticVars());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) getAccessFlags();
|
||||
result = 31 * result + (getClassName() != null ? getClassName().hashCode() : 0);
|
||||
result = 31 * result + (getSuperClassName() != null ? getSuperClassName().hashCode() : 0);
|
||||
result = 31 * result + Arrays.hashCode(getInterfaceNames());
|
||||
result = 31 * result + (getConstantPool() != null ? getConstantPool().hashCode() : 0);
|
||||
result = 31 * result + Arrays.hashCode(getFields());
|
||||
result = 31 * result + Arrays.hashCode(getMethods());
|
||||
result = 31 * result + (getClassLoader() != null ? getClassLoader().hashCode() : 0);
|
||||
result = 31 * result + (getSuperClass() != null ? getSuperClass().hashCode() : 0);
|
||||
result = 31 * result + Arrays.hashCode(getInterfaces());
|
||||
result = 31 * result + getInstanceSlotCount();
|
||||
result = 31 * result + getStaticSlotCount();
|
||||
result = 31 * result + (getStaticVars() != null ? getStaticVars().hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(ClassStruct other) {
|
||||
ClassStruct s = other;
|
||||
ClassStruct t = this;
|
||||
if (s.equals(t)) {
|
||||
return true;
|
||||
}
|
||||
if (!t.IsInterface()) {
|
||||
return s.isSubClassOf(t);
|
||||
} else {
|
||||
return s.isImplements(t);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isImplements(ClassStruct iface) {
|
||||
for (ClassStruct c = this.superClass; c != null; c = c.getSuperClass()) {
|
||||
for (ClassStruct cs : c.interfaces
|
||||
) {
|
||||
if (cs.equals(iface) || cs.isSubInterfaceOf(iface)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSubInterfaceOf(ClassStruct iface) {
|
||||
for (ClassStruct superInterface : this.interfaces
|
||||
) {
|
||||
if (superInterface.equals(iface) || superInterface.isSubInterfaceOf(iface)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Method getMainMethod() {
|
||||
return this.getStaticMethod("main", "([Ljava/lang/String;)V");
|
||||
}
|
||||
|
||||
public Method getStaticMethod(String name, String descriptor) {
|
||||
for (Method method : methods
|
||||
) {
|
||||
if (method.IsStatic() && method.getClassMember().getName().equals(name) && method.getClassMember().getDescriptor().equals(descriptor)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
48
src/com/gabongao/jvm/rtda/heap/Constant.java
Normal file
48
src/com/gabongao/jvm/rtda/heap/Constant.java
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import java.lang.*;
|
||||
import java.lang.Object;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class Constant {
|
||||
private java.lang.Object object;
|
||||
|
||||
public Constant(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
}
|
||||
55
src/com/gabongao/jvm/rtda/heap/ConstantPool.java
Normal file
55
src/com/gabongao/jvm/rtda/heap/ConstantPool.java
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class ConstantPool {
|
||||
private ClassStruct classStruct;
|
||||
private Constant[] constants;
|
||||
|
||||
ConstantPool(ClassStruct classStruct, Constant[] constants) {
|
||||
this.constants = constants;
|
||||
this.classStruct = classStruct;
|
||||
}
|
||||
|
||||
|
||||
public Constant getConstant(int index) {
|
||||
if (index >= constants.length) {
|
||||
throw new RuntimeException("getConstant Array out of bound");
|
||||
}
|
||||
return constants[index] == null ? null : constants[index];
|
||||
}
|
||||
|
||||
public ClassStruct getClassStruct() {
|
||||
return classStruct;
|
||||
}
|
||||
}
|
||||
110
src/com/gabongao/jvm/rtda/heap/Field.java
Normal file
110
src/com/gabongao/jvm/rtda/heap/Field.java
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.AttrConstantValue;
|
||||
import com.gabongao.jvm.classfile.MemberInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class Field extends ClassMember {
|
||||
private int slotId;
|
||||
private int constValueIndex;
|
||||
|
||||
public Field(MemberInfo memberInfo) {
|
||||
super(memberInfo);
|
||||
AttrConstantValue attr = memberInfo.getConstantValueAttribute();
|
||||
if (attr != null) {
|
||||
constValueIndex = attr.getConstantValueIndex();
|
||||
}
|
||||
}
|
||||
|
||||
public int getConstValueIndex() {
|
||||
return constValueIndex;
|
||||
}
|
||||
|
||||
public boolean IsFinal() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_FINAL.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSynthetic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_SYNTHETIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsEnum() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_ENUM.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPublic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PUBLIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPrivate() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PRIVATE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsProtected() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_PROTECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean IsStatic() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_STATIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsVolatile() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_VOLATILE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsTransient() {
|
||||
return 0 != (((int) accessFlags) & AccessFlags.ACCESS_TRANSIENT.getValue());
|
||||
}
|
||||
|
||||
|
||||
public char getAccessFlags() {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public void setAccessFlags(char accessFlags) {
|
||||
this.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
public int getSlotId() {
|
||||
return slotId;
|
||||
}
|
||||
|
||||
public void setSlotId(int slotId) {
|
||||
this.slotId = slotId;
|
||||
}
|
||||
|
||||
public boolean isLongOrDouble() {
|
||||
return descriptor.equals("J") || descriptor.equals("D");
|
||||
}
|
||||
}
|
||||
82
src/com/gabongao/jvm/rtda/heap/FieldRef.java
Normal file
82
src/com/gabongao/jvm/rtda/heap/FieldRef.java
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.*;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class FieldRef extends MemberRef {
|
||||
private Field field;
|
||||
|
||||
public FieldRef(ConstantPool constantPool, ConstantMemberrefInfo memberrefInfo) {
|
||||
super(constantPool, memberrefInfo);
|
||||
}
|
||||
|
||||
public Field resolvedField() {
|
||||
if (field == null) {
|
||||
resolveFieldRef();
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
public void resolveFieldRef() {
|
||||
ClassStruct d = constantPool.getClassStruct();
|
||||
ClassStruct c = resolvedClass();
|
||||
field = lookupField(c, name, descriptor);
|
||||
if (field == null) {
|
||||
throw new RuntimeException("NoSuchFieldError");
|
||||
}
|
||||
if (!field.isAccessibleTo(d)) {
|
||||
throw new RuntimeException("IllegalAccessError");
|
||||
}
|
||||
}
|
||||
|
||||
public Field lookupField(ClassStruct c, String name, String descriptor) {
|
||||
for (Field f : c.getFields()
|
||||
) {
|
||||
if (f.getName().equals(name) && f.descriptor.equals(descriptor)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
for (ClassStruct cs : c.getInterfaces()
|
||||
) {
|
||||
Field field = lookupField(cs, name, descriptor);
|
||||
if (field != null) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
if (c.getSuperClass() != null) {
|
||||
return lookupField(c.getSuperClass(), name, descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
43
src/com/gabongao/jvm/rtda/heap/InterfaceMethodRef.java
Normal file
43
src/com/gabongao/jvm/rtda/heap/InterfaceMethodRef.java
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ConstantMemberrefInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class InterfaceMethodRef extends MemberRef {
|
||||
private Method method;
|
||||
|
||||
public InterfaceMethodRef(ConstantPool constantPool, ConstantMemberrefInfo memberrefInfo) {
|
||||
super(constantPool, memberrefInfo);
|
||||
}
|
||||
}
|
||||
55
src/com/gabongao/jvm/rtda/heap/MemberRef.java
Normal file
55
src/com/gabongao/jvm/rtda/heap/MemberRef.java
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ConstantClassInfo;
|
||||
import com.gabongao.jvm.classfile.ConstantMemberrefInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class MemberRef extends SymRef {
|
||||
protected String name, descriptor;
|
||||
|
||||
public MemberRef(ConstantPool constantPool, ConstantMemberrefInfo memberrefInfo) {
|
||||
super(constantPool);
|
||||
super.setClassName(memberrefInfo.getClassName());
|
||||
name = memberrefInfo.nameAndDescriptor()[0];
|
||||
descriptor = memberrefInfo.nameAndDescriptor()[1];
|
||||
}
|
||||
|
||||
public String getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
138
src/com/gabongao/jvm/rtda/heap/Method.java
Normal file
138
src/com/gabongao/jvm/rtda/heap/Method.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.MemberInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class Method {
|
||||
ClassMember classMember;
|
||||
int maxStack, maxLocals;
|
||||
byte[] code;
|
||||
|
||||
Method(MemberInfo memberInfo) {
|
||||
classMember = new ClassMember(memberInfo);
|
||||
maxLocals = memberInfo.getCodeAttribure() == null ? 0 : memberInfo.getCodeAttribure().getMaxLocals();
|
||||
maxStack = memberInfo.getCodeAttribure() == null ? 0 : memberInfo.getCodeAttribure().getMaxStack();
|
||||
code = memberInfo.getCodeAttribure() == null ? null : memberInfo.getCodeAttribure().getCode();
|
||||
}
|
||||
|
||||
public ClassMember getClassMember() {
|
||||
return classMember;
|
||||
}
|
||||
|
||||
public void setClassMember(ClassMember classMember) {
|
||||
this.classMember = classMember;
|
||||
}
|
||||
|
||||
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 byte[] getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(byte[] code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean IsFinal() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_FINAL.getValue());
|
||||
}
|
||||
|
||||
public boolean IsAbstract() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_ABSTRACT.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSynthetic() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_SYNTHETIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPublic() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_PUBLIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsPrivate() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_PRIVATE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsProtected() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_PROTECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean IsStatic() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_STATIC.getValue());
|
||||
}
|
||||
|
||||
public boolean IsSynchronized() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_SYNCHRONIZED.getValue());
|
||||
}
|
||||
|
||||
public boolean IsBridge() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_BRIDGE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsVarargs() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_VARARGS.getValue());
|
||||
}
|
||||
|
||||
public boolean IsNative() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_NATIVE.getValue());
|
||||
}
|
||||
|
||||
public boolean IsStrict() {
|
||||
return 0 != (((int) classMember.accessFlags) & AccessFlags.ACCESS_STRICT.getValue());
|
||||
}
|
||||
|
||||
public char getAccessFlags() {
|
||||
return classMember.accessFlags;
|
||||
}
|
||||
|
||||
public void setAccessFlags(char accessFlags) {
|
||||
this.classMember.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
47
src/com/gabongao/jvm/rtda/heap/MethodRef.java
Normal file
47
src/com/gabongao/jvm/rtda/heap/MethodRef.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ConstantMemberrefInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class MethodRef extends MemberRef {
|
||||
private Method method;
|
||||
|
||||
public MethodRef(ConstantPool constantPool, ConstantMemberrefInfo memberrefInfo) {
|
||||
super(constantPool, memberrefInfo);
|
||||
}
|
||||
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
59
src/com/gabongao/jvm/rtda/heap/Object.java
Normal file
59
src/com/gabongao/jvm/rtda/heap/Object.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/18.
|
||||
*/
|
||||
public class Object {
|
||||
private ClassStruct classStruct;
|
||||
private Slots fields;
|
||||
//TODO
|
||||
|
||||
public Object() {
|
||||
}
|
||||
|
||||
public Object(ClassStruct classStruct) {
|
||||
this.classStruct = classStruct;
|
||||
this.fields = new Slots(classStruct.getInstanceSlotCount());
|
||||
}
|
||||
|
||||
public ClassStruct getClassStruct() {
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
public Slots getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public boolean isInstanceOf(ClassStruct classStruct) {
|
||||
return classStruct.isAssignableFrom(this.classStruct);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,9 @@
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda;
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.rtda.LocalVars;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
@ -30,8 +32,10 @@ package com.gabongao.jvm.rtda;
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/18.
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class Object {
|
||||
//TODO
|
||||
public class Slots extends LocalVars {
|
||||
public Slots(int slotCount) {
|
||||
super(slotCount);
|
||||
}
|
||||
}
|
||||
85
src/com/gabongao/jvm/rtda/heap/SymRef.java
Normal file
85
src/com/gabongao/jvm/rtda/heap/SymRef.java
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.gabongao.jvm.rtda.heap;
|
||||
|
||||
import com.gabongao.jvm.classfile.ConstantClassInfo;
|
||||
|
||||
/**
|
||||
* ┏┓ ┏┓+ +
|
||||
* ┏┛┻━━━┛┻┓ + +
|
||||
* ┃ ┃
|
||||
* ┃ ━ ┃ ++ + + +
|
||||
* ████━████ ┃+
|
||||
* ┃ ┃ +
|
||||
* ┃ ┻ ┃
|
||||
* ┃ ┃ + +
|
||||
* ┗━┓ ┏━┛
|
||||
* ┃ ┃
|
||||
* ┃ ┃ + + + +
|
||||
* ┃ ┃ Code is far away from bug with the animal protecting
|
||||
* ┃ ┃ + 神兽保佑,代码无bug
|
||||
* ┃ ┃
|
||||
* ┃ ┃ +
|
||||
* ┃ ┗━━━┓ + +
|
||||
* ┃ ┣┓
|
||||
* ┃ ┏┛
|
||||
* ┗┓┓┏━┳┓┏┛ + + + +
|
||||
* ┃┫┫ ┃┫┫
|
||||
* ┗┻┛ ┗┻┛+ + + +
|
||||
* Created by Imgaojp on 2017/2/20.
|
||||
*/
|
||||
public class SymRef {
|
||||
ConstantPool constantPool;
|
||||
String className;
|
||||
private ClassStruct classStruct;
|
||||
|
||||
public SymRef(ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public ConstantPool getConstantPool() {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
public void setConstantPool(ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public void setClassName(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public ClassStruct getClassStruct() {
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
public void setClassStruct(ClassStruct classStruct) {
|
||||
this.classStruct = classStruct;
|
||||
}
|
||||
|
||||
public ClassStruct resolvedClass() {
|
||||
if (this.classStruct == null) {
|
||||
resolvedClassRef();
|
||||
}
|
||||
return classStruct;
|
||||
}
|
||||
|
||||
public void resolvedClassRef() {
|
||||
ClassStruct d = constantPool.getClassStruct();
|
||||
ClassStruct c = d.getClassLoader().loadClass(className);
|
||||
if (!c.isAccessibleTo(d)) {
|
||||
throw new RuntimeException("java.lang.IllegalAccessError");
|
||||
}
|
||||
classStruct = c;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user