├── README.md ├── src └── myjvm │ ├── class_hash.h │ ├── constants.h │ ├── jvm.c │ ├── jvm.c.autosave │ ├── jvm_debug.h │ ├── main.c │ ├── method_table.h │ ├── my_types.h │ ├── myjvm.pro │ ├── myjvm.pro.user │ ├── op_core.h │ ├── opcode.c │ ├── opcode.h │ ├── opcode_actions.c │ ├── opcode_actions │ ├── op_cast.c │ ├── op_compare.c │ ├── op_const.c │ ├── op_control.c │ ├── op_extend.c │ ├── op_jump.c │ ├── op_load.c │ ├── op_math.c │ ├── op_obj.c │ ├── op_stack.c │ └── op_store.c │ ├── opcode_pre.c │ ├── parse_class.c │ ├── structs.h │ ├── test_jvm_types.c │ ├── utils.c │ └── utils.h └── test ├── A.class ├── Average.class ├── Average.code ├── Average.java ├── B.class ├── C.class ├── Child.class ├── Child.code ├── Child.java ├── D.class ├── Dance.class ├── Employee.class ├── Employee.java ├── Engineer.class ├── Engineer.java ├── Fibonacci.class ├── Fibonacci.java ├── Hello.class ├── Hello.java ├── HelloStatic.class ├── HelloStatic.java ├── IMath.class ├── IOUtil.class ├── IOUtil.code ├── IOUtil.java ├── Jazz.class ├── Latin.class ├── Manager.class ├── Manager.java ├── Parent.class ├── Parent.code ├── Parent.java ├── Point.class ├── Point.code ├── Point.java ├── TestAArray.class ├── TestAArray.java ├── TestArray.class ├── TestArray.java ├── TestInheritance.class ├── TestInheritance.code ├── TestInheritance.java ├── TestMultiAArray.class ├── TestMultiAArray.java ├── TestPoly.class ├── TestPoly.java ├── TestPoly2.java ├── TestPoly3.class ├── TestPoly3.java ├── TestStatic.class ├── TestStatic.java ├── TestString.class ├── TestString.code ├── TestString.java ├── TestSwitch.class └── TestSwitch.java /README.md: -------------------------------------------------------------------------------- 1 | # myjvm 2 | Writing a Simple Java Virtual Machine Step by Step 3 | 一步一步自制Java虚拟机(C语言版) 4 | 5 | ## Introduction 6 | 该项目的目的是从零开始用C语言做一个实验性质的Java虚拟机,实现大部分JVM指令,实现基本的面向对象特性(封装、继承、多态),能够运行一个不涉及Java本地方法调用的类(不能包含未实现的指令,见下面的指令实现情况),因为涉及到Java的本地方法(native method)还是比较麻烦的,暂时没有那么多时间精力去研究。 7 | 8 | ## 项目文件介绍 9 | 10 | * main.c 这是整个项目的入口文件。主要是加载需要运行的类,然后运行该类的main方法 11 | * jvm.c 实现虚拟机的基本框架(如指令执行循环、方法调用)。一些复杂的指令实现(`invokespecial`,`invokevirtual`,`invokestatic`)也在这里 12 | * parse_class.c 实现了把字节码文件解析成Class结构体,以及递归加载类 13 | * structs.h Class结构体中的各个数据类型的结构定义(如常量池中的各种结构、method_info、field_info) 14 | * constants.h 定义了一些常量,主要是访问控制标志、常量池种类 15 | * my_types.h 对C中的基本数据类型重新定义了个名字 16 | * utils.h 对读取文件做了个简单的封装(如读取一个字节(多个字节),读取一个short,读取一个int 17 | * op_core.h 该文件抽象地实现了JVM中的各种指令,简单的指令以宏的方式实现,复杂的以函数的方式。该文件很重要! 18 | * opcode.h 实现了指令中用到的一些方法,之所以不与op_core放在一起,是因为op_core过于庞大 19 | * opcode.c 主要是一个结构体数组,存放JVM指令的预处理函数及实现函数,数组的下标就是指令的opcode的十进制值 20 | * opcode_pre.c 方法区代码段的预处理函数集,主要是大小端转换 21 | * opcode_actions.c 该文件用include把opcode_actions目录中的文件包含进来,是指令实现的函数,每遇到一个指令,就调用相应的函数执行。 22 | * class_hash.h 简单地实现了一个HashTable结构类型和hash算法,用于保存已经加载并解析的字节码文件,rehash方法没有实现 23 | * test_jvm_types.c 一些测试用例,为了方便在不加载字节码文件的情况下测试代码而写 24 | 25 | * 其它: 26 | test目录下的`.java`文件是测试文件。 27 | 28 | ## 指令实现情况 29 | 30 | * constant系列指令(加载常量到当前操作数栈上),除`ldc`, `ldc_w`,`ldc2_w`这三条指令只实现了部分之外(字符串和对象部分没实现),其余均以实现 31 | * load系列指令(从局部变量表中加载数据到当前操作数栈上),全部实现 32 | * store系列指令(把当前操作数栈栈顶的数据保存到局部变量表),全部实现 33 | * stack系列指令(操作操作数栈的),全部实现 34 | * math系列指令(数学运算),全部实现 35 | * conversion(cast)系列指令(类型转换),全部实现 36 | * compare系列指令(比较跳转),全部实现 37 | * reference系列指令(主要是关于面向对象相关的指令),除`athrow`,`checkcast`,`instanceof`,`monitorenter`,`monitorexit`,`invokedynamic`,`invokeinterface`没有实现外,其余均已实现 38 | * control系列指令(控制转移指令),全部实现 39 | * extend系列指令,实现了`multianewarray`,`ifnull`,`ifnotnull`,`goto_w`指令 40 | * 保留指令,未实现 41 | 42 | ## 后话 43 |  该项目是用业余时间做的,在QT5.0下开发,原先只是想做个解析Java字节码的程序,后来灵感一来就越写越多。 44 | 45 | 由于时间精力有限,没有去好好组织项目结构,代码风格不是很好,请不要学习。 46 | 47 | 该项目对于学习C语言和想了解Java虚拟节的人来说还是都有很大帮助的。指令的实现中大量用到了宏,把运算符、变量类型作为参数传给宏,通过宏来定义类似的函数,省了很多代码。还有各种指针转换、函数指针的运用等,创建带有指向数组指针的结构体时,特意分配比结构体大的内存,然后让结构体中的成员指向剩余的内存,避免再次调用`malloc`,也减少了内存碎片。 48 | 49 | 对于想了解JVM的人而言,虽然商用JVM的类加载、指令的实现不一定是这样的,但至少可以从中大概知道JVM内部是什么个情况,加深对JVM的了解。 -------------------------------------------------------------------------------- /src/myjvm/class_hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef CLASS_HASH_H 10 | #define CLASS_HASH_H 11 | 12 | static int last_hash_size = 144; 13 | static int hash_size=233; 14 | 15 | typedef struct _classEntry { 16 | int name_len; 17 | char *class_name; 18 | Class* parent_class; 19 | Class* pclass; 20 | 21 | struct _classEntry *next; 22 | } ClassEntry; 23 | 24 | 25 | typedef struct _classHashTable { 26 | int class_num; 27 | int hash_size; 28 | int used_slots; 29 | ClassEntry **class_array; 30 | } ClassHashTable; 31 | 32 | static ClassHashTable *loadedClassTable; 33 | 34 | ClassHashTable* newClassHashTable(int size) 35 | { 36 | int total_size = sizeof(ClassHashTable)+(sizeof(ClassEntry*) * size); 37 | 38 | ClassHashTable *classTable = (ClassHashTable*)malloc(total_size); 39 | memset(classTable, 0, total_size); 40 | 41 | classTable->hash_size = size; 42 | classTable->class_array = (ClassEntry**)(classTable+1); 43 | 44 | return classTable; 45 | } 46 | 47 | void newLoadedClassTable() 48 | { 49 | loadedClassTable = newClassHashTable(hash_size); 50 | } 51 | 52 | unsigned int hash(const char* s, int hash_size) 53 | { 54 | unsigned long sum=0; 55 | while (*s) { 56 | sum = (sum<<1) + *s++; 57 | } 58 | return sum % hash_size; 59 | } 60 | Class* findLoadedClass(const char* class_name, const int class_name_len) 61 | { 62 | Class* pclass = NULL; 63 | ClassEntry* entry; 64 | unsigned int index = hash(class_name, hash_size); 65 | 66 | if (NULL == (entry = loadedClassTable->class_array[index])) { 67 | return pclass; 68 | } 69 | 70 | do { 71 | if (entry->name_len == class_name_len && strcmp(entry->class_name, class_name) == 0) { 72 | pclass = entry->pclass; 73 | break; 74 | } else { 75 | entry = entry->next; 76 | } 77 | } while(NULL != entry); 78 | 79 | return pclass; 80 | } 81 | 82 | int storeLoadedClass(Class* pclass) 83 | { 84 | int index; 85 | CONSTANT_Utf8_info* utf8_info; 86 | CONSTANT_Class_info* class_info; 87 | ClassEntry* entry; 88 | ClassEntry* thisClassEntry = (ClassEntry*)malloc(sizeof(ClassEntry)); 89 | class_info = (CONSTANT_Class_info*)(pclass->constant_pool[pclass->this_class]); 90 | utf8_info = (CONSTANT_Utf8_info*)(pclass->constant_pool[class_info->name_index]); 91 | thisClassEntry->name_len = utf8_info->length; 92 | thisClassEntry->class_name = utf8_info->bytes; 93 | thisClassEntry->pclass = pclass; 94 | thisClassEntry->next = NULL; 95 | 96 | index = hash(utf8_info->bytes, hash_size); 97 | if (NULL == loadedClassTable->class_array[index]) { 98 | loadedClassTable->class_array[index] = thisClassEntry; 99 | loadedClassTable->class_num++; 100 | loadedClassTable->used_slots++; 101 | return 0; 102 | } 103 | 104 | entry = loadedClassTable->class_array[index]; 105 | while (entry->next != NULL) { 106 | entry = entry->next; 107 | } 108 | entry->next = thisClassEntry; 109 | loadedClassTable->class_num++; 110 | 111 | return 0; 112 | } 113 | 114 | void displayLoadedClass() 115 | { 116 | int i = 0; 117 | ClassEntry* entry; 118 | 119 | printf("loadedClassTable: class_num=%d, hash_size=%d, used_slots=%d\n", loadedClassTable->class_num, loadedClassTable->hash_size, loadedClassTable->used_slots); 120 | 121 | for (; i < hash_size; i++) { 122 | if (loadedClassTable->class_array[i] != NULL) { 123 | printf("#%d ", i); 124 | entry = loadedClassTable->class_array[i]; 125 | while (entry != NULL) { 126 | printf("%s ", entry->class_name); 127 | entry = entry->next; 128 | } 129 | printf("\n"); 130 | } 131 | } 132 | } 133 | 134 | #endif // CLASS_HASH_H 135 | -------------------------------------------------------------------------------- /src/myjvm/constants.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef CONSTANTS_H 10 | #define CONSTANTS_H 11 | 12 | #include "my_types.h" 13 | 14 | #define CONSTANT_Utf8 1 15 | #define CONSTANT_Integer 3 16 | #define CONSTANT_Float 4 17 | #define CONSTANT_Long 5 18 | #define CONSTANT_Double 6 19 | #define CONSTANT_Class 7 20 | #define CONSTANT_String 8 21 | #define CONSTANT_Fieldref 9 22 | #define CONSTANT_Methodref 10 23 | #define CONSTANT_InterfaceMethodref 11 24 | #define CONSTANT_NameAndType 12 25 | #define CONSTANT_MethodHandle 15 26 | #define CONSTANT_MethodType 16 27 | #define CONSTANT_InvokeDynamic 18 28 | 29 | #define ACC_PUBLIC 0x0001 30 | #define ACC_PRIVATE 0x0002 31 | #define ACC_PROTECTED 0x0004 32 | #define ACC_STATIC 0x0008 33 | #define ACC_FINAL 0x0010 34 | #define ACC_SUPER 0x0020 35 | #define ACC_BRIDGE 0x0040 36 | #define ACC_VARARGS 0x0080 37 | #define ACC_NATIVE 0x0100 38 | #define ACC_INTERFACE 0x0200 39 | #define ACC_ABSTRACT 0x0400 40 | #define ACC_STRICT 0x0800 41 | #define ACC_SYNTHETIC 0x1000 42 | #define ACC_ANNOTATION 0x2000 43 | #define ACC_ENUM 0x4000 44 | 45 | #define IS_ACC_STATIC(flag) ((flag & ACC_STATIC) == ACC_STATIC) 46 | #define NOT_ACC_STATIC(flag) ((flag & ACC_STATIC) != ACC_STATIC) 47 | #define IS_ACC_NATIVE(flag) ((flag & ACC_NATIVE) == ACC_NATIVE) 48 | #define NOT_ACC_NATIVE(flag) ((flag & ACC_NATIVE) != ACC_NATIVE) 49 | 50 | char *cpTypeMap[] = { 51 | "None", // 0 52 | "Utf8", //1 53 | "None", // 2 54 | "Integer", // 3 55 | "Float", // 4 56 | "Long", // 5 57 | "Double", // 6 58 | "Class", // 7 59 | "String", // 8 60 | "Fieldref", // 9 61 | "Methodref", // 10 62 | "InterfaceMethodref", // 11 63 | "NameAndType", // 12 64 | "None", // 13 65 | "None", // 14 66 | "MethodHandle", // 15 67 | "MethodType", // 16 68 | "InvokeDynamic" // 17 69 | }; 70 | ushort accFlagInt[] = { 71 | ACC_PUBLIC, 72 | ACC_PRIVATE, 73 | ACC_PROTECTED, 74 | ACC_STATIC, 75 | ACC_FINAL, 76 | ACC_SUPER, 77 | ACC_BRIDGE, 78 | ACC_VARARGS, 79 | ACC_NATIVE, 80 | ACC_INTERFACE, 81 | ACC_ABSTRACT, 82 | ACC_STRICT, 83 | ACC_SYNTHETIC, 84 | ACC_ANNOTATION, 85 | ACC_ENUM 86 | }; 87 | char *accFlagMap[] = { 88 | "ACC_PUBLIC", 89 | "ACC_PRIVATE", 90 | "ACC_PROTECTED", 91 | "ACC_STATIC", 92 | "ACC_FINAL", 93 | "ACC_SUPER", 94 | "ACC_BRIDGE", 95 | "ACC_VARARGS", 96 | "ACC_NATIVE", 97 | "ACC_INTERFACE", 98 | "ACC_ABSTRACT", 99 | "ACC_STRICT", 100 | "ACC_SYNTHETIC", 101 | "ACC_ANNOTATION", 102 | "ACC_ENUM" 103 | }; 104 | 105 | char* formatAccessFlag(ushort accFlag) 106 | { 107 | char *accFlagStr = (char*)malloc(sizeof(char)*255); 108 | int i; 109 | int len = sizeof(accFlagInt)/sizeof(short int); 110 | memset(accFlagStr, 0, 255); 111 | 112 | for(i=0; i 2 | #include 3 | #include 4 | 5 | #include "parse_class.c" 6 | 7 | void displayStaticFields(Class *pclass); 8 | 9 | void runMethod(OPENV *env) 10 | { 11 | uchar op; 12 | Instruction instruction; 13 | do { 14 | op = *(env->pc); 15 | instruction = jvm_instructions[op]; 16 | printf("#%d: %s ", env->pc-env->pc_start, instruction.code_name); 17 | printCurrentClassMethod(env, instruction); 18 | 19 | env->pc=env->pc+1; 20 | instruction.action(env); 21 | printf("\n"); 22 | } while(1); 23 | } 24 | 25 | void internalRunClinitMethod(OPENV *env) 26 | { 27 | uchar op; 28 | Instruction instruction; 29 | do { 30 | op = *(env->pc); 31 | instruction = jvm_instructions[op]; 32 | printf("#%d: %s ", env->pc-env->pc_start, instruction.code_name); 33 | printCurrentClassMethod(env, instruction); 34 | 35 | env->pc=env->pc+1; 36 | instruction.action(env); 37 | displayStaticFields(env->current_class); 38 | printf("\n"); 39 | } while(env->pc <= env->pc_end && env->pc!=NULL); 40 | } 41 | 42 | method_info* findMainMethod(Class *pclass) 43 | { 44 | ushort index=0; 45 | while(index < pclass->methods_count) { 46 | if(IS_MAIN_METHOD(pclass, pclass->methods[index])){ 47 | break; 48 | } 49 | index++; 50 | } 51 | 52 | if (index == pclass->methods_count) { 53 | return NULL; 54 | } 55 | return pclass->methods[index]; 56 | } 57 | 58 | method_info* findClinitMethod(Class *pclass) 59 | { 60 | ushort index=0; 61 | while(index < pclass->methods_count) { 62 | if(NULL != pclass->methods[index] && IS_CLINIT_METHOD(pclass, pclass->methods[index])){ 63 | break; 64 | } 65 | index++; 66 | } 67 | 68 | if (index == pclass->methods_count) { 69 | return NULL; 70 | } 71 | 72 | return pclass->methods[index]; 73 | } 74 | 75 | void runClinitMethod(OPENV *current_env, Class *clinit_class, method_info* method) 76 | { 77 | OPENV clinitEnv; 78 | StackFrame* stf; 79 | Code_attribute* code_attr; 80 | 81 | if (clinit_class->clinit_runned) { 82 | return; 83 | } 84 | 85 | debug("before call, current_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 86 | 87 | // 1. create new stack frame 88 | code_attr = (Code_attribute*)(method->code_attribute_addr); 89 | stf = newStackFrame(NULL, code_attr); 90 | 91 | // 4. set new environment 92 | clinitEnv.pc = clinitEnv.pc_start = code_attr->code; 93 | clinitEnv.pc_end = code_attr->code + code_attr->code_length; 94 | clinitEnv.current_stack = stf; 95 | clinitEnv.current_class = clinit_class; 96 | clinitEnv.method = method; 97 | clinitEnv.is_clinit = 1; 98 | clinitEnv.call_depth = 0; 99 | stf->method = method; 100 | 101 | #ifdef DEBUG 102 | clinitEnv.dbg = newDebugType(code_attr->max_locals, STACK_FRAME_SIZE); 103 | #endif 104 | debug("real class name = %s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 105 | internalRunClinitMethod(&clinitEnv); 106 | clinit_class->clinit_runned = 1; 107 | displayStaticFields(clinit_class); 108 | } 109 | 110 | void runMainMethod(Class *pclass) 111 | { 112 | CONSTANT_Class_info *class_info; 113 | CONSTANT_Utf8_info *class_utf8_info; 114 | 115 | Class *parent_class; 116 | StackFrame* mainStack; 117 | OPENV mainEnv; 118 | method_info *mainMethod, *clinitMethod; 119 | Code_attribute* mainCode_attr; 120 | 121 | mainMethod = findMainMethod(pclass); 122 | if (NULL == mainMethod) { 123 | printf("Error: cannot find main method!\n"); 124 | exit(1); 125 | } 126 | 127 | mainCode_attr = GET_CODE_FROM_METHOD(mainMethod); 128 | mainStack = newStackFrame(NULL, mainCode_attr); 129 | 130 | mainEnv.current_class = pclass; 131 | mainEnv.current_stack = mainStack; 132 | mainEnv.pc = mainCode_attr->code; 133 | mainEnv.pc_end = mainCode_attr->code + mainCode_attr->code_length; 134 | mainEnv.pc_start = mainCode_attr->code; 135 | mainEnv.method = mainMethod; 136 | mainEnv.call_depth = 0; 137 | mainEnv.is_clinit = 0; 138 | 139 | mainStack->method = mainMethod; 140 | 141 | #ifdef DEBUG 142 | mainEnv.dbg = newDebugType(mainCode_attr->max_locals, STACK_FRAME_SIZE); 143 | #endif 144 | 145 | debug("stack=%p", mainStack); 146 | 147 | printf("class name=%s", get_this_class_name(pclass)); 148 | // 1. run super class's clinit method 149 | if (pclass->super_class > 0) { 150 | printf("**********run super class's clinit method\n"); 151 | class_info = (CONSTANT_Class_info*)(pclass->constant_pool[pclass->super_class]); 152 | class_utf8_info = (CONSTANT_Utf8_info*)(pclass->constant_pool[class_info->name_index]); 153 | parent_class = loadClassFromDiskRecursive(&mainEnv, class_utf8_info->bytes); 154 | class_info->pclass = parent_class; 155 | pclass->parent_class = parent_class; 156 | } 157 | 158 | // 2. run this class's clinit method 159 | 160 | if (clinitMethod = findClinitMethod(pclass)) { 161 | printf("*********run this class's clinit method\n"); 162 | runClinitMethod(&mainEnv, pclass, clinitMethod); 163 | } 164 | 165 | printf("class name=%s", get_this_class_name(pclass)); 166 | 167 | // 3. run main method 168 | printf("******run main method\n"); 169 | runMethod(&mainEnv); 170 | } 171 | 172 | 173 | void callResolvedClassVirtualMethod(OPENV* current_env, CONSTANT_Methodref_info* method_ref, MethodEntry *mentry) 174 | { 175 | Object *obj; 176 | StackFrame* stf, *last_stack; 177 | CONSTANT_Class_info* class_info; 178 | method_info* method; 179 | Code_attribute* code_attr; 180 | int real_args_len =0; 181 | 182 | debug("before call, current_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 183 | if (current_env->current_class->super_class) { 184 | debug("super_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->super_class)); 185 | } 186 | printMethodrefInfo(current_env->current_class, method_ref); 187 | 188 | 189 | last_stack= current_env->current_stack; 190 | // 1. create new stack frame 191 | method = mentry->method; //(method_info*)(method_ref->ref_addr); 192 | code_attr = (Code_attribute*)(method->code_attribute_addr); 193 | debug("code_attr=%p", code_attr); 194 | stf = newStackFrame(last_stack, code_attr); 195 | debug("End create new stack frame, max_locals = %d", code_attr->max_locals); 196 | 197 | // 2. copy args 198 | real_args_len = method->args_len + SZ_REF; 199 | last_stack->sp -= real_args_len; 200 | memcpy(stf->localvars, last_stack->sp, real_args_len); 201 | obj = *(Object**)(stf->localvars); 202 | current_env->current_obj = obj; 203 | debug("args_len=%d", real_args_len); 204 | debug("last_stack=%p, localvar[0]=%p", PICK_STACKC(last_stack, Reference), obj); 205 | 206 | // 3. save current environment 207 | stf->last_pc = current_env->pc; 208 | stf->last_pc_end = current_env->pc_end; 209 | stf->last_pc_start = current_env->pc_start; 210 | stf->last_class = current_env->current_class; 211 | stf->method = method; 212 | printf("End save current environment\n"); 213 | 214 | // 4. set new environment 215 | //class_info = (CONSTANT_Class_info*)(current_env->current_class->constant_pool[method_ref->class_index]); 216 | current_env->pc = current_env->pc_start = code_attr->code; 217 | current_env->pc_end = code_attr->code + code_attr->code_length; 218 | current_env->current_class = mentry->pclass; //method_ref->pclass; 219 | current_env->current_stack = stf; 220 | current_env->call_depth++; 221 | 222 | debug("real call: class_name=%s", get_this_class_name(mentry->pclass)); 223 | //debug("real class name = %s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 224 | } 225 | 226 | MethodEntry* resolveClassVirtualMethod(Class* caller_class, CONSTANT_Methodref_info **pmethod_ref, CONSTANT_Utf8_info *method_name_utf8, CONSTANT_Utf8_info *method_descriptor_utf8) 227 | { 228 | MethodEntry *mentry = NULL; 229 | Class* callee_class; 230 | cp_info callee_cp, caller_cp; 231 | CONSTANT_Methodref_info* method_ref = *pmethod_ref; 232 | CONSTANT_NameAndType_info* method_nt_info; 233 | CONSTANT_Utf8_info *tmp_method_name_utf8, *tmp_method_descriptor_utf8; 234 | CONSTANT_Class_info *method_ref_class_info; 235 | method_info *method; 236 | int i, found =0; 237 | 238 | caller_cp = caller_class->constant_pool; 239 | callee_class = caller_class; 240 | if (NULL == callee_class) { 241 | printf("resolveClassVirtualMehod: null class\n");exit(1); 242 | } 243 | 244 | debug("method_name=%s, type=%s", method_name_utf8->bytes, method_descriptor_utf8->bytes); 245 | do { 246 | debug("callee_class=%p", callee_class); 247 | callee_cp = callee_class->constant_pool; 248 | debug("callee_class=%s, methods_count=%d", get_class_name(callee_cp, callee_class->this_class), callee_class->methods_count); 249 | for (i = 0; i < callee_class->methods_count; i++) { 250 | method = (method_info*)(callee_class->methods[i]); 251 | tmp_method_name_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->name_index]); 252 | tmp_method_descriptor_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->descriptor_index]); 253 | //debug("method name = %s, type=%s", tmp_method_name_utf8->bytes, tmp_method_descriptor_utf8->bytes); 254 | if (method_name_utf8->length == tmp_method_name_utf8->length && 255 | strcmp(method_name_utf8->bytes, tmp_method_name_utf8->bytes) == 0) { 256 | if (method_descriptor_utf8->length == tmp_method_descriptor_utf8->length && 257 | strcmp(method_descriptor_utf8->bytes, tmp_method_descriptor_utf8->bytes) == 0) { 258 | debug("resolve method success, class=%s", get_class_name(callee_cp, callee_class->this_class)); 259 | 260 | mentry = newMethodEntry(callee_class, method); 261 | debug("mentry: pclass=%p, method=%p", mentry->pclass, mentry->method); 262 | 263 | addMethodEntry(method_ref->mtable, mentry); 264 | 265 | found = 1; 266 | 267 | break; 268 | } 269 | } 270 | } 271 | 272 | if (found) { 273 | break; 274 | } 275 | callee_class = callee_class->parent_class; 276 | } while (callee_class != NULL); 277 | 278 | if (!found) { 279 | printf("Error! cannot resolve method: %s.%s\n", method_name_utf8->bytes, method_descriptor_utf8->bytes); 280 | exit(1); 281 | } 282 | 283 | return mentry; 284 | } 285 | 286 | void callClassVirtualMethod(OPENV *current_env, int mindex) 287 | { 288 | MethodEntry *mentry = NULL; 289 | Object *caller_obj; 290 | Class* current_class = current_env->current_class; 291 | cp_info cp = current_class->constant_pool; 292 | CONSTANT_Methodref_info* method_ref = (CONSTANT_Methodref_info*)(current_class->constant_pool[mindex]); 293 | CONSTANT_NameAndType_info *nt_info = (CONSTANT_NameAndType_info*)(current_class->constant_pool[method_ref->name_and_type_index]); 294 | 295 | if (NULL == method_ref->mtable) { 296 | method_ref->args_len = getMethodrefArgsLen(current_class, nt_info->descriptor_index); 297 | method_ref->mtable = newMethodTable(); 298 | } 299 | 300 | caller_obj = *(Reference*)(current_env->current_stack->sp - ((method_ref->args_len+4))); 301 | printf("%p\n", caller_obj); 302 | debug("caller_obj=%p, class=%s", caller_obj, get_this_class_name(caller_obj->pclass)); 303 | debug("current_class=%s", get_utf8(current_class->constant_pool[((CONSTANT_Class_info*)(current_class->constant_pool[current_class->this_class]))->name_index])); 304 | debug("method class index=%d", method_ref->class_index); 305 | 306 | if(NULL == (mentry = findMethodEntry(method_ref->mtable, caller_obj->pclass))) { 307 | debug("method_ref=%p, mtable=%p", method_ref, method_ref->mtable); 308 | debug("name_index=%d,%p, desc_index=%d\n", nt_info->name_index, (CONSTANT_Utf8_info*)(cp[nt_info->name_index]), nt_info->descriptor_index); 309 | mentry = resolveClassVirtualMethod(caller_obj->pclass, &method_ref, (CONSTANT_Utf8_info*)(cp[nt_info->name_index]), (CONSTANT_Utf8_info*)(cp[nt_info->descriptor_index])); 310 | } 311 | printf("caller_obj=%p, caller_obj_class=%s\n", caller_obj, get_this_class_name(mentry->pclass)); 312 | 313 | callResolvedClassVirtualMethod(current_env, method_ref, mentry); 314 | } 315 | 316 | void resolveClassStaticField(Class* caller_class, CONSTANT_Fieldref_info **pfield_ref) 317 | { 318 | Class* callee_class; 319 | cp_info callee_cp, caller_cp; 320 | CONSTANT_Fieldref_info* field_ref = *pfield_ref; 321 | CONSTANT_NameAndType_info* field_nt_info; 322 | CONSTANT_Utf8_info* field_name_utf8, *field_descriptor_utf8, *tmp_field_name_utf8, *tmp_field_descriptor_utf8; 323 | CONSTANT_Class_info *field_ref_class_info; 324 | field_info *field; 325 | int i, found =0, fields_count; 326 | 327 | caller_cp = caller_class->constant_pool; 328 | field_ref_class_info = (CONSTANT_Class_info*)(caller_cp[field_ref->class_index]); 329 | callee_class = field_ref_class_info->pclass; 330 | if (NULL == callee_class) { 331 | printf("NULL class");exit(1); 332 | } 333 | 334 | field_nt_info = (CONSTANT_NameAndType_info*)(caller_cp[field_ref->name_and_type_index]); 335 | field_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[field_nt_info->name_index]); 336 | field_descriptor_utf8 = (CONSTANT_Utf8_info*)(caller_cp[field_nt_info->descriptor_index]); 337 | 338 | do { 339 | callee_cp = callee_class->constant_pool; 340 | fields_count = callee_class->fields_count; 341 | for (i = 0; i < fields_count; i++) { 342 | field = (field_info*)(callee_class->fields[i]); 343 | tmp_field_name_utf8 = (CONSTANT_Utf8_info*)(callee_cp[field->name_index]); 344 | //debug("field name=%s access_flags=%x, %x", tmp_field_name_utf8->bytes, field->access_flags, field->access_flags & ACC_STATIC); 345 | if (IS_ACC_STATIC(field->access_flags) && 346 | field_name_utf8->length == tmp_field_name_utf8->length && 347 | strcmp(field_name_utf8->bytes, tmp_field_name_utf8->bytes) == 0) { 348 | tmp_field_descriptor_utf8 = (CONSTANT_Utf8_info*)(callee_cp[field->descriptor_index]); 349 | if (field_descriptor_utf8->length == tmp_field_descriptor_utf8->length && 350 | strcmp(field_descriptor_utf8->bytes, tmp_field_descriptor_utf8->bytes) == 0) { 351 | field_ref->ftype = field->ftype; 352 | field_ref->findex = field->findex; 353 | found = 1; 354 | 355 | debug("field resolve success, class=%s", get_class_name(callee_cp, callee_class->this_class)); 356 | debug("field index=%d", field->findex); 357 | break; 358 | } 359 | } 360 | } 361 | 362 | if (found) { 363 | break; 364 | } 365 | callee_class = callee_class->parent_class; 366 | } while(callee_class != NULL); 367 | 368 | if (!found) { 369 | printf("Error! cannot resolve field: %s.%s", field_name_utf8->bytes, field_descriptor_utf8->bytes); 370 | exit(1); 371 | } 372 | } 373 | void do_arraycopy(OPENV *env) 374 | { 375 | int i; 376 | int length, destPos, srcPos; 377 | CArray_char *arr1, *arr2; 378 | GET_STACK(env->current_stack, length, int); 379 | GET_STACK(env->current_stack, destPos, int); 380 | GET_STACK(env->current_stack, arr2, CArray_char*); 381 | GET_STACK(env->current_stack, srcPos, int); 382 | GET_STACK(env->current_stack, arr1, CArray_char*); 383 | 384 | memcpy(arr2->elements+destPos, arr1->elements+srcPos, length); 385 | } 386 | 387 | int callNativeMethod(const char* method_name, OPENV *env) 388 | { 389 | Object *obj; 390 | CArray_char* arr_ref; 391 | int i=0; 392 | if (strcmp(method_name, "writeString") == 0) { 393 | obj = GET_STACKR(env->current_stack, obj, Reference); 394 | debug("obj=%p", obj); 395 | if (NULL != obj) { 396 | arr_ref = GET_FIELD(obj, 0, CArray_char*); 397 | printf("type=%d, length=%d\n", arr_ref->atype, arr_ref->length); 398 | printf("[OUT]: "); 399 | while(ilength) { 400 | putchar(arr_ref->elements[i]); 401 | i++; 402 | } 403 | printf("\n"); 404 | } 405 | } 406 | return 0; 407 | } 408 | 409 | int resolveStaticClassMethod(Class* caller_class, CONSTANT_Methodref_info **pmethod_ref, OPENV *env) 410 | { 411 | Class* callee_class; 412 | cp_info callee_cp, caller_cp; 413 | CONSTANT_Methodref_info* method_ref = *pmethod_ref; 414 | CONSTANT_NameAndType_info* method_nt_info; 415 | CONSTANT_Utf8_info* method_name_utf8, *method_descriptor_utf8, *tmp_method_name_utf8, *tmp_method_descriptor_utf8; 416 | CONSTANT_Class_info *method_ref_class_info; 417 | method_info *method; 418 | int i, found =0; 419 | 420 | caller_cp = caller_class->constant_pool; 421 | 422 | method_ref_class_info = (CONSTANT_Class_info*)(caller_cp[method_ref->class_index]); 423 | callee_class = method_ref_class_info->pclass; 424 | 425 | if (NULL == callee_class) { 426 | callee_class = method_ref_class_info->pclass = systemLoadClassRecursive(env, (CONSTANT_Utf8_info*)(caller_cp[method_ref_class_info->name_index])); 427 | } 428 | 429 | method_nt_info = (CONSTANT_NameAndType_info*)(caller_cp[method_ref->name_and_type_index]); 430 | method_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->name_index]); 431 | method_descriptor_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->descriptor_index]); 432 | 433 | printMethodrefInfo(caller_class, method_ref); 434 | do { 435 | callee_cp = callee_class->constant_pool; 436 | debug("callee_class=%s, methods_count=%d", get_class_name(callee_cp, callee_class->this_class), callee_class->methods_count); 437 | for (i = 0; i < callee_class->methods_count; i++) { 438 | method = (method_info*)(callee_class->methods[i]); 439 | tmp_method_name_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->name_index]); 440 | 441 | if (IS_ACC_STATIC(method->access_flags) && 442 | method_name_utf8->length == tmp_method_name_utf8->length && 443 | strcmp(method_name_utf8->bytes, tmp_method_name_utf8->bytes) == 0) { 444 | tmp_method_descriptor_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->descriptor_index]); 445 | if (method_descriptor_utf8->length == tmp_method_descriptor_utf8->length && 446 | strcmp(method_descriptor_utf8->bytes, tmp_method_descriptor_utf8->bytes) == 0) { 447 | if (IS_ACC_NATIVE(method->access_flags)) { 448 | if (strcmp(method_name_utf8->bytes, "arraycopy") == 0) { 449 | debug("arraycopy: found %s method", method_name_utf8->bytes); 450 | do_arraycopy(env); 451 | return 0; 452 | } else if (strcmp(get_this_class_name(callee_class), "test/IOUtil") == 0) { 453 | printf("find self defined native class"); 454 | return callNativeMethod(method_name_utf8->bytes, env); 455 | 456 | exit(1); 457 | } else { 458 | // "registerNatives" 459 | debug("found unimplemented %s method, skip it", method_name_utf8->bytes); 460 | system("pause"); 461 | return 0; 462 | } 463 | } 464 | 465 | method_ref->ref_addr = method; 466 | method_ref->args_len = method->args_len; 467 | found = 1; 468 | 469 | debug("resolve method success, class=%s", get_class_name(callee_cp, callee_class->this_class)); 470 | 471 | break; 472 | } 473 | } 474 | } 475 | 476 | if (found) { 477 | break; 478 | } 479 | callee_class = callee_class->parent_class; 480 | } while (callee_class != NULL); 481 | 482 | if (!found) { 483 | printf("Error! cannot resolve method: %s.%s\n", method_name_utf8->bytes, method_descriptor_utf8->bytes); 484 | exit(1); 485 | } 486 | 487 | return 1; 488 | } 489 | 490 | void callResolvedStaticClassMethod(OPENV* current_env, CONSTANT_Methodref_info* method_ref) 491 | { 492 | StackFrame* stf, *last_stack; 493 | CONSTANT_Class_info* class_info; 494 | method_info* method; 495 | Code_attribute* code_attr; 496 | int real_args_len =0; 497 | 498 | debug("before call, current_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 499 | if (current_env->current_class->super_class) { 500 | debug("super_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->super_class)); 501 | } 502 | printMethodrefInfo(current_env->current_class, method_ref); 503 | 504 | 505 | last_stack= current_env->current_stack; 506 | // 1. create new stack frame 507 | method = (method_info*)(method_ref->ref_addr); 508 | code_attr = (Code_attribute*)(method->code_attribute_addr); 509 | stf = newStackFrame(last_stack, code_attr); 510 | debug("End create new stack frame, max_locals = %d", code_attr->max_locals); 511 | 512 | // 2. copy args 513 | real_args_len = method->args_len; 514 | if (real_args_len > 0) { 515 | last_stack->sp -= real_args_len; 516 | memcpy(stf->localvars, last_stack->sp, real_args_len); 517 | debug("args_len=%d", real_args_len); 518 | } 519 | 520 | // 3. save current environment 521 | stf->last_pc = current_env->pc; 522 | stf->last_pc_end = current_env->pc_end; 523 | stf->last_pc_start = current_env->pc_start; 524 | stf->last_class = current_env->current_class; 525 | stf->method = method; 526 | 527 | printf("End save current environment\n"); 528 | 529 | // 4. set new environment 530 | class_info = (CONSTANT_Class_info*)(current_env->current_class->constant_pool[method_ref->class_index]); 531 | current_env->pc = current_env->pc_start = code_attr->code; 532 | current_env->pc_end = code_attr->code + code_attr->code_length; 533 | current_env->current_class = class_info->pclass; 534 | current_env->current_stack = stf; 535 | current_env->call_depth++; 536 | 537 | debug("real call: class_index=%d", method_ref->class_index); 538 | debug("real class name = %s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 539 | } 540 | 541 | void callStaticClassMethod(OPENV* current_env, int mindex) 542 | { 543 | char *method_name; 544 | CONSTANT_NameAndType_info *nt_info; 545 | Class* current_class = current_env->current_class; 546 | CONSTANT_Methodref_info* method_ref = (CONSTANT_Methodref_info*)(current_class->constant_pool[mindex]); 547 | char *current_class_name = get_utf8(current_class->constant_pool[((CONSTANT_Class_info*)(current_class->constant_pool[current_class->this_class]))->name_index]); 548 | method_name = get_utf8(current_class->constant_pool[((CONSTANT_NameAndType_info*)(current_class->constant_pool[method_ref->name_and_type_index]))->name_index]); 549 | if (strncmp(current_class_name, "java", 4) == 0) { 550 | debug("skip static method of java lib class: %s", current_class_name); 551 | debug("method name=%s", method_name); 552 | } 553 | 554 | if (strcmp(method_name, "getPrimitiveClass") == 0) { 555 | debug("skip method: %s", method_name); 556 | 557 | return; 558 | } 559 | 560 | nt_info = (CONSTANT_NameAndType_info*)(current_class->constant_pool[method_ref->name_and_type_index]); 561 | 562 | debug("call static method, ref_addr=%p", method_ref->ref_addr); 563 | debug("current_class=%s", get_utf8(current_class->constant_pool[((CONSTANT_Class_info*)(current_class->constant_pool[current_class->this_class]))->name_index])); 564 | debug("method class index=%d", method_ref->class_index); 565 | 566 | if (NULL == method_ref->ref_addr) { 567 | if (0 == resolveStaticClassMethod(current_class, &method_ref, current_env)) { 568 | return; 569 | } 570 | } 571 | 572 | callResolvedStaticClassMethod(current_env, method_ref); 573 | } 574 | 575 | void resolveClassInstanceField(Class* caller_class, CONSTANT_Fieldref_info **pfield_ref) 576 | { 577 | Class* callee_class; 578 | cp_info callee_cp, caller_cp; 579 | CONSTANT_Fieldref_info* field_ref = *pfield_ref; 580 | CONSTANT_NameAndType_info* field_nt_info; 581 | CONSTANT_Utf8_info* field_name_utf8, *tmp_field_name_utf8, *tmp_field_descriptor_utf8, *field_descriptor_utf8; 582 | CONSTANT_Class_info *field_ref_class_info; 583 | field_info *field; 584 | int i, found =0, fields_count; 585 | 586 | caller_cp = caller_class->constant_pool; 587 | field_ref_class_info = (CONSTANT_Class_info*)(caller_cp[field_ref->class_index]); 588 | callee_class = field_ref_class_info->pclass; 589 | if (NULL == callee_class) { 590 | printf("NULL class");exit(1); 591 | } 592 | 593 | field_nt_info = (CONSTANT_NameAndType_info*)(caller_cp[field_ref->name_and_type_index]); 594 | field_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[field_nt_info->name_index]); 595 | field_descriptor_utf8 = (CONSTANT_Utf8_info*)(caller_cp[field_nt_info->descriptor_index]); 596 | 597 | do { 598 | callee_cp = callee_class->constant_pool; 599 | fields_count = callee_class->fields_count; 600 | for (i = 0; i < fields_count; i++) { 601 | field = (field_info*)(callee_class->fields[i]); 602 | tmp_field_name_utf8 = (CONSTANT_Utf8_info*)(callee_cp[field->name_index]); 603 | if (NOT_ACC_STATIC(field->access_flags) && 604 | field_name_utf8->length == tmp_field_name_utf8->length && 605 | strcmp(field_name_utf8->bytes, tmp_field_name_utf8->bytes) == 0) { 606 | tmp_field_descriptor_utf8 = (CONSTANT_Utf8_info*)(callee_cp[field->descriptor_index]); 607 | if (field_descriptor_utf8->length == tmp_field_descriptor_utf8->length && 608 | strcmp(field_descriptor_utf8->bytes, tmp_field_descriptor_utf8->bytes) == 0) { 609 | field_ref->ftype = field->ftype; 610 | field_ref->findex = field->findex; 611 | found = 1; 612 | 613 | debug("field resolve success, class=%s", get_class_name(callee_cp, callee_class->this_class)); 614 | debug("field index=%d", field->findex); 615 | break; 616 | } 617 | } 618 | } 619 | 620 | if (found) { 621 | break; 622 | } 623 | callee_class = callee_class->parent_class; 624 | } while(callee_class != NULL); 625 | 626 | if (!found) { 627 | field_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[field_nt_info->name_index]); 628 | printf("Error! cannot resolve field: %s%s", field_name_utf8->bytes); 629 | exit(1); 630 | } 631 | } 632 | 633 | void resolveClassSpecialMethod(Class* caller_class, CONSTANT_Methodref_info **pmethod_ref) 634 | { 635 | Class* callee_class; 636 | cp_info callee_cp, caller_cp; 637 | CONSTANT_Methodref_info* method_ref = *pmethod_ref; 638 | CONSTANT_NameAndType_info* method_nt_info; 639 | CONSTANT_Utf8_info *method_name_utf8, *method_descriptor_utf8, *tmp_method_name_utf8,*tmp_method_descriptor_utf8; 640 | CONSTANT_Class_info *method_ref_class_info; 641 | method_info *method; 642 | int i, found =0; 643 | 644 | caller_cp = caller_class->constant_pool; 645 | method_ref_class_info = (CONSTANT_Class_info*)(caller_cp[method_ref->class_index]); 646 | callee_class = method_ref_class_info->pclass; 647 | if (NULL == callee_class) { 648 | callee_class = method_ref_class_info->pclass = systemLoadClass((CONSTANT_Utf8_info*)(caller_cp[method_ref_class_info->name_index])); 649 | } 650 | 651 | method_nt_info = (CONSTANT_NameAndType_info*)(caller_cp[method_ref->name_and_type_index]); 652 | method_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->name_index]); 653 | method_descriptor_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->descriptor_index]); 654 | 655 | printf("Begin resolve method:\n"); 656 | printMethodrefInfo(caller_class, method_ref); 657 | do { 658 | callee_cp = callee_class->constant_pool; 659 | debug("callee_class=%s, methods_count=%d", get_class_name(callee_cp, callee_class->this_class), callee_class->methods_count); 660 | for (i = 0; i < callee_class->methods_count; i++) { 661 | method = (method_info*)(callee_class->methods[i]); 662 | tmp_method_name_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->name_index]); 663 | if (method_name_utf8->length == tmp_method_name_utf8->length && 664 | strcmp(method_name_utf8->bytes, tmp_method_name_utf8->bytes) == 0) { 665 | tmp_method_descriptor_utf8 = (CONSTANT_Utf8_info*)(callee_cp[method->descriptor_index]); 666 | if (method_descriptor_utf8->length == tmp_method_descriptor_utf8->length && 667 | strcmp(method_descriptor_utf8->bytes, tmp_method_descriptor_utf8->bytes) == 0) { 668 | method_ref->ref_addr = method; 669 | method_ref->args_len = method->args_len; 670 | 671 | found = 1; 672 | 673 | debug("resolve method success, class=%s", get_class_name(callee_cp, callee_class->this_class)); 674 | 675 | break; 676 | } 677 | } 678 | } 679 | 680 | if (found) { 681 | break; 682 | } 683 | callee_class = callee_class->parent_class; 684 | } while (callee_class != NULL); 685 | 686 | if (!found) { 687 | method_name_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->name_index]); 688 | method_descriptor_utf8 = (CONSTANT_Utf8_info*)(caller_cp[method_nt_info->descriptor_index]); 689 | printf("Error! cannot resolve method: %s.%s\n", method_name_utf8->bytes, method_descriptor_utf8->bytes); 690 | exit(1); 691 | } 692 | } 693 | 694 | void callResolvedClassSpecialMethod(OPENV* current_env, CONSTANT_Methodref_info* method_ref) 695 | { 696 | Object *obj; 697 | StackFrame* stf, *last_stack; 698 | CONSTANT_Class_info* class_info; 699 | method_info* method; 700 | Code_attribute* code_attr; 701 | int real_args_len =0; 702 | 703 | debug("before call, current_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 704 | if (current_env->current_class->super_class) { 705 | debug("super_class=%s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->super_class)); 706 | } 707 | printMethodrefInfo(current_env->current_class, method_ref); 708 | 709 | 710 | last_stack= current_env->current_stack; 711 | // 1. create new stack frame 712 | method = (method_info*)(method_ref->ref_addr); 713 | code_attr = (Code_attribute*)(method->code_attribute_addr); 714 | stf = newStackFrame(last_stack, code_attr); 715 | debug("End create new stack frame, max_locals = %d", code_attr->max_locals); 716 | 717 | // 2. copy args 718 | real_args_len = method->args_len + SZ_REF; 719 | last_stack->sp -= real_args_len; 720 | memcpy(stf->localvars, last_stack->sp, real_args_len); 721 | obj = *(Object**)(stf->localvars); 722 | current_env->current_obj = obj; 723 | 724 | // 3. save current environment 725 | stf->last_pc = current_env->pc; 726 | stf->last_pc_end = current_env->pc_end; 727 | stf->last_pc_start = current_env->pc_start; 728 | stf->last_class = current_env->current_class; 729 | stf->method = method; 730 | 731 | // 4. set new environment 732 | class_info = (CONSTANT_Class_info*)(current_env->current_class->constant_pool[method_ref->class_index]); 733 | current_env->pc = current_env->pc_start = code_attr->code; 734 | current_env->pc_end = code_attr->code + code_attr->code_length; 735 | current_env->current_class = class_info->pclass; 736 | current_env->current_stack = stf; 737 | current_env->call_depth++; 738 | 739 | debug("real call: class_index=%d", method_ref->class_index); 740 | debug("real class name = %s", get_class_name(current_env->current_class->constant_pool, current_env->current_class->this_class)); 741 | } 742 | 743 | void callClassSpecialMethod(OPENV* current_env, int mindex) 744 | { 745 | Class* current_class = current_env->current_class; 746 | CONSTANT_Methodref_info* method_ref = (CONSTANT_Methodref_info*)(current_class->constant_pool[mindex]); 747 | 748 | debug("current_class=%s", get_utf8(current_class->constant_pool[((CONSTANT_Class_info*)(current_class->constant_pool[current_class->this_class]))->name_index])); 749 | debug("method class index=%d", method_ref->class_index); 750 | 751 | if (NULL == method_ref->ref_addr) { 752 | resolveClassSpecialMethod(current_class, &method_ref); 753 | } 754 | 755 | callResolvedClassSpecialMethod(current_env, method_ref); 756 | } 757 | -------------------------------------------------------------------------------- /src/myjvm/jvm_debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef JVM_DEBUG_H 10 | #define JVM_DEBUG_H 11 | 12 | #include "constants.h" 13 | 14 | #define debug_type_c 0x01 15 | #define debug_type_s 0x02 16 | #define debug_type_i 0x03 17 | #define debug_type_f 0x04 18 | #define debug_type_l 0x05 19 | #define debug_type_d 0x06 20 | #define debug_type_a 0x07 21 | #define debug_type_r 0x08 22 | 23 | #ifdef DEBUG 24 | 25 | #define DEBUG_SET_LV_TYPE(dbg, vindex, dtype) *(dbg->localvar_type+vindex)=dtype 26 | #define DEBUG_SET_SP_TYPE(dbg, dtype) *(dbg->spvar_type)=dtype;dbg->spvar_type+=1; 27 | #define DEBUG_CAST_SP_TYPE(dbg, dtype) *(dbg->spvar_type)=dtype 28 | 29 | #define DEBUG_SP_UP(dbg) dbg->spvar_type+=1 30 | #define DEBUG_SP_DOWN(dbg) dbg->spvar_type-=1 31 | #define DEBUG_SP_UPL(dbg) dbg->spvar_type+=2 32 | #define DEBUG_SP_DOWNL(dbg) dbg->spvar_type-=2 33 | #define DEBUG_SP_UPT(dbg) dbg->spvar_type+=3 34 | #define DEBUG_SP_DOWNT(dbg) dbg->spvar_type-=3 35 | 36 | #else 37 | 38 | #define SET_DEBUG_LV_TYPE(dbg, vindex, dtype) 39 | #define SET_DEBUG_SP_TYPE(dbg, dtype) 40 | #define DEBUG_SP_UP(dbg) 41 | #define DEBUG_SP_DOWN(dbg) 42 | #define DEBUG_SP_UPL(dbg) 43 | #define DEBUG_SP_DOWNL(dbg) 44 | #define DEBUG_SP_UPT(dbg) 45 | #define DEBUG_SP_DOWNT(dbg) 46 | 47 | #endif 48 | 49 | #define debug(format,...) printf("\nDEBUG:");\ 50 | printf(format, __VA_ARGS__ );\ 51 | printf("\n") 52 | 53 | typedef struct _DebugType { 54 | char* localvar_type; 55 | char* localvar_base; 56 | char* spvar_type; 57 | char* spvar_base; 58 | } DebugType; 59 | 60 | DebugType* newDebugType(ushort local_vars, int stack_size) 61 | { 62 | DebugType* dbg = (DebugType*)malloc(sizeof(DebugType) + (local_vars+1) + stack_size); 63 | memset(dbg, 0, sizeof(DebugType) + (local_vars+1) + stack_size); 64 | 65 | dbg->localvar_type = (char*)(dbg+1); 66 | dbg->localvar_base = dbg->localvar_type; 67 | dbg->spvar_type = dbg->localvar_type + local_vars+1; 68 | dbg->spvar_base = dbg->spvar_type; 69 | return dbg; 70 | } 71 | 72 | #endif // JVM_DEBUG_H 73 | -------------------------------------------------------------------------------- /src/myjvm/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #define DEBUG true 13 | 14 | #include "jvm.c" 15 | #include "test_jvm_types.c" 16 | 17 | 18 | int main() 19 | { 20 | // 0. specify the test class, the directory is specified in pass_class.c class_dir 21 | const char * testClassName = "test/TestStatic"; // the full qualified name of the class to be tested 22 | Class* pclass; 23 | CONSTANT_Utf8_info class_utf8_info; 24 | class_utf8_info.bytes = testClassName; 25 | class_utf8_info.length = strlen(testClassName); 26 | 27 | // 1. initialize a new class table to store all loaded classes 28 | newLoadedClassTable(); 29 | // 2. load the test class 30 | pclass = systemLoadClass(&class_utf8_info); 31 | 32 | // 3. store the loaded test class 33 | storeLoadedClass(pclass); 34 | 35 | // 4. run the main method of the test class 36 | runMainMethod(pclass); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /src/myjvm/method_table.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef METHOD_TABLE_H 10 | #define METHOD_TABLE_H 11 | 12 | /** 13 | * this file helps to implement the `invokevirtual` instruction 14 | */ 15 | typedef struct _MethodEntry { 16 | Class *pclass; 17 | method_info *method; 18 | struct _MethodEntry *next; 19 | } MethodEntry; 20 | 21 | typedef struct _MethodTable { 22 | MethodEntry *head; 23 | MethodEntry *tail; 24 | } MethodTable; 25 | 26 | MethodEntry* newMethodEntry(Class *pclass, method_info *method) 27 | { 28 | MethodEntry *mte = (MethodEntry*)malloc(sizeof(MethodEntry)); 29 | mte->pclass = pclass; 30 | mte->method = method; 31 | mte->next = NULL; 32 | 33 | return mte; 34 | } 35 | 36 | MethodTable* newMethodTable() 37 | { 38 | MethodTable* mtable = (MethodTable*)malloc(sizeof(MethodTable)); 39 | mtable->head = mtable->tail = NULL; 40 | 41 | return mtable; 42 | } 43 | 44 | void addMethodEntry(MethodTable *mtable, MethodEntry *mte) 45 | { 46 | if (NULL == mtable->head) { 47 | mtable->head = mte; 48 | mtable->tail = mte; 49 | } else { 50 | mtable->tail->next = mte; 51 | mtable->tail = mte; 52 | } 53 | } 54 | 55 | MethodEntry* findMethodEntry(MethodTable *mtable, Class *pclass) 56 | { 57 | MethodEntry *mte = mtable->head; 58 | while (mte != NULL) { 59 | if (mte->pclass == pclass) { 60 | break; 61 | } 62 | mte = mte->next; 63 | } 64 | 65 | return mte; 66 | } 67 | 68 | #endif // METHOD_TABLE_H 69 | -------------------------------------------------------------------------------- /src/myjvm/my_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef MY_TYPES_H 10 | #define MY_TYPES_H 11 | 12 | typedef char byte; 13 | typedef unsigned char uchar; 14 | typedef unsigned short ushort; 15 | typedef unsigned int uint; 16 | 17 | #endif // MY_TYPES_H 18 | -------------------------------------------------------------------------------- /src/myjvm/myjvm.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | CONFIG -= app_bundle 4 | CONFIG -= qt 5 | 6 | SOURCES += \ 7 | main.c 8 | 9 | HEADERS += \ 10 | structs.h \ 11 | utils.h \ 12 | constants.h \ 13 | jvm_debug.h \ 14 | opcode.h \ 15 | my_types.h \ 16 | op_core.h \ 17 | class_hash.h \ 18 | method_table.h 19 | 20 | -------------------------------------------------------------------------------- /src/myjvm/myjvm.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ProjectExplorer.Project.ActiveTarget 7 | 0 8 | 9 | 10 | ProjectExplorer.Project.EditorSettings 11 | 12 | true 13 | false 14 | true 15 | 16 | Cpp 17 | 18 | CppGlobal 19 | 20 | 21 | 22 | QmlJS 23 | 24 | QmlJSGlobal 25 | 26 | 27 | 2 28 | UTF-8 29 | false 30 | 4 31 | false 32 | true 33 | 1 34 | true 35 | 0 36 | true 37 | 0 38 | 8 39 | true 40 | 1 41 | true 42 | true 43 | true 44 | false 45 | 46 | 47 | 48 | ProjectExplorer.Project.PluginSettings 49 | 50 | 51 | 52 | ProjectExplorer.Project.Target.0 53 | 54 | Desktop Qt 5.2.1 MinGW 32bit 55 | Desktop Qt 5.2.1 MinGW 32bit 56 | qt.521.win32_mingw48.essentials_kit 57 | 1 58 | 0 59 | 0 60 | 61 | D:/QT/build-myjvm-Desktop_Qt_5_2_1_MinGW_32bit-Debug 62 | 63 | 64 | true 65 | qmake 66 | 67 | QtProjectManager.QMakeBuildStep 68 | false 69 | true 70 | 71 | false 72 | 73 | 74 | true 75 | Make 76 | 77 | Qt4ProjectManager.MakeStep 78 | 79 | false 80 | 81 | 82 | 83 | 2 84 | 构建 85 | 86 | ProjectExplorer.BuildSteps.Build 87 | 88 | 89 | 0 90 | 清理 91 | 92 | ProjectExplorer.BuildSteps.Clean 93 | 94 | 2 95 | false 96 | 97 | Debug 98 | 99 | Qt4ProjectManager.Qt4BuildConfiguration 100 | 2 101 | true 102 | 103 | 104 | D:/QT/build-myjvm-Desktop_Qt_5_2_1_MinGW_32bit-Release 105 | 106 | 107 | true 108 | qmake 109 | 110 | QtProjectManager.QMakeBuildStep 111 | false 112 | true 113 | 114 | false 115 | 116 | 117 | true 118 | Make 119 | 120 | Qt4ProjectManager.MakeStep 121 | 122 | false 123 | 124 | 125 | 126 | 2 127 | 构建 128 | 129 | ProjectExplorer.BuildSteps.Build 130 | 131 | 132 | 133 | true 134 | Make 135 | 136 | Qt4ProjectManager.MakeStep 137 | 138 | true 139 | clean 140 | 141 | 142 | 1 143 | 清理 144 | 145 | ProjectExplorer.BuildSteps.Clean 146 | 147 | 2 148 | false 149 | 150 | Release 151 | 152 | Qt4ProjectManager.Qt4BuildConfiguration 153 | 0 154 | true 155 | 156 | 2 157 | 158 | 159 | 0 160 | 部署 161 | 162 | ProjectExplorer.BuildSteps.Deploy 163 | 164 | 1 165 | 在本地部署 166 | 167 | ProjectExplorer.DefaultDeployConfiguration 168 | 169 | 1 170 | 171 | 172 | 173 | false 174 | false 175 | false 176 | false 177 | true 178 | 0.01 179 | 10 180 | true 181 | 1 182 | 25 183 | 184 | 1 185 | true 186 | false 187 | true 188 | valgrind 189 | 190 | 0 191 | 1 192 | 2 193 | 3 194 | 4 195 | 5 196 | 6 197 | 7 198 | 8 199 | 9 200 | 10 201 | 11 202 | 12 203 | 13 204 | 14 205 | 206 | 2 207 | 208 | myjvm 209 | 210 | Qt4ProjectManager.Qt4RunConfiguration:D:/QT/myjvm/myjvm.pro 211 | 212 | myjvm.pro 213 | false 214 | true 215 | 216 | 3768 217 | true 218 | false 219 | false 220 | false 221 | false 222 | 223 | 1 224 | 225 | 226 | 227 | ProjectExplorer.Project.TargetCount 228 | 1 229 | 230 | 231 | ProjectExplorer.Project.Updater.EnvironmentId 232 | {2b632d0e-2b45-4745-991f-6d37b2a168bd} 233 | 234 | 235 | ProjectExplorer.Project.Updater.FileVersion 236 | 15 237 | 238 | 239 | -------------------------------------------------------------------------------- /src/myjvm/opcode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | #ifndef OPCODE_C 9 | #define OPCODE_C 10 | 11 | #include "opcode_pre.c" 12 | #include "opcode_actions.c" 13 | 14 | Instruction jvm_instructions[256] = { 15 | {"nop", pre_nop, do_nop}, 16 | {"aconst_nul", pre_aconst_nul, do_aconst_nul}, 17 | {"iconst_m1", pre_iconst_m1, do_iconst_m1}, 18 | {"iconst_0", pre_iconst_0, do_iconst_0}, 19 | {"iconst_1", pre_iconst_1, do_iconst_1}, 20 | {"iconst_2", pre_iconst_2, do_iconst_2}, 21 | {"iconst_3", pre_iconst_3, do_iconst_3}, 22 | {"iconst_4", pre_iconst_4, do_iconst_4}, 23 | {"iconst_5", pre_iconst_5, do_iconst_5}, 24 | {"lconst_0", pre_lconst_0, do_lconst_0}, 25 | {"lconst_1", pre_lconst_1, do_lconst_1}, 26 | {"fconst_0", pre_fconst_0, do_fconst_0}, 27 | {"fconst_1", pre_fconst_1, do_fconst_1}, 28 | {"fconst_2", pre_fconst_2, do_fconst_2}, 29 | {"dconst_0", pre_dconst_0, do_dconst_0}, 30 | {"dconst_1", pre_dconst_1, do_dconst_1}, 31 | {"bipush", pre_bipush, do_bipush}, 32 | {"sipush", pre_sipush, do_sipush}, 33 | {"ldc", pre_ldc, do_ldc}, 34 | {"ldc_w", pre_ldc_w, do_ldc_w}, 35 | {"ldc2_w", pre_ldc2_w, do_ldc2_w}, 36 | {"iload", pre_iload, do_iload}, 37 | {"lload", pre_lload, do_lload}, 38 | {"fload", pre_fload, do_fload}, 39 | {"dload", pre_dload, do_dload}, 40 | {"aload", pre_aload, do_aload}, 41 | {"iload_0", pre_iload_0, do_iload_0}, 42 | {"iload_1", pre_iload_1, do_iload_1}, 43 | {"iload_2", pre_iload_2, do_iload_2}, 44 | {"iload_3", pre_iload_3, do_iload_3}, 45 | {"lload_0", pre_lload_0, do_lload_0}, 46 | {"lload_1", pre_lload_1, do_lload_1}, 47 | {"lload_2", pre_lload_2, do_lload_2}, 48 | {"lload_3", pre_lload_3, do_lload_3}, 49 | {"fload_0", pre_fload_0, do_fload_0}, 50 | {"fload_1", pre_fload_1, do_fload_1}, 51 | {"fload_2", pre_fload_2, do_fload_2}, 52 | {"fload_3", pre_fload_3, do_fload_3}, 53 | {"dload_0", pre_dload_0, do_dload_0}, 54 | {"dload_1", pre_dload_1, do_dload_1}, 55 | {"dload_2", pre_dload_2, do_dload_2}, 56 | {"dload_3", pre_dload_3, do_dload_3}, 57 | {"aload_0", pre_aload_0, do_aload_0}, 58 | {"aload_1", pre_aload_1, do_aload_1}, 59 | {"aload_2", pre_aload_2, do_aload_2}, 60 | {"aload_3", pre_aload_3, do_aload_3}, 61 | {"iaload", pre_iaload, do_iaload}, 62 | {"laload", pre_laload, do_laload}, 63 | {"faload", pre_faload, do_faload}, 64 | {"daload", pre_daload, do_daload}, 65 | {"aaload", pre_aaload, do_aaload}, 66 | {"baload", pre_baload, do_baload}, 67 | {"caload", pre_caload, do_caload}, 68 | {"saload", pre_saload, do_saload}, 69 | {"istore", pre_istore, do_istore}, 70 | {"lstore", pre_lstore, do_lstore}, 71 | {"fstore", pre_fstore, do_fstore}, 72 | {"dstore", pre_dstore, do_dstore}, 73 | {"astore", pre_astore, do_astore}, 74 | {"istore_0", pre_istore_0, do_istore_0}, 75 | {"istore_1", pre_istore_1, do_istore_1}, 76 | {"istore_2", pre_istore_2, do_istore_2}, 77 | {"istore_3", pre_istore_3, do_istore_3}, 78 | {"lstore_0", pre_lstore_0, do_lstore_0}, 79 | {"lstore_1", pre_lstore_1, do_lstore_1}, 80 | {"lstore_2", pre_lstore_2, do_lstore_2}, 81 | {"lstore_3", pre_lstore_3, do_lstore_3}, 82 | {"fstore_0", pre_fstore_0, do_fstore_0}, 83 | {"fstore_1", pre_fstore_1, do_fstore_1}, 84 | {"fstore_2", pre_fstore_2, do_fstore_2}, 85 | {"fstore_3", pre_fstore_3, do_fstore_3}, 86 | {"dstore_0", pre_dstore_0, do_dstore_0}, 87 | {"dstore_1", pre_dstore_1, do_dstore_1}, 88 | {"dstore_2", pre_dstore_2, do_dstore_2}, 89 | {"dstore_3", pre_dstore_3, do_dstore_3}, 90 | {"astore_0", pre_astore_0, do_astore_0}, 91 | {"astore_1", pre_astore_1, do_astore_1}, 92 | {"astore_2", pre_astore_2, do_astore_2}, 93 | {"astore_3", pre_astore_3, do_astore_3}, 94 | {"iastore", pre_iastore, do_iastore}, 95 | {"lastore", pre_lastore, do_lastore}, 96 | {"fastore", pre_fastore, do_fastore}, 97 | {"dastore", pre_dastore, do_dastore}, 98 | {"aastore", pre_aastore, do_aastore}, 99 | {"bastore", pre_bastore, do_bastore}, 100 | {"castore", pre_castore, do_castore}, 101 | {"sastore", pre_sastore, do_sastore}, 102 | {"pop", pre_pop, do_pop}, 103 | {"pop2", pre_pop2, do_pop2}, 104 | {"dup", pre_dup, do_dup}, 105 | {"dup_x1", pre_dup_x1, do_dup_x1}, 106 | {"dup_x2", pre_dup_x2, do_dup_x2}, 107 | {"dup2", pre_dup2, do_dup2}, 108 | {"dup2_x1", pre_dup2_x1, do_dup2_x1}, 109 | {"dup2_x2", pre_dup2_x2, do_dup2_x2}, 110 | {"swap", pre_swap, do_swap}, 111 | {"iadd", pre_iadd, do_iadd}, 112 | {"ladd", pre_ladd, do_ladd}, 113 | {"fadd", pre_fadd, do_fadd}, 114 | {"dadd", pre_dadd, do_dadd}, 115 | {"isub", pre_isub, do_isub}, 116 | {"lsub", pre_lsub, do_lsub}, 117 | {"fsub", pre_fsub, do_fsub}, 118 | {"dsub", pre_dsub, do_dsub}, 119 | {"imul", pre_imul, do_imul}, 120 | {"lmul", pre_lmul, do_lmul}, 121 | {"fmul", pre_fmul, do_fmul}, 122 | {"dmul", pre_dmul, do_dmul}, 123 | {"idiv", pre_idiv, do_idiv}, 124 | {"ldiv", pre_ldiv, do_ldiv}, 125 | {"fdiv", pre_fdiv, do_fdiv}, 126 | {"ddiv", pre_ddiv, do_ddiv}, 127 | {"irem", pre_irem, do_irem}, 128 | {"lrem", pre_lrem, do_lrem}, 129 | {"frem", pre_frem, do_frem}, 130 | {"drem", pre_drem, do_drem}, 131 | {"ineg", pre_ineg, do_ineg}, 132 | {"lneg", pre_lneg, do_lneg}, 133 | {"fneg", pre_fneg, do_fneg}, 134 | {"dneg", pre_dneg, do_dneg}, 135 | {"ishl", pre_ishl, do_ishl}, 136 | {"lshl", pre_lshl, do_lshl}, 137 | {"ishr", pre_ishr, do_ishr}, 138 | {"lshr", pre_lshr, do_lshr}, 139 | {"iushr", pre_iushr, do_iushr}, 140 | {"lushr", pre_lushr, do_lushr}, 141 | {"iand", pre_iand, do_iand}, 142 | {"land", pre_land, do_land}, 143 | {"ior", pre_ior, do_ior}, 144 | {"lor", pre_lor, do_lor}, 145 | {"ixor", pre_ixor, do_ixor}, 146 | {"lxor", pre_lxor, do_lxor}, 147 | {"iinc", pre_iinc, do_iinc}, 148 | {"i2l", pre_i2l, do_i2l}, 149 | {"i2f", pre_i2f, do_i2f}, 150 | {"i2d", pre_i2d, do_i2d}, 151 | {"l2i", pre_l2i, do_l2i}, 152 | {"l2f", pre_l2f, do_l2f}, 153 | {"l2d", pre_l2d, do_l2d}, 154 | {"f2i", pre_f2i, do_f2i}, 155 | {"f2l", pre_f2l, do_f2l}, 156 | {"f2d", pre_f2d, do_f2d}, 157 | {"d2i", pre_d2i, do_d2i}, 158 | {"d2l", pre_d2l, do_d2l}, 159 | {"d2f", pre_d2f, do_d2f}, 160 | {"i2b", pre_i2b, do_i2b}, 161 | {"i2c", pre_i2c, do_i2c}, 162 | {"i2s", pre_i2s, do_i2s}, 163 | {"lcmp", pre_lcmp, do_lcmp}, 164 | {"fcmpl", pre_fcmpl, do_fcmpl}, 165 | {"fcmpg", pre_fcmpg, do_fcmpg}, 166 | {"dcmpl", pre_dcmpl, do_dcmpl}, 167 | {"dcmpg", pre_dcmpg, do_dcmpg}, 168 | {"ifeq", pre_ifeq, do_ifeq}, 169 | {"ifne", pre_ifne, do_ifne}, 170 | {"iflt", pre_iflt, do_iflt}, 171 | {"ifge", pre_ifge, do_ifge}, 172 | {"ifgt", pre_ifgt, do_ifgt}, 173 | {"ifle", pre_ifle, do_ifle}, 174 | {"if_icmpeq", pre_if_icmpeq, do_if_icmpeq}, 175 | {"if_icmpne", pre_if_icmpne, do_if_icmpne}, 176 | {"if_icmplt", pre_if_icmplt, do_if_icmplt}, 177 | {"if_icmpge", pre_if_icmpge, do_if_icmpge}, 178 | {"if_icmpgt", pre_if_icmpgt, do_if_icmpgt}, 179 | {"if_icmple", pre_if_icmple, do_if_icmple}, 180 | {"if_acmpeq", pre_if_acmpeq, do_if_acmpeq}, 181 | {"if_acmpne", pre_if_acmpne, do_if_acmpne}, 182 | {"goto", pre_goto, do_goto}, 183 | {"jsr", pre_jsr, do_jsr}, 184 | {"ret", pre_ret, do_ret}, 185 | {"tableswitch", pre_tableswitch, do_tableswitch}, 186 | {"lookupsw", pre_lookupswitch, do_lookupswitch}, 187 | {"ireturn", pre_ireturn, do_ireturn}, 188 | {"lreturn", pre_lreturn, do_lreturn}, 189 | {"freturn", pre_freturn, do_freturn}, 190 | {"dreturn", pre_dreturn, do_dreturn}, 191 | {"areturn", pre_areturn, do_areturn}, 192 | {"return", pre_return, do_return}, 193 | {"getstatic", pre_getstatic, do_getstatic}, 194 | {"putstatic", pre_putstatic, do_putstatic}, 195 | {"getfield", pre_getfield, do_getfield}, 196 | {"putfield", pre_putfield, do_putfield}, 197 | {"invokevirtual", pre_invokevirtual, do_invokevirtual}, 198 | {"invokespecial", pre_invokespecial, do_invokespecial}, 199 | {"invokestatic", pre_invokestatic, do_invokestatic}, 200 | {"invokeinterface", pre_invokeinterface, do_invokeinterface}, 201 | {"invokedynamic", pre_invokedynamic, do_invokedynamic}, 202 | {"new", pre_new, do_new}, 203 | {"newarray", pre_newarray, do_newarray}, 204 | {"anewarray", pre_anewarray, do_anewarray}, 205 | {"arraylength", pre_arraylength, do_arraylength}, 206 | {"athrow", pre_athrow, do_athrow}, 207 | {"checkcast", pre_checkcast, do_checkcast}, 208 | {"instanceof", pre_instanceof, do_instanceof}, 209 | {"monitorenter", pre_monitorenter, do_monitorenter}, 210 | {"monitorexit", pre_monitorexit, do_monitorexit}, 211 | {"wide", pre_wide, do_wide}, 212 | {"multianewarray", pre_multianewarray, do_multianewarray}, 213 | {"ifnull", pre_ifnull, do_ifnull}, 214 | {"ifnonnull", pre_ifnonnull, do_ifnonnull}, 215 | {"goto_w", pre_goto_w, do_goto_w}, 216 | {"jsr_w", pre_jsr_w, do_jsr_w}, 217 | {"breakpoint", pre_breakpoint, do_breakpoint}, 218 | {"", NULL, NULL}, 219 | {"", NULL, NULL}, 220 | {"", NULL, NULL}, 221 | {"", NULL, NULL}, 222 | {"", NULL, NULL}, 223 | {"", NULL, NULL}, 224 | {"", NULL, NULL}, 225 | {"", NULL, NULL}, 226 | {"", NULL, NULL}, 227 | {"", NULL, NULL}, 228 | {"", NULL, NULL}, 229 | {"", NULL, NULL}, 230 | {"", NULL, NULL}, 231 | {"", NULL, NULL}, 232 | {"", NULL, NULL}, 233 | {"", NULL, NULL}, 234 | {"", NULL, NULL}, 235 | {"", NULL, NULL}, 236 | {"", NULL, NULL}, 237 | {"", NULL, NULL}, 238 | {"", NULL, NULL}, 239 | {"", NULL, NULL}, 240 | {"", NULL, NULL}, 241 | {"", NULL, NULL}, 242 | {"", NULL, NULL}, 243 | {"", NULL, NULL}, 244 | {"", NULL, NULL}, 245 | {"", NULL, NULL}, 246 | {"", NULL, NULL}, 247 | {"", NULL, NULL}, 248 | {"", NULL, NULL}, 249 | {"", NULL, NULL}, 250 | {"", NULL, NULL}, 251 | {"", NULL, NULL}, 252 | {"", NULL, NULL}, 253 | {"", NULL, NULL}, 254 | {"", NULL, NULL}, 255 | {"", NULL, NULL}, 256 | {"", NULL, NULL}, 257 | {"", NULL, NULL}, 258 | {"", NULL, NULL}, 259 | {"", NULL, NULL}, 260 | {"", NULL, NULL}, 261 | {"", NULL, NULL}, 262 | {"", NULL, NULL}, 263 | {"", NULL, NULL}, 264 | {"", NULL, NULL}, 265 | {"", NULL, NULL}, 266 | {"", NULL, NULL}, 267 | {"", NULL, NULL}, 268 | {"", NULL, NULL}, 269 | {"impdep1", pre_impdep1, do_impdep1}, 270 | {"impdep", pre_impdep2, do_impdep2} 271 | }; 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /src/myjvm/opcode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OPCODE_H 10 | #define OPCODE_H 11 | 12 | #define OPCODE_MAX 203 13 | #define RETURNV return 14 | 15 | #define TO_BYTE(pc) ((*(pc) & 0x80) > 0 ? ((*(pc) & 0x7f)-128) : (*(pc))) 16 | #define TO_CHAR(pc) *(pc) 17 | #define TO_SHORT(pc) *(short*)(pc) 18 | #define TO_INT(pc) *(int*)(pc) 19 | 20 | 21 | #define PRINTLN printf("\n") 22 | #define PRINTD(x) printf("%d",x) 23 | #define PRINTSD(x) fprintf(stderr, "#%d", x) 24 | 25 | #define SWAP(p,index0,index1) *(p+index1)^=(*(p+index0));\ 26 | *(p+index0)^=(*(p+index1));\ 27 | *(p+index1)^=(*(p+index0)); 28 | #define BE2LE2(p) SWAP(p,0,1) 29 | #define BE2LE4(p) SWAP(p,0,3);\ 30 | SWAP(p,1,2) 31 | #define BE2LE8(p) SWAP(p,0,7);\ 32 | SWAP(p,1,6);\ 33 | SWAP(p,2,5);\ 34 | SWAP(p,3,4) 35 | 36 | #define INC_PC(pc) (pc)+=1 37 | #define INC2_PC(pc) (pc)+=2 38 | #define INC3_PC(pc) (pc)+=3 39 | #define INC4_PC(pc) (pc)+=4 40 | #define INC8_PC(pc) (pc)+=8 41 | 42 | #endif // OPCODE_H 43 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #include "opcode_actions/op_const.c" 10 | #include "opcode_actions/op_load.c" 11 | #include "opcode_actions/op_store.c" 12 | #include "opcode_actions/op_stack.c" 13 | #include "opcode_actions/op_math.c" 14 | #include "opcode_actions/op_cast.c" 15 | #include "opcode_actions/op_compare.c" 16 | #include "opcode_actions/op_jump.c" 17 | #include "opcode_actions/op_control.c" 18 | #include "opcode_actions/op_obj.c" 19 | #include "opcode_actions/op_extend.c" 20 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_cast.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_CAST_C 10 | #define OP_CAST_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_i2l(OPENV *env) 16 | { 17 | I2L(env); 18 | RETURNV; 19 | } 20 | Opreturn do_i2f(OPENV *env) 21 | { 22 | I2F(env); 23 | RETURNV; 24 | } 25 | Opreturn do_i2d(OPENV *env) 26 | { 27 | I2D(env); 28 | RETURNV; 29 | } 30 | Opreturn do_l2i(OPENV *env) 31 | { 32 | L2I(env); 33 | RETURNV; 34 | } 35 | Opreturn do_l2f(OPENV *env) 36 | { 37 | L2F(env); 38 | RETURNV; 39 | } 40 | Opreturn do_l2d(OPENV *env) 41 | { 42 | L2D(env); 43 | RETURNV; 44 | } 45 | Opreturn do_f2i(OPENV *env) 46 | { 47 | F2I(env); 48 | RETURNV; 49 | } 50 | Opreturn do_f2l(OPENV *env) 51 | { 52 | F2L(env); 53 | RETURNV; 54 | } 55 | Opreturn do_f2d(OPENV *env) 56 | { 57 | F2D(env); 58 | RETURNV; 59 | } 60 | Opreturn do_d2i(OPENV *env) 61 | { 62 | D2I(env); 63 | RETURNV; 64 | } 65 | Opreturn do_d2l(OPENV *env) 66 | { 67 | D2L(env); 68 | RETURNV; 69 | } 70 | Opreturn do_d2f(OPENV *env) 71 | { 72 | D2F(env); 73 | RETURNV; 74 | } 75 | Opreturn do_i2b(OPENV *env) 76 | { 77 | I2B(env); 78 | RETURNV; 79 | } 80 | Opreturn do_i2c(OPENV *env) 81 | { 82 | I2C(env); 83 | RETURNV; 84 | } 85 | Opreturn do_i2s(OPENV *env) 86 | { 87 | I2S(env); 88 | RETURNV; 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_compare.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_COMPARE_C 10 | #define OP_COMPARE_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_lcmp(OPENV *env) 16 | { 17 | LCMP(env); 18 | RETURNV; 19 | } 20 | Opreturn do_fcmpl(OPENV *env) 21 | { 22 | FCMPL(env); 23 | RETURNV; 24 | } 25 | Opreturn do_fcmpg(OPENV *env) 26 | { 27 | // TODO: different behavior of fcmpl and fcmpg to NaN 28 | FCMPG(env); 29 | RETURNV; 30 | } 31 | Opreturn do_dcmpl(OPENV *env) 32 | { 33 | DCMPL(env); 34 | RETURNV; 35 | } 36 | Opreturn do_dcmpg(OPENV *env) 37 | { 38 | // TODO: different behavior of dcmpl and dcmpg to NaN 39 | DCMPG(env); 40 | RETURNV; 41 | } 42 | 43 | Opreturn do_ifeq(OPENV *env) 44 | { 45 | IFEQ(env); 46 | } 47 | Opreturn do_ifne(OPENV *env) 48 | { 49 | IFNE(env); 50 | } 51 | Opreturn do_iflt(OPENV *env) 52 | { 53 | IFLT(env); 54 | } 55 | Opreturn do_ifge(OPENV *env) 56 | { 57 | IFGE(env); 58 | } 59 | Opreturn do_ifgt(OPENV *env) 60 | { 61 | IFGT(env); 62 | } 63 | Opreturn do_ifle(OPENV *env) 64 | { 65 | IFLE(env); 66 | } 67 | Opreturn do_if_icmpeq(OPENV *env) 68 | { 69 | ICMPEQ(env); 70 | } 71 | Opreturn do_if_icmpne(OPENV *env) 72 | { 73 | ICMPNE(env); 74 | } 75 | Opreturn do_if_icmplt(OPENV *env) 76 | { 77 | ICMPLT(env); 78 | } 79 | Opreturn do_if_icmpge(OPENV *env) 80 | { 81 | ICMPGE(env); 82 | } 83 | Opreturn do_if_icmpgt(OPENV *env) 84 | { 85 | ICMPGT(env); 86 | } 87 | Opreturn do_if_icmple(OPENV *env) 88 | { 89 | ICMPLE(env); 90 | } 91 | Opreturn do_if_acmpeq(OPENV *env) 92 | { 93 | ACMPEQ(env); 94 | } 95 | Opreturn do_if_acmpne(OPENV *env) 96 | { 97 | ACMPNE(env); 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_const.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_CONST_C 10 | #define OP_CONST_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_nop(OPENV *env) 16 | { 17 | RETURNV; 18 | } 19 | Opreturn do_aconst_nul(OPENV *env) 20 | { 21 | PUSH_STACKR(env->current_stack, NULL, Reference); 22 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_r); 23 | RETURNV; 24 | } 25 | Opreturn do_iconst_m1(OPENV *env) 26 | { 27 | PUSH_STACK(env->current_stack, -1, int); 28 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 29 | RETURNV; 30 | } 31 | Opreturn do_iconst_0(OPENV *env) 32 | { 33 | PUSH_STACK(env->current_stack, 0, int); 34 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 35 | RETURNV; 36 | } 37 | Opreturn do_iconst_1(OPENV *env) 38 | { 39 | PUSH_STACK(env->current_stack, 1, int); 40 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 41 | RETURNV; 42 | } 43 | Opreturn do_iconst_2(OPENV *env) 44 | { 45 | PUSH_STACK(env->current_stack, 2, int); 46 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 47 | RETURNV; 48 | } 49 | Opreturn do_iconst_3(OPENV *env) 50 | { 51 | PUSH_STACK(env->current_stack, 3, int); 52 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 53 | RETURNV; 54 | } 55 | Opreturn do_iconst_4(OPENV *env) 56 | { 57 | PUSH_STACK(env->current_stack, 4, int); 58 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 59 | RETURNV; 60 | } 61 | Opreturn do_iconst_5(OPENV *env) 62 | { 63 | PUSH_STACK(env->current_stack, 5, int); 64 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 65 | RETURNV; 66 | } 67 | Opreturn do_lconst_0(OPENV *env) 68 | { 69 | PUSH_STACKL(env->current_stack, 0, long); 70 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_l); 71 | RETURNV; 72 | } 73 | Opreturn do_lconst_1(OPENV *env) 74 | { 75 | PUSH_STACKL(env->current_stack, 1, long); 76 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_l); 77 | RETURNV; 78 | } 79 | Opreturn do_fconst_0(OPENV *env) 80 | { 81 | PUSH_STACK(env->current_stack, 0.0f, float); 82 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_f); 83 | RETURNV; 84 | } 85 | Opreturn do_fconst_1(OPENV *env) 86 | { 87 | PUSH_STACK(env->current_stack, 1.0f, float); 88 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_f); 89 | RETURNV; 90 | } 91 | Opreturn do_fconst_2(OPENV *env) 92 | { 93 | PUSH_STACK(env->current_stack, 2.0f, float); 94 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_f); 95 | RETURNV; 96 | } 97 | Opreturn do_dconst_0(OPENV *env) 98 | { 99 | PUSH_STACKL(env->current_stack, 0.0, double); 100 | 101 | RETURNV; 102 | } 103 | Opreturn do_dconst_1(OPENV *env) 104 | { 105 | PUSH_STACKL(env->current_stack, 1.0, double); 106 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_d); 107 | RETURNV; 108 | } 109 | Opreturn do_bipush(OPENV *env) 110 | { 111 | PRINTD(TO_BYTE(env->pc)); 112 | PUSH_STACK(env->current_stack,TO_BYTE(env->pc), int); 113 | INC_PC(env->pc); 114 | printCurrentEnv(env, "bipush"); 115 | //DEBUG_SET_SP_TYPE(env->dbg, debug_type_c); 116 | RETURNV; 117 | } 118 | Opreturn do_sipush(OPENV *env) 119 | { 120 | PRINTD(TO_SHORT(env->pc)); 121 | PUSH_STACK(env->current_stack,TO_SHORT(env->pc), int); 122 | debug("sipush=%d, %d", TO_SHORT(env->pc), PICK_STACK(env->current_stack, short)); 123 | INC2_PC(env->pc); 124 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_s); 125 | RETURNV; 126 | } 127 | Opreturn do_ldc(OPENV *env) 128 | { 129 | FILE *fp; 130 | int i; 131 | CArray_char* char_arr; 132 | Object *str_obj; 133 | PRINTSD(TO_CHAR(env->pc)); 134 | ushort index = (ushort)(TO_CHAR(env->pc)); 135 | uchar tag; 136 | tag = *(char*)(env->current_class->constant_pool[index]); 137 | 138 | INC_PC(env->pc); 139 | switch (tag) { 140 | case CONSTANT_Integer: 141 | PUSH_STACK(env->current_stack, ((CONSTANT_Integer_info*)(env->current_class->constant_pool[index]))->value, int); 142 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 143 | break; 144 | case CONSTANT_Float: 145 | PUSH_STACK(env->current_stack, ((CONSTANT_Float_info*)(env->current_class->constant_pool[index]))->value, float); 146 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_f); 147 | break; 148 | case CONSTANT_String: 149 | debug("this class = %s", get_this_class_name(env->current_class)); 150 | debug("ldc error: tag=%d, index=%d", tag, index); 151 | printf("ldc: stack=%p, sp=%p, pc=%p\n", env->current_stack, env->current_stack->sp, env->pc); 152 | 153 | // begin save to log 154 | printCurrentEnv(env, "ldc"); 155 | // end save to log 156 | 157 | char_arr = newCArray_char_fromConstStr(env->current_class, index); 158 | str_obj = newConstString(env, char_arr); 159 | //PUSH_STACKR(env->current_stack, str_obj, Reference); 160 | printf("create const string success\n"); 161 | printf("ldcend: stack=%p, sp=%p, pc=%p\n", env->current_stack, env->current_stack->sp, env->pc); 162 | // begin save to log 163 | printCurrentEnv(env, "ldc end"); 164 | // end save to log 165 | //exit(1); 166 | break; 167 | default: 168 | debug("ldc error: tag=%d, index=%d", tag, index); 169 | exit(1); 170 | } 171 | 172 | RETURNV; 173 | } 174 | Opreturn do_ldc_w(OPENV *env) 175 | { 176 | PRINTSD(TO_SHORT(env->pc)); 177 | ushort index = (ushort)(TO_SHORT(env->pc)); 178 | uchar tag; 179 | tag = *(char*)(env->current_class->constant_pool[index]); 180 | if (tag == CONSTANT_Integer) { 181 | PUSH_STACK(env->current_stack, ((CONSTANT_Integer_info*)(env->current_class->constant_pool[index]))->value, int); 182 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_i); 183 | } else if (tag == CONSTANT_Float) { 184 | PUSH_STACK(env->current_stack, ((CONSTANT_Float_info*)(env->current_class->constant_pool[index]))->value, float); 185 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_f); 186 | } else { 187 | debug("ldc_w error: tag=%d, index=%d", tag, index); 188 | exit(1); 189 | } 190 | INC2_PC(env->pc); 191 | RETURNV; 192 | } 193 | Opreturn do_ldc2_w(OPENV *env) 194 | { 195 | PRINTSD(TO_SHORT(env->pc)); 196 | ushort index = (ushort)(TO_SHORT(env->pc)); 197 | uchar tag; 198 | tag = *(char*)(env->current_class->constant_pool[index]); 199 | if (tag == CONSTANT_Long) { 200 | PUSH_STACKL(env->current_stack, ((CONSTANT_Long_info*)(env->current_class->constant_pool[index]))->value, long); 201 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_l); 202 | } else if (tag == CONSTANT_Double) { 203 | PUSH_STACKL(env->current_stack, ((CONSTANT_Double_info*)(env->current_class->constant_pool[index]))->value, double); 204 | DEBUG_SET_SP_TYPE(env->dbg, debug_type_d); 205 | } else { 206 | debug("ldc2_w error: tag=%d, index=%d", tag, index); 207 | exit(1); 208 | } 209 | 210 | INC2_PC(env->pc); 211 | RETURNV; 212 | } 213 | #endif 214 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_control.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_CONTROL_C 10 | #define OP_CONTROL_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_goto(OPENV *env) 16 | { 17 | short offset = TO_SHORT(env->pc); 18 | env->pc+=(offset-1); 19 | } 20 | Opreturn do_jsr(OPENV *env) 21 | { 22 | short offset = TO_SHORT(env->pc); 23 | PUSH_STACK(env->current_stack, offset, short); 24 | 25 | INC2_PC(env->pc); 26 | } 27 | Opreturn do_ret(OPENV *env) 28 | { 29 | short index = TO_CHAR(env->pc); 30 | Reference ref = GET_LOCAL(env->current_stack, index, Reference); 31 | env->pc = (char*)ref; 32 | 33 | RETURNV; 34 | } 35 | Opreturn do_tableswitch(OPENV *env) 36 | { 37 | int index, default_offset, low_offset, high_offset, padding; 38 | PC pc_switch_begin; 39 | GET_STACK(env->current_stack, index, int); 40 | env->pc-=1; 41 | pc_switch_begin = env->pc; 42 | padding = (env->pc - env->pc_start)%4; 43 | if (padding > 0) { 44 | padding = 4 - padding; 45 | } 46 | env->pc+=padding; 47 | debug("index=%d", index); 48 | 49 | default_offset = TO_INT(env->pc); 50 | INC4_PC(env->pc); 51 | low_offset = TO_INT(env->pc); 52 | INC4_PC(env->pc); 53 | high_offset = TO_INT(env->pc); 54 | INC4_PC(env->pc); 55 | 56 | debug("default=%d,low=%d,high=%d\n", default_offset, low_offset, high_offset); 57 | if (index < low_offset || index > high_offset) { 58 | env->pc = pc_switch_begin + default_offset; 59 | } else { 60 | env->pc += ((index-low_offset)<<2); 61 | debug("jump offset: %d", TO_INT(env->pc)); 62 | env->pc = pc_switch_begin + TO_INT(env->pc); 63 | } 64 | RETURNV; 65 | } 66 | Opreturn do_lookupswitch(OPENV *env) 67 | { 68 | int default_offset, padding, i, key, npairs; 69 | PC pc_lookup_begin; 70 | GET_STACK(env->current_stack, key, int); 71 | env->pc-=1; 72 | pc_lookup_begin = env->pc; 73 | padding = (env->pc - env->pc_start)%4; 74 | if (padding > 0) { 75 | padding = 4 - padding; 76 | } 77 | env->pc+=padding; 78 | 79 | default_offset = TO_INT(env->pc); 80 | INC4_PC(env->pc); 81 | npairs = TO_INT(env->pc); 82 | INC4_PC(env->pc); 83 | 84 | for(i = 0; i < npairs; i++) { 85 | if (key == TO_INT(env->pc)) { 86 | INC4_PC(env->pc); 87 | env->pc = pc_lookup_begin + TO_INT(env->pc); 88 | debug("jump=%d", env->pc - env->pc_start); 89 | RETURNV; 90 | } else { 91 | INC8_PC(env->pc); 92 | } 93 | } 94 | 95 | env->pc = pc_lookup_begin + default_offset; 96 | debug("default jump=%d", env->pc-env->pc_start); 97 | 98 | RETURNV; 99 | } 100 | 101 | Opreturn do_ireturn(OPENV *env) 102 | { 103 | int v; 104 | GET_STACK(env->current_stack, v, int); 105 | PUSH_STACK(env->current_stack->prev, v, int); 106 | debug("method call end, returns: %d", v); 107 | FUNC_RETURN(env); 108 | RETURNV; 109 | } 110 | Opreturn do_lreturn(OPENV *env) 111 | { 112 | long v; 113 | GET_STACKL(env->current_stack,v, long); 114 | PUSH_STACKL(env->current_stack->prev, v, long); 115 | debug("method call end, returns: %ld", v); 116 | FUNC_RETURN(env); 117 | RETURNV; 118 | } 119 | Opreturn do_freturn(OPENV *env) 120 | { 121 | float v; 122 | GET_STACK(env->current_stack, v, float); 123 | PUSH_STACK(env->current_stack->prev, v, float); 124 | debug("method call end, returns: %f", v); 125 | FUNC_RETURN(env); 126 | RETURNV; 127 | } 128 | Opreturn do_dreturn(OPENV *env) 129 | { 130 | double v; 131 | GET_STACKL(env->current_stack,v, double); 132 | PUSH_STACKL(env->current_stack->prev, v, double); 133 | debug("method call end, returns: %lf", v); 134 | FUNC_RETURN(env); 135 | RETURNV; 136 | } 137 | Opreturn do_areturn(OPENV *env) 138 | { 139 | Reference v; 140 | GET_STACK(env->current_stack,v, Reference); 141 | PUSH_STACK(env->current_stack->prev, v, Reference); 142 | debug("method call end, returns: 0x%p", v); 143 | FUNC_RETURN(env); 144 | RETURNV; 145 | } 146 | Opreturn do_return(OPENV *env) 147 | { 148 | // return void 149 | debug("method call end, returns void",3); 150 | FUNC_RETURN(env); 151 | RETURNV; 152 | } 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_extend.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_EXTEND_C 10 | #define OP_EXTEND_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_wide(OPENV *env) 16 | { 17 | BE2LE4(env->pc); 18 | PRINTD(TO_INT(env->pc)); 19 | INC4_PC(env->pc); 20 | } 21 | Opreturn do_multianewarray(OPENV *env) 22 | { 23 | PRINTD(TO_SHORT(env->pc)); 24 | cp_info cp = env->current_class->constant_pool; 25 | char *arr_type_utf8; 26 | int arr_type_index = TO_SHORT(env->pc); 27 | int dcount, callback_index; 28 | int *parr_dims; 29 | CArray_ArrayRef *multi_arr_ref; 30 | INC2_PC(env->pc); 31 | dcount = (int)(TO_CHAR(env->pc)); 32 | INC_PC(env->pc); 33 | 34 | arr_type_utf8 = ((CONSTANT_Utf8_info*)(cp[((CONSTANT_Class_info*)(cp[arr_type_index]))->name_index]))->bytes; 35 | debug("arr_type_utf8=%s", arr_type_utf8); 36 | while(*arr_type_utf8 == '[') arr_type_utf8++; 37 | debug("arr_type=%s", arr_type_utf8); 38 | 39 | parr_dims = (int*)(env->current_stack->sp - SZ_INT*dcount); 40 | env->current_stack->sp = parr_dims; 41 | 42 | switch (*arr_type_utf8) { 43 | case 'B': // byte 44 | callback_index = 1; 45 | break; 46 | case 'C': // char 47 | callback_index = 2; 48 | break; 49 | case 'S': // short 50 | callback_index = 2; 51 | break; 52 | case 'Z': // boolean 53 | callback_index = 0; 54 | break; 55 | case 'I': // integer 56 | callback_index = 5; 57 | break; 58 | case 'F': 59 | callback_index = 6; 60 | break; 61 | case 'L': 62 | callback_index = 9; 63 | break; 64 | case 'J': 65 | callback_index = 7; 66 | break; 67 | case 'D': 68 | callback_index = 8; 69 | break; 70 | default: 71 | break; 72 | } 73 | multi_arr_ref = newMultiArray(parr_dims, dcount, arr_type_index & 0x10, mAnewCallaback[callback_index]); 74 | PUSH_STACK(env->current_stack, multi_arr_ref, CArray_ArrayRef*); 75 | //exit(1); 76 | } 77 | 78 | Opreturn do_ifnull(OPENV *env) 79 | { 80 | Reference ref; 81 | short offset; 82 | GET_STACK(env->current_stack, ref, Reference); 83 | if (NULL == ref) { 84 | offset = TO_SHORT(env->pc); 85 | env->pc += (offset-1); 86 | } else { 87 | INC2_PC(env->pc); 88 | } 89 | } 90 | Opreturn do_ifnonnull(OPENV *env) 91 | { 92 | Reference ref; 93 | short offset; 94 | GET_STACK(env->current_stack, ref, Reference); 95 | if (NULL != ref) { 96 | offset = TO_SHORT(env->pc); 97 | env->pc += (offset-1); 98 | } else { 99 | INC2_PC(env->pc); 100 | } 101 | } 102 | 103 | Opreturn do_goto_w(OPENV *env) 104 | { 105 | int offset = TO_INT(env->pc); 106 | env->pc += (offset-1); 107 | } 108 | 109 | Opreturn do_jsr_w(OPENV *env) 110 | { 111 | int addr = TO_INT(env->pc); 112 | PUSH_STACK(env->current_stack, addr, int); 113 | INC4_PC(env->pc); 114 | } 115 | 116 | Opreturn do_breakpoint(OPENV *env) 117 | { 118 | PRINTD(TO_CHAR(env->pc)); 119 | debug("%s", "breakpoint"); 120 | exit(1); 121 | //INC_PC(env->pc); 122 | } 123 | Opreturn do_impdep1(OPENV *env) 124 | { 125 | PRINTD(TO_CHAR(env->pc)); 126 | debug("%s", "impdep1"); 127 | exit(1); 128 | //INC_PC(env->pc); 129 | } 130 | Opreturn do_impdep2(OPENV *env) 131 | { 132 | PRINTD(TO_CHAR(env->pc)); 133 | debug("%s", "impdep2"); 134 | exit(1); 135 | //INC_PC(env->pc); 136 | } 137 | #endif 138 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_jump.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_JUMP_C 10 | #define OP_JUMP_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_load.c: -------------------------------------------------------------------------------- 1 | #ifndef OP_LOAD_C 2 | #define OP_LOAD_C 3 | 4 | #include "opcode.h" 5 | #include "op_core.h" 6 | #include "structs.h" 7 | 8 | Opreturn do_iload(OPENV *env) 9 | { 10 | printf(" %d", TO_CHAR(env->pc)); 11 | ushort index = (ushort)(TO_CHAR(env->pc)); 12 | ILOAD(env, index); 13 | 14 | INC_PC(env->pc); 15 | RETURNV; 16 | } 17 | Opreturn do_lload(OPENV *env) 18 | { 19 | PRINTSD(TO_CHAR(env->pc)); 20 | ushort index = (ushort)(TO_CHAR(env->pc)); 21 | LLOAD(env, index); 22 | 23 | INC_PC(env->pc); 24 | RETURNV; 25 | } 26 | Opreturn do_fload(OPENV *env) 27 | { 28 | PRINTSD(TO_CHAR(env->pc)); 29 | ushort index = (ushort)(TO_CHAR(env->pc)); 30 | FLOAD(env, index); 31 | 32 | INC_PC(env->pc); 33 | RETURNV; 34 | } 35 | Opreturn do_dload(OPENV *env) 36 | { 37 | PRINTSD(TO_CHAR(env->pc)); 38 | ushort index = (ushort)(TO_CHAR(env->pc)); 39 | DLOAD(env, index); 40 | 41 | INC_PC(env->pc); 42 | RETURNV; 43 | } 44 | Opreturn do_aload(OPENV *env) 45 | { 46 | PRINTSD(TO_CHAR(env->pc)); 47 | ushort index = (ushort)(TO_CHAR(env->pc)); 48 | ALOAD(env, index); 49 | 50 | INC_PC(env->pc); 51 | RETURNV; 52 | } 53 | Opreturn do_iload_0(OPENV *env) 54 | { 55 | ILOAD(env, 0); 56 | RETURNV; 57 | } 58 | Opreturn do_iload_1(OPENV *env) 59 | { 60 | ILOAD(env, 1); 61 | RETURNV; 62 | } 63 | Opreturn do_iload_2(OPENV *env) 64 | { 65 | ILOAD(env, 2); 66 | RETURNV; 67 | } 68 | Opreturn do_iload_3(OPENV *env) 69 | { 70 | ILOAD(env, 3); 71 | RETURNV; 72 | } 73 | Opreturn do_lload_0(OPENV *env) 74 | { 75 | LLOAD(env, 0); 76 | RETURNV; 77 | } 78 | Opreturn do_lload_1(OPENV *env) 79 | { 80 | LLOAD(env, 1); 81 | RETURNV; 82 | } 83 | Opreturn do_lload_2(OPENV *env) 84 | { 85 | LLOAD(env, 2); 86 | RETURNV; 87 | } 88 | Opreturn do_lload_3(OPENV *env) 89 | { 90 | LLOAD(env, 3); 91 | RETURNV; 92 | } 93 | Opreturn do_fload_0(OPENV *env) 94 | { 95 | FLOAD(env, 0); 96 | RETURNV; 97 | } 98 | Opreturn do_fload_1(OPENV *env) 99 | { 100 | FLOAD(env, 1); 101 | RETURNV; 102 | } 103 | Opreturn do_fload_2(OPENV *env) 104 | { 105 | FLOAD(env, 2); 106 | RETURNV; 107 | } 108 | Opreturn do_fload_3(OPENV *env) 109 | { 110 | FLOAD(env, 3); 111 | RETURNV; 112 | } 113 | Opreturn do_dload_0(OPENV *env) 114 | { 115 | DLOAD(env, 0); 116 | RETURNV; 117 | } 118 | Opreturn do_dload_1(OPENV *env) 119 | { 120 | DLOAD(env, 1); 121 | RETURNV; 122 | } 123 | Opreturn do_dload_2(OPENV *env) 124 | { 125 | DLOAD(env, 2); 126 | RETURNV; 127 | } 128 | Opreturn do_dload_3(OPENV *env) 129 | { 130 | DLOAD(env, 3); 131 | RETURNV; 132 | } 133 | Opreturn do_aload_0(OPENV *env) 134 | { 135 | ALOAD(env, 0); 136 | RETURNV; 137 | } 138 | Opreturn do_aload_1(OPENV *env) 139 | { 140 | ALOAD(env, 1); 141 | RETURNV; 142 | } 143 | Opreturn do_aload_2(OPENV *env) 144 | { 145 | ALOAD(env, 2); 146 | RETURNV; 147 | } 148 | Opreturn do_aload_3(OPENV *env) 149 | { 150 | ALOAD(env, 3); 151 | RETURNV; 152 | } 153 | Opreturn do_iaload(OPENV *env) 154 | { 155 | XALOADI(env, int); 156 | RETURNV; 157 | } 158 | Opreturn do_laload(OPENV *env) 159 | { 160 | XALOADL(env, long); 161 | RETURNV; 162 | } 163 | Opreturn do_faload(OPENV *env) 164 | { 165 | XALOAD(env, float); 166 | RETURNV; 167 | } 168 | Opreturn do_daload(OPENV *env) 169 | { 170 | XALOADL(env, double); 171 | RETURNV; 172 | } 173 | Opreturn do_aaload(OPENV *env) 174 | { 175 | XALOAD(env, Reference); 176 | RETURNV; 177 | } 178 | Opreturn do_baload(OPENV *env) 179 | { 180 | XALOADI(env, char); 181 | RETURNV; 182 | } 183 | Opreturn do_caload(OPENV *env) 184 | { 185 | XALOADI(env, char); 186 | RETURNV; 187 | } 188 | Opreturn do_saload(OPENV *env) 189 | { 190 | XALOADI(env, short); 191 | RETURNV; 192 | } 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_math.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_MATH_C 10 | #define OP_MATH_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_iadd(OPENV *env) 16 | { 17 | IADD(env); 18 | RETURNV; 19 | } 20 | Opreturn do_ladd(OPENV *env) 21 | { 22 | LADD(env); 23 | RETURNV; 24 | } 25 | Opreturn do_fadd(OPENV *env) 26 | { 27 | FADD(env); 28 | RETURNV; 29 | } 30 | Opreturn do_dadd(OPENV *env) 31 | { 32 | DADD(env); 33 | RETURNV; 34 | } 35 | Opreturn do_isub(OPENV *env) 36 | { 37 | ISUB(env); 38 | RETURNV; 39 | } 40 | Opreturn do_lsub(OPENV *env) 41 | { 42 | LSUB(env); 43 | RETURNV; 44 | } 45 | Opreturn do_fsub(OPENV *env) 46 | { 47 | FSUB(env); 48 | RETURNV; 49 | } 50 | Opreturn do_dsub(OPENV *env) 51 | { 52 | DSUB(env); 53 | RETURNV; 54 | } 55 | Opreturn do_imul(OPENV *env) 56 | { 57 | IMUL(env); 58 | RETURNV; 59 | } 60 | Opreturn do_lmul(OPENV *env) 61 | { 62 | LMUL(env); 63 | RETURNV; 64 | } 65 | Opreturn do_fmul(OPENV *env) 66 | { 67 | FMUL(env); 68 | RETURNV; 69 | } 70 | Opreturn do_dmul(OPENV *env) 71 | { 72 | DMUL(env); 73 | RETURNV; 74 | } 75 | Opreturn do_idiv(OPENV *env) 76 | { 77 | IDIV(env); 78 | RETURNV; 79 | } 80 | Opreturn do_ldiv(OPENV *env) 81 | { 82 | LDIV(env); 83 | RETURNV; 84 | } 85 | Opreturn do_fdiv(OPENV *env) 86 | { 87 | FDIV(env); 88 | RETURNV; 89 | } 90 | Opreturn do_ddiv(OPENV *env) 91 | { 92 | DDIV(env); 93 | RETURNV; 94 | } 95 | Opreturn do_irem(OPENV *env) 96 | { 97 | IREM(env); 98 | RETURNV; 99 | } 100 | Opreturn do_lrem(OPENV *env) 101 | { 102 | LREM(env); 103 | RETURNV; 104 | } 105 | Opreturn do_frem(OPENV *env) 106 | { 107 | FREM(env); 108 | RETURNV; 109 | } 110 | Opreturn do_drem(OPENV *env) 111 | { 112 | DREM(env); 113 | RETURNV; 114 | } 115 | Opreturn do_ineg(OPENV *env) 116 | { 117 | INEG(env); 118 | RETURNV; 119 | } 120 | Opreturn do_lneg(OPENV *env) 121 | { 122 | LNEG(env); 123 | RETURNV; 124 | } 125 | Opreturn do_fneg(OPENV *env) 126 | { 127 | FNEG(env); 128 | RETURNV; 129 | } 130 | Opreturn do_dneg(OPENV *env) 131 | { 132 | DNEG(env); 133 | RETURNV; 134 | } 135 | Opreturn do_ishl(OPENV *env) 136 | { 137 | ISHL(env); 138 | RETURNV; 139 | } 140 | Opreturn do_lshl(OPENV *env) 141 | { 142 | LSHL(env); 143 | RETURNV; 144 | } 145 | Opreturn do_ishr(OPENV *env) 146 | { 147 | ISHR(env); 148 | RETURNV; 149 | } 150 | Opreturn do_lshr(OPENV *env) 151 | { 152 | LSHR(env); 153 | RETURNV; 154 | } 155 | Opreturn do_iushr(OPENV *env) 156 | { 157 | IUSHR(env); 158 | RETURNV; 159 | } 160 | Opreturn do_lushr(OPENV *env) 161 | { 162 | LUSHR(env); 163 | RETURNV; 164 | } 165 | Opreturn do_iand(OPENV *env) 166 | { 167 | IAND(env); 168 | RETURNV; 169 | } 170 | Opreturn do_land(OPENV *env) 171 | { 172 | LAND(env); 173 | RETURNV; 174 | } 175 | Opreturn do_ior(OPENV *env) 176 | { 177 | IOR(env); 178 | RETURNV; 179 | } 180 | Opreturn do_lor(OPENV *env) 181 | { 182 | LOR(env); 183 | RETURNV; 184 | } 185 | Opreturn do_ixor(OPENV *env) 186 | { 187 | IXOR(env); 188 | RETURNV; 189 | } 190 | Opreturn do_lxor(OPENV *env) 191 | { 192 | LXOR(env); 193 | RETURNV; 194 | } 195 | Opreturn do_iinc(OPENV *env) 196 | { 197 | IINC(env); 198 | RETURNV; 199 | } 200 | 201 | #endif 202 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_obj.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_OBJ_C 10 | #define OP_OBJ_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | extern void callThisClassMethod(OPENV *env, ushort mindex); 16 | extern Class* findLoadedClass(const char* class_name, int name_len); 17 | extern void callOtherClassMethod(OPENV *env, CONSTANT_Methodref_info* method_ref); 18 | extern Class* systemLoadClass(CONSTANT_Utf8_info* class_utf8_info); 19 | extern Class* systemLoadClassRecursive(OPENV *env, CONSTANT_Utf8_info* class_utf8_info); 20 | extern void resolveClassInstanceField(Class* caller_class, CONSTANT_Fieldref_info **pfield_ref); 21 | extern void resolveClassMethod(Class* caller_class, CONSTANT_Methodref_info **pmethod_ref); 22 | extern void resolveClassSpecialMethod(Class* caller_class, CONSTANT_Methodref_info **pmethod_ref); 23 | extern void callClassSpecialMethod(OPENV *env, int mindex); 24 | 25 | Opreturn do_getstatic(OPENV *env) 26 | { 27 | ArrayRef arr_ref; 28 | CONSTANT_Fieldref_info *fieldref; 29 | Class *pclass; 30 | cp_info cp; 31 | short index = TO_SHORT(env->pc); 32 | PRINTSD(TO_SHORT(env->pc)); 33 | cp = env->current_class->constant_pool; 34 | fieldref = (CONSTANT_Fieldref_info*)(cp[index]); 35 | 36 | if (0 == fieldref->ftype) { 37 | // TODO: resolve this fields 38 | resolveClassStaticField(env->current_class, &fieldref); 39 | } 40 | 41 | pclass = ((CONSTANT_Class_info*)(cp[fieldref->class_index]))->pclass; 42 | 43 | switch (fieldref->ftype) { 44 | case 'B': // byte 45 | OP_GET_STATIC_FIELDI(pclass, fieldref->findex, byte); 46 | break; 47 | case 'C': // char 48 | OP_GET_STATIC_FIELDI(pclass, fieldref->findex, char); 49 | break; 50 | case 'S': // short 51 | OP_GET_STATIC_FIELDI(pclass, fieldref->findex, short); 52 | break; 53 | case 'Z': // boolean 54 | OP_GET_STATIC_FIELDI(pclass, fieldref->findex, int); 55 | break; 56 | case 'I': // integer 57 | OP_GET_STATIC_FIELDI(pclass, fieldref->findex, int); 58 | break; 59 | case 'F': // float 60 | OP_GET_STATIC_FIELDF(pclass, fieldref->findex, float); 61 | break; 62 | case '[': // reference 63 | arr_ref = *(ArrayRef*)(pclass->static_fields+(fieldref->findex<<2)); 64 | displayStaticFields(pclass); 65 | OP_GET_STATIC_FIELDR(pclass, fieldref->findex, ArrayRef); 66 | break; 67 | case 'L': // reference 68 | OP_GET_STATIC_FIELDR(pclass, fieldref->findex, Reference); 69 | break; 70 | case 'J': // long 71 | OP_GET_STATIC_FIELDL(pclass, fieldref->findex, long); 72 | break; 73 | case 'D': // double 74 | OP_GET_STATIC_FIELDL(pclass, fieldref->findex, double); 75 | break; 76 | default: 77 | printf("Error: getfield, ftype=%d\n", fieldref->ftype); 78 | exit(1); 79 | break; 80 | } 81 | 82 | INC2_PC(env->pc); 83 | } 84 | 85 | Opreturn do_putstatic(OPENV *env) 86 | { 87 | ArrayRef arr_ref; 88 | CONSTANT_Fieldref_info *fieldref; 89 | Class *pclass; 90 | cp_info cp; 91 | short index = TO_SHORT(env->pc); 92 | PRINTSD(TO_SHORT(env->pc)); 93 | cp = env->current_class->constant_pool; 94 | fieldref = (CONSTANT_Fieldref_info*)(cp[index]); 95 | 96 | 97 | if (0 == fieldref->ftype) { 98 | // TODO: resolve this fields 99 | resolveClassStaticField(env->current_class, &fieldref); 100 | } 101 | 102 | pclass = ((CONSTANT_Class_info*)(cp[fieldref->class_index]))->pclass; 103 | switch (fieldref->ftype) { 104 | case 'B': // byte 105 | OP_PUT_STATIC_FIELDI(pclass, fieldref->findex, byte); 106 | debug("static field: findex=%d, value=%d", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, byte)); 107 | break; 108 | case 'C': // char 109 | OP_PUT_STATIC_FIELDI(pclass, fieldref->findex, char); 110 | debug("static field: findex=%d, value=%d", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, char)); 111 | break; 112 | case 'S': // short 113 | OP_PUT_STATIC_FIELDI(pclass, fieldref->findex, short); 114 | debug("static field: findex=%d, value=%d", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, short)); 115 | break; 116 | case 'Z': // boolean 117 | OP_PUT_STATIC_FIELDI(pclass, fieldref->findex, int); 118 | debug("static field: findex=%d, value=%d", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, int)); 119 | break; 120 | case 'I': // integer 121 | OP_PUT_STATIC_FIELDI(pclass, fieldref->findex, int); 122 | debug("static field: findex=%d, value=%d", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, int)); 123 | break; 124 | case 'F': // float 125 | OP_PUT_STATIC_FIELDF(pclass, fieldref->findex, float); 126 | debug("static field: findex=%d, value=%f", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, float)); 127 | break; 128 | case '[': // reference 129 | OP_PUT_STATIC_FIELDR(pclass, fieldref->findex, ArrayRef); 130 | displayStaticFields(pclass); 131 | printf("###################put static#######################\n"); 132 | //system("pause"); 133 | break; 134 | case 'L': // reference 135 | OP_PUT_STATIC_FIELDR(pclass, fieldref->findex, Reference); 136 | break; 137 | case 'J': // long 138 | OP_PUT_STATIC_FIELDL(pclass, fieldref->findex, long); 139 | debug("static field: findex=%d, value=%ld", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, long)); 140 | break; 141 | case 'D': // double 142 | OP_PUT_STATIC_FIELDL(pclass, fieldref->findex, double); 143 | debug("static field: findex=%d, value=%lf", fieldref->findex, GET_STATIC_FIELD(pclass, fieldref->findex, double)); 144 | break; 145 | default: 146 | printf("Error: getfield, ftype=%d\n", fieldref->ftype); 147 | exit(1); 148 | break; 149 | } 150 | 151 | INC2_PC(env->pc); 152 | } 153 | Opreturn do_getfield(OPENV *env) 154 | { 155 | CONSTANT_Fieldref_info *fieldref; 156 | cp_info cp; 157 | Object *obj; 158 | short index = TO_SHORT(env->pc); 159 | PRINTSD(TO_SHORT(env->pc)); 160 | cp = env->current_class->constant_pool; 161 | fieldref = (CONSTANT_Fieldref_info*)(cp[index]); 162 | 163 | GET_STACKR(env->current_stack, obj, Reference); 164 | if (0 == fieldref->ftype) { 165 | // TODO: resolve this field 166 | resolveClassInstanceField(env->current_class, &fieldref); 167 | } 168 | 169 | switch (fieldref->ftype) { 170 | case 'B': // byte 171 | OP_GET_FIELDI(obj, fieldref->findex, byte); 172 | debug("get-field:findex=%d, value=%d, stackvalue=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, byte), PICK_STACK(env->current_stack, byte)); 173 | break; 174 | case 'C': // char 175 | OP_GET_FIELDI(obj, fieldref->findex, char); 176 | debug("get-field:findex=%d, value=%d, stackvalue=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, char), PICK_STACK(env->current_stack, char)); 177 | break; 178 | case 'S': // short 179 | OP_GET_FIELDI(obj, fieldref->findex, short); 180 | debug("get-field:findex=%d, value=%d, stackvalue=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, short), PICK_STACK(env->current_stack, short)); 181 | break; 182 | case 'Z': // boolean 183 | OP_GET_FIELDI(obj, fieldref->findex, char); 184 | debug("get-field:findex=%d, value=%d, stackvalue=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, char), PICK_STACK(env->current_stack, char)); 185 | break; 186 | case 'I': // integer 187 | debug("findex=%d, field=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, int)); 188 | OP_GET_FIELDI(obj, fieldref->findex, int); 189 | debug("get-field:findex=%d, value=%d, stackvalue=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, int), PICK_STACK(env->current_stack, int)); 190 | break; 191 | case 'F': // float 192 | OP_GET_FIELDI(obj, fieldref->findex, float); 193 | debug("get-field:value=%f, stackvalue=%f", GET_FIELD(obj, fieldref->findex, float), PICK_STACK(env->current_stack, float)); 194 | break; 195 | case '[': // reference 196 | case 'L': // reference 197 | OP_GET_FIELDR(obj, fieldref->findex, Reference); 198 | debug("get-field:value=%p, stackvalue=%p", GET_FIELD(obj, fieldref->findex, Reference), PICK_STACK(env->current_stack, Reference)); 199 | break; 200 | case 'J': // long 201 | OP_GET_FIELDL(obj, fieldref->findex, long); 202 | debug("get-field:value=%ld, stackvalue=%ld", GET_FIELD(obj, fieldref->findex, long), PICK_STACK(env->current_stack, long)); 203 | break; 204 | case 'D': // double 205 | OP_GET_FIELDL(obj, fieldref->findex, double); 206 | debug("get-field:value=%lf, stackvalue=%lf", GET_FIELD(obj, fieldref->findex, double),PICK_STACK(env->current_stack, double)); 207 | break; 208 | default: 209 | printf("Error: getfield, ftype=%d\n", fieldref->ftype); 210 | exit(1); 211 | break; 212 | } 213 | 214 | INC2_PC(env->pc); 215 | } 216 | Opreturn do_putfield(OPENV *env) 217 | { 218 | CONSTANT_Fieldref_info *fieldref; 219 | CONSTANT_Class_info* class_info; 220 | cp_info cp; 221 | Object *obj; 222 | short index = TO_SHORT(env->pc); 223 | 224 | PRINTSD(TO_SHORT(env->pc)); 225 | 226 | cp = env->current_class->constant_pool; 227 | fieldref = (CONSTANT_Fieldref_info*)(cp[index]); 228 | class_info = (CONSTANT_Class_info*)(cp[fieldref->class_index]); 229 | 230 | if (0 == fieldref->ftype) { 231 | // TODO: resolve this field 232 | resolveClassInstanceField(env->current_class, &fieldref); 233 | } 234 | 235 | switch (fieldref->ftype) { 236 | case 'B': // byte 237 | OP_PUT_FIELDI(obj, fieldref->findex, byte); 238 | break; 239 | case 'C': // char 240 | OP_PUT_FIELDI(obj, fieldref->findex, char); 241 | break; 242 | case 'S': // short 243 | OP_PUT_FIELDI(obj, fieldref->findex, short); 244 | break; 245 | case 'Z': // boolean 246 | OP_PUT_FIELDI(obj, fieldref->findex, char); 247 | break; 248 | case 'I': // integer 249 | OP_PUT_FIELDI(obj, fieldref->findex, int); 250 | debug("findex=%d, field=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, int)); 251 | break; 252 | case 'F': // float 253 | OP_PUT_FIELDF(obj, fieldref->findex, float); 254 | debug("findex=%d, field=%d", fieldref->findex, GET_FIELD(obj, fieldref->findex, float)); 255 | break; 256 | case '[': // reference 257 | case 'L': // reference 258 | OP_PUT_FIELDR(obj, fieldref->findex, Reference); 259 | break; 260 | case 'J': // long 261 | OP_PUT_FIELDL(obj, fieldref->findex, long); 262 | break; 263 | case 'D': // double 264 | OP_PUT_FIELDL(obj, fieldref->findex, double); 265 | break; 266 | default: 267 | printf("\nError: getfield, ftype=%d\n", fieldref->ftype); 268 | exit(1); 269 | break; 270 | } 271 | INC2_PC(env->pc); 272 | } 273 | Opreturn do_invokevirtual(OPENV *env) 274 | { 275 | PRINTSD(TO_SHORT(env->pc)); 276 | short mindex = TO_SHORT(env->pc); 277 | INC2_PC(env->pc); 278 | 279 | callClassVirtualMethod(env, mindex); 280 | } 281 | Opreturn do_invokespecial(OPENV *env) 282 | { 283 | PRINTSD(TO_SHORT(env->pc)); 284 | short mindex = TO_SHORT(env->pc); 285 | INC2_PC(env->pc); 286 | 287 | callClassSpecialMethod(env, mindex); 288 | } 289 | Opreturn do_invokestatic(OPENV *env) 290 | { 291 | PRINTSD(TO_SHORT(env->pc)); 292 | short mindex = TO_SHORT(env->pc); 293 | INC2_PC(env->pc); 294 | callStaticClassMethod(env, mindex); 295 | } 296 | Opreturn do_invokeinterface(OPENV *env) 297 | { 298 | PRINTSD(TO_SHORT(env->pc)); 299 | INC2_PC(env->pc); 300 | } 301 | Opreturn do_invokedynamic(OPENV *env) 302 | { 303 | PRINTSD(TO_SHORT(env->pc)); 304 | INC2_PC(env->pc); 305 | } 306 | Opreturn do_new(OPENV *env) 307 | { 308 | Class* pclass; 309 | CONSTANT_Utf8_info* utf8_info; 310 | CONSTANT_Class_info* class_info; 311 | PRINTSD(TO_SHORT(env->pc)); 312 | short index = TO_SHORT(env->pc); 313 | Object *obj; 314 | INC2_PC(env->pc); 315 | 316 | if (env->current_class->this_class == index) { 317 | pclass = env->current_class; 318 | } else { 319 | // create other class 320 | class_info = (CONSTANT_Class_info*)(env->current_class->constant_pool[index]); 321 | utf8_info = (CONSTANT_Utf8_info*)(env->current_class->constant_pool[class_info->name_index]); 322 | printf("class = %s\n", utf8_info->bytes); 323 | utf8_info = (CONSTANT_Utf8_info*)(env->current_class->constant_pool[env->current_stack->method->name_index]); 324 | printf("method = %s\n", utf8_info->bytes); 325 | 326 | if (class_info->pclass == NULL) { 327 | debug("load pclass: %d", 2); 328 | utf8_info = (CONSTANT_Utf8_info*)(env->current_class->constant_pool[class_info->name_index]); 329 | pclass = class_info->pclass = findLoadedClass(utf8_info->bytes, utf8_info->length); 330 | debug("findLoadedClass pclass=%p", pclass); 331 | } else { 332 | pclass = class_info->pclass; 333 | } 334 | 335 | if (NULL == pclass) { 336 | pclass = class_info->pclass = systemLoadClassRecursive(env, utf8_info); 337 | debug("systemLoadClassRecursive pclass=%p", pclass); 338 | } 339 | } 340 | 341 | debug("goto new Object: class_index=%d, %p", pclass->this_class, pclass); 342 | printCurrentEnv(env, "after new:"); 343 | obj = newObject(env, pclass); 344 | printCurrentEnv(env, "before new:"); 345 | env->current_obj = obj; 346 | debug("new: obj=%p,pc=%p,sp=%p\n", obj, env->pc,env->current_stack->sp); 347 | PUSH_STACKR(env->current_stack, obj, Reference); 348 | printCurrentEnv(env, "afrer push obj:"); 349 | } 350 | 351 | Opreturn do_newarray(OPENV *env) 352 | { 353 | int arr_count; 354 | char arr_type; 355 | PRINTSD(TO_CHAR(env->pc)); 356 | arr_type = TO_CHAR(env->pc); 357 | GET_STACK(env->current_stack, arr_count, int); 358 | char *sp_old = env->current_stack->sp; 359 | PUSH_STACKR(env->current_stack, generalNewArray(arr_type, arr_count), ArrayRef); 360 | 361 | INC_PC(env->pc); 362 | } 363 | Opreturn do_anewarray(OPENV *env) 364 | { 365 | int arr_count; 366 | int arr_type_index = TO_SHORT(env->pc); 367 | PRINTSD(TO_SHORT(env->pc)); 368 | GET_STACK(env->current_stack, arr_count, int); 369 | PUSH_STACK(env->current_stack, newCArray_Reference(arr_type_index&0x10, arr_count, 1), ArrayRef); 370 | 371 | INC2_PC(env->pc); 372 | } 373 | Opreturn do_arraylength(OPENV *env) 374 | { 375 | OP_ARRAY_LENGTH(env); 376 | 377 | RETURNV; 378 | } 379 | Opreturn do_athrow(OPENV *env) 380 | { 381 | printf("[athrow] not implemented yet\n"); 382 | exit(1); 383 | RETURNV; 384 | } 385 | Opreturn do_checkcast(OPENV *env) 386 | { 387 | PRINTSD(TO_SHORT(env->pc)); 388 | INC2_PC(env->pc); 389 | } 390 | Opreturn do_instanceof(OPENV *env) 391 | { 392 | PRINTSD(TO_SHORT(env->pc)); 393 | INC2_PC(env->pc); 394 | } 395 | Opreturn do_monitorenter(OPENV *env) 396 | { 397 | printf("[monitorenter] not implemented yet\n"); 398 | exit(1); 399 | RETURNV; 400 | } 401 | Opreturn do_monitorexit(OPENV *env) 402 | { 403 | printf("[monitorexit] not implemented yet\n"); 404 | exit(1); 405 | RETURNV; 406 | } 407 | 408 | #endif 409 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_stack.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_STACK_C 10 | #define OP_STACK_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_pop(OPENV *env) 16 | { 17 | POP_STACK(env->current_stack); 18 | DEBUG_SP_DOWN(env->dbg); 19 | RETURNV; 20 | } 21 | Opreturn do_pop2(OPENV *env) 22 | { 23 | POP_STACKL(env->current_stack); 24 | DEBUG_SP_DOWNL(env->dbg); 25 | RETURNV; 26 | } 27 | Opreturn do_dup(OPENV *env) 28 | { 29 | char *csp = SP_DOWN_POS(env->current_stack); 30 | memcpy(env->current_stack->sp, csp, SZ_INT); 31 | SP_UP(env->current_stack); 32 | 33 | DEBUG_SP_UP(env->dbg); 34 | RETURNV; 35 | } 36 | Opreturn do_dup_x1(OPENV *env) 37 | { 38 | uchar *csp = SP_DOWN_POSL(env->current_stack); 39 | memmove(SP_DOWN_POS(env->current_stack), csp, SZ_LONG); 40 | memmove(csp, env->current_stack->sp, SZ_INT); 41 | SP_UP(env->current_stack); 42 | 43 | DEBUG_SP_UP(env->dbg); 44 | RETURNV; 45 | } 46 | Opreturn do_dup_x2(OPENV *env) 47 | { 48 | int offset = SZ_INT + SZ_LONG; 49 | uchar *csp = env->current_stack->sp - offset; 50 | memmove(csp, SP_DOWN_POSL(env->current_stack), offset); 51 | memmove(env->current_stack->sp, csp, SZ_INT); 52 | SP_UP(env->current_stack); 53 | 54 | DEBUG_SP_UP(env->dbg); 55 | RETURNV; 56 | } 57 | Opreturn do_dup2(OPENV *env) 58 | { 59 | uchar *csp = SP_DOWN_POSL(env->current_stack); 60 | memcpy(env->current_stack->sp, csp, SZ_LONG); 61 | SP_UPL(env->current_stack); 62 | 63 | DEBUG_SP_UPL(env->dbg); 64 | RETURNV; 65 | } 66 | Opreturn do_dup2_x1(OPENV *env) 67 | { 68 | uchar *csp = SP_DOWN_POSL(env->current_stack); 69 | uchar *csp2 = csp - SZ_INT; 70 | memcpy(env->current_stack->sp, csp, SZ_LONG); 71 | memcpy(SP_DOWN_POS(env->current_stack), csp2, SZ_INT); 72 | memcpy(csp2, env->current_stack->sp,SZ_LONG); 73 | SP_UPL(env->current_stack); 74 | 75 | DEBUG_SP_UPL(env->dbg); 76 | RETURNV; 77 | } 78 | Opreturn do_dup2_x2(OPENV *env) 79 | { 80 | uchar *csp = SP_DOWN_POSL(env->current_stack); 81 | uchar *csp2 = csp - SZ_LONG; 82 | memcpy(env->current_stack->sp, csp, SZ_LONG); 83 | memcpy(csp, csp2, SZ_LONG); 84 | memcpy(csp2, env->current_stack->sp, SZ_LONG); 85 | 86 | SP_UPL(env->current_stack); 87 | 88 | DEBUG_SP_UPL(env->dbg); 89 | RETURNV; 90 | } 91 | Opreturn do_swap(OPENV *env) 92 | { 93 | uchar c_tmp[4]; 94 | uchar *csp = SP_DOWN_POS(env->current_stack); 95 | memcpy(csp, c_tmp, SZ_INT); 96 | memcpy(SP_DOWN_POSL(env->current_stack), csp, SZ_INT); 97 | memcpy(c_tmp, csp, SZ_INT); 98 | RETURNV; 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/myjvm/opcode_actions/op_store.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OP_STORE_C 10 | #define OP_STORE_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn do_istore(OPENV *env) 16 | { 17 | PRINTSD(TO_CHAR(env->pc)); 18 | int i = (int)(TO_CHAR(env->pc)); 19 | ISTORE(env, i); 20 | INC_PC(env->pc); 21 | RETURNV; 22 | } 23 | Opreturn do_lstore(OPENV *env) 24 | { 25 | PRINTSD(TO_CHAR(env->pc)); 26 | int i = (int)(TO_CHAR(env->pc)); 27 | LSTORE(env, i); 28 | INC_PC(env->pc); 29 | RETURNV; 30 | } 31 | Opreturn do_fstore(OPENV *env) 32 | { 33 | PRINTSD(TO_CHAR(env->pc)); 34 | int i = (int)(TO_CHAR(env->pc)); 35 | FSTORE(env, i); 36 | INC_PC(env->pc); 37 | RETURNV; 38 | } 39 | Opreturn do_dstore(OPENV *env) 40 | { 41 | PRINTSD(TO_CHAR(env->pc)); 42 | int i = (int)(TO_CHAR(env->pc)); 43 | DSTORE(env, i); 44 | INC_PC(env->pc); 45 | RETURNV; 46 | } 47 | Opreturn do_astore(OPENV *env) 48 | { 49 | PRINTSD(TO_CHAR(env->pc)); 50 | int i = (int)(TO_CHAR(env->pc)); 51 | ASTORE(env, i); 52 | INC_PC(env->pc); 53 | RETURNV; 54 | } 55 | Opreturn do_istore_0(OPENV *env) 56 | { 57 | ISTORE(env, 0); 58 | RETURNV; 59 | } 60 | Opreturn do_istore_1(OPENV *env) 61 | { 62 | ISTORE(env, 1); 63 | RETURNV; 64 | } 65 | Opreturn do_istore_2(OPENV *env) 66 | { 67 | ISTORE(env, 2); 68 | RETURNV; 69 | } 70 | Opreturn do_istore_3(OPENV *env) 71 | { 72 | ISTORE(env, 3); 73 | RETURNV; 74 | } 75 | Opreturn do_lstore_0(OPENV *env) 76 | { 77 | LSTORE(env, 0); 78 | RETURNV; 79 | } 80 | Opreturn do_lstore_1(OPENV *env) 81 | { 82 | LSTORE(env, 1); 83 | RETURNV; 84 | } 85 | Opreturn do_lstore_2(OPENV *env) 86 | { 87 | LSTORE(env, 2); 88 | RETURNV; 89 | } 90 | Opreturn do_lstore_3(OPENV *env) 91 | { 92 | LSTORE(env, 3); 93 | RETURNV; 94 | } 95 | Opreturn do_fstore_0(OPENV *env) 96 | { 97 | FSTORE(env, 0); 98 | RETURNV; 99 | } 100 | Opreturn do_fstore_1(OPENV *env) 101 | { 102 | FSTORE(env, 1); 103 | RETURNV; 104 | } 105 | Opreturn do_fstore_2(OPENV *env) 106 | { 107 | FSTORE(env, 2); 108 | RETURNV; 109 | } 110 | Opreturn do_fstore_3(OPENV *env) 111 | { 112 | FSTORE(env, 3); 113 | RETURNV; 114 | } 115 | Opreturn do_dstore_0(OPENV *env) 116 | { 117 | DSTORE(env, 0); 118 | RETURNV; 119 | } 120 | Opreturn do_dstore_1(OPENV *env) 121 | { 122 | DSTORE(env, 1); 123 | RETURNV; 124 | } 125 | Opreturn do_dstore_2(OPENV *env) 126 | { 127 | DSTORE(env, 2); 128 | RETURNV; 129 | } 130 | Opreturn do_dstore_3(OPENV *env) 131 | { 132 | DSTORE(env, 3); 133 | RETURNV; 134 | } 135 | Opreturn do_astore_0(OPENV *env) 136 | { 137 | ASTORE(env, 0); 138 | RETURNV; 139 | } 140 | Opreturn do_astore_1(OPENV *env) 141 | { 142 | ASTORE(env, 1); 143 | RETURNV; 144 | } 145 | Opreturn do_astore_2(OPENV *env) 146 | { 147 | ASTORE(env, 2); 148 | RETURNV; 149 | } 150 | Opreturn do_astore_3(OPENV *env) 151 | { 152 | ASTORE(env, 3); 153 | RETURNV; 154 | } 155 | Opreturn do_iastore(OPENV *env) 156 | { 157 | IASTORE(env, int); 158 | RETURNV; 159 | } 160 | Opreturn do_lastore(OPENV *env) 161 | { 162 | XASTOREL(env, long); 163 | RETURNV; 164 | } 165 | Opreturn do_fastore(OPENV *env) 166 | { 167 | XASTORE(env, float); 168 | RETURNV; 169 | } 170 | Opreturn do_dastore(OPENV *env) 171 | { 172 | XASTOREL(env, double); 173 | RETURNV; 174 | } 175 | Opreturn do_aastore(OPENV *env) 176 | { 177 | XASTORE(env, Reference); 178 | RETURNV; 179 | } 180 | Opreturn do_bastore(OPENV *env) 181 | { 182 | XASTORE(env, char); 183 | RETURNV; 184 | } 185 | Opreturn do_castore(OPENV *env) 186 | { 187 | CASTORE(env, char); 188 | RETURNV; 189 | } 190 | Opreturn do_sastore(OPENV *env) 191 | { 192 | XASTORE(env, short); 193 | RETURNV; 194 | } 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /src/myjvm/opcode_pre.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef OPCODE_PRE_C 10 | #define OPCODE_PRE_C 11 | 12 | #include "opcode.h" 13 | #include "op_core.h" 14 | 15 | Opreturn pre_nop(OPENV *env) 16 | { 17 | RETURNV; 18 | } 19 | Opreturn pre_aconst_nul(OPENV *env) 20 | { 21 | RETURNV; 22 | } 23 | Opreturn pre_iconst_m1(OPENV *env) 24 | { 25 | RETURNV; 26 | } 27 | Opreturn pre_iconst_0(OPENV *env) 28 | { 29 | RETURNV; 30 | } 31 | Opreturn pre_iconst_1(OPENV *env) 32 | { 33 | RETURNV; 34 | } 35 | Opreturn pre_iconst_2(OPENV *env) 36 | { 37 | RETURNV; 38 | } 39 | Opreturn pre_iconst_3(OPENV *env) 40 | { 41 | RETURNV; 42 | } 43 | Opreturn pre_iconst_4(OPENV *env) 44 | { 45 | RETURNV; 46 | } 47 | Opreturn pre_iconst_5(OPENV *env) 48 | { 49 | RETURNV; 50 | } 51 | Opreturn pre_lconst_0(OPENV *env) 52 | { 53 | RETURNV; 54 | } 55 | Opreturn pre_lconst_1(OPENV *env) 56 | { 57 | RETURNV; 58 | } 59 | Opreturn pre_fconst_0(OPENV *env) 60 | { 61 | RETURNV; 62 | } 63 | Opreturn pre_fconst_1(OPENV *env) 64 | { 65 | RETURNV; 66 | } 67 | Opreturn pre_fconst_2(OPENV *env) 68 | { 69 | RETURNV; 70 | } 71 | Opreturn pre_dconst_0(OPENV *env) 72 | { 73 | RETURNV; 74 | } 75 | Opreturn pre_dconst_1(OPENV *env) 76 | { 77 | RETURNV; 78 | } 79 | Opreturn pre_bipush(OPENV *env) 80 | { 81 | PRINTD(TO_CHAR(env->pc)); 82 | INC_PC(env->pc); 83 | RETURNV; 84 | } 85 | Opreturn pre_sipush(OPENV *env) 86 | { 87 | BE2LE2(env->pc); 88 | PRINTD(TO_SHORT(env->pc)); 89 | INC2_PC(env->pc); 90 | 91 | } 92 | Opreturn pre_ldc(OPENV *env) 93 | { 94 | PRINTSD(TO_CHAR(env->pc)); 95 | INC_PC(env->pc); 96 | RETURNV; 97 | } 98 | Opreturn pre_ldc_w(OPENV *env) 99 | { 100 | BE2LE2(env->pc); 101 | PRINTSD(TO_SHORT(env->pc)); 102 | INC2_PC(env->pc); 103 | RETURNV; 104 | } 105 | Opreturn pre_ldc2_w(OPENV *env) 106 | { 107 | BE2LE2(env->pc); 108 | PRINTSD(TO_SHORT(env->pc)); 109 | INC2_PC(env->pc); 110 | RETURNV; 111 | } 112 | Opreturn pre_iload(OPENV *env) 113 | { 114 | PRINTSD(TO_CHAR(env->pc)); 115 | INC_PC(env->pc); 116 | RETURNV; 117 | } 118 | Opreturn pre_lload(OPENV *env) 119 | { 120 | PRINTSD(TO_CHAR(env->pc)); 121 | INC_PC(env->pc); 122 | RETURNV; 123 | } 124 | Opreturn pre_fload(OPENV *env) 125 | { 126 | PRINTSD(TO_CHAR(env->pc)); 127 | INC_PC(env->pc); 128 | RETURNV; 129 | } 130 | Opreturn pre_dload(OPENV *env) 131 | { 132 | PRINTSD(TO_CHAR(env->pc)); 133 | INC_PC(env->pc); 134 | RETURNV; 135 | } 136 | Opreturn pre_aload(OPENV *env) 137 | { 138 | PRINTSD(TO_CHAR(env->pc)); 139 | INC_PC(env->pc); 140 | RETURNV; 141 | } 142 | Opreturn pre_iload_0(OPENV *env) 143 | { 144 | RETURNV; 145 | } 146 | Opreturn pre_iload_1(OPENV *env) 147 | { 148 | RETURNV; 149 | } 150 | Opreturn pre_iload_2(OPENV *env) 151 | { 152 | RETURNV; 153 | } 154 | Opreturn pre_iload_3(OPENV *env) 155 | { 156 | RETURNV; 157 | } 158 | Opreturn pre_lload_0(OPENV *env) 159 | { 160 | RETURNV; 161 | } 162 | Opreturn pre_lload_1(OPENV *env) 163 | { 164 | RETURNV; 165 | } 166 | Opreturn pre_lload_2(OPENV *env) 167 | { 168 | RETURNV; 169 | } 170 | Opreturn pre_lload_3(OPENV *env) 171 | { 172 | RETURNV; 173 | } 174 | Opreturn pre_fload_0(OPENV *env) 175 | { 176 | RETURNV; 177 | } 178 | Opreturn pre_fload_1(OPENV *env) 179 | { 180 | RETURNV; 181 | } 182 | Opreturn pre_fload_2(OPENV *env) 183 | { 184 | RETURNV; 185 | } 186 | Opreturn pre_fload_3(OPENV *env) 187 | { 188 | RETURNV; 189 | } 190 | Opreturn pre_dload_0(OPENV *env) 191 | { 192 | RETURNV; 193 | } 194 | Opreturn pre_dload_1(OPENV *env) 195 | { 196 | RETURNV; 197 | } 198 | Opreturn pre_dload_2(OPENV *env) 199 | { 200 | RETURNV; 201 | } 202 | Opreturn pre_dload_3(OPENV *env) 203 | { 204 | RETURNV; 205 | } 206 | Opreturn pre_aload_0(OPENV *env) 207 | { 208 | RETURNV; 209 | } 210 | Opreturn pre_aload_1(OPENV *env) 211 | { 212 | RETURNV; 213 | } 214 | Opreturn pre_aload_2(OPENV *env) 215 | { 216 | RETURNV; 217 | } 218 | Opreturn pre_aload_3(OPENV *env) 219 | { 220 | RETURNV; 221 | } 222 | Opreturn pre_iaload(OPENV *env) 223 | { 224 | RETURNV; 225 | } 226 | Opreturn pre_laload(OPENV *env) 227 | { 228 | RETURNV; 229 | } 230 | Opreturn pre_faload(OPENV *env) 231 | { 232 | RETURNV; 233 | } 234 | Opreturn pre_daload(OPENV *env) 235 | { 236 | RETURNV; 237 | } 238 | Opreturn pre_aaload(OPENV *env) 239 | { 240 | RETURNV; 241 | } 242 | Opreturn pre_baload(OPENV *env) 243 | { 244 | RETURNV; 245 | } 246 | Opreturn pre_caload(OPENV *env) 247 | { 248 | RETURNV; 249 | } 250 | Opreturn pre_saload(OPENV *env) 251 | { 252 | RETURNV; 253 | } 254 | Opreturn pre_istore(OPENV *env) 255 | { 256 | PRINTSD(TO_CHAR(env->pc)); 257 | INC_PC(env->pc); 258 | RETURNV; 259 | } 260 | Opreturn pre_lstore(OPENV *env) 261 | { 262 | PRINTSD(TO_CHAR(env->pc)); 263 | INC_PC(env->pc); 264 | RETURNV; 265 | } 266 | Opreturn pre_fstore(OPENV *env) 267 | { 268 | PRINTSD(TO_CHAR(env->pc)); 269 | INC_PC(env->pc); 270 | RETURNV; 271 | } 272 | Opreturn pre_dstore(OPENV *env) 273 | { 274 | PRINTSD(TO_CHAR(env->pc)); 275 | INC_PC(env->pc); 276 | RETURNV; 277 | } 278 | Opreturn pre_astore(OPENV *env) 279 | { 280 | PRINTSD(TO_CHAR(env->pc)); 281 | INC_PC(env->pc); 282 | RETURNV; 283 | } 284 | Opreturn pre_istore_0(OPENV *env) 285 | { 286 | RETURNV; 287 | } 288 | Opreturn pre_istore_1(OPENV *env) 289 | { 290 | RETURNV; 291 | } 292 | Opreturn pre_istore_2(OPENV *env) 293 | { 294 | RETURNV; 295 | } 296 | Opreturn pre_istore_3(OPENV *env) 297 | { 298 | RETURNV; 299 | } 300 | Opreturn pre_lstore_0(OPENV *env) 301 | { 302 | RETURNV; 303 | } 304 | Opreturn pre_lstore_1(OPENV *env) 305 | { 306 | RETURNV; 307 | } 308 | Opreturn pre_lstore_2(OPENV *env) 309 | { 310 | RETURNV; 311 | } 312 | Opreturn pre_lstore_3(OPENV *env) 313 | { 314 | RETURNV; 315 | } 316 | Opreturn pre_fstore_0(OPENV *env) 317 | { 318 | RETURNV; 319 | } 320 | Opreturn pre_fstore_1(OPENV *env) 321 | { 322 | RETURNV; 323 | } 324 | Opreturn pre_fstore_2(OPENV *env) 325 | { 326 | RETURNV; 327 | } 328 | Opreturn pre_fstore_3(OPENV *env) 329 | { 330 | RETURNV; 331 | } 332 | Opreturn pre_dstore_0(OPENV *env) 333 | { 334 | RETURNV; 335 | } 336 | Opreturn pre_dstore_1(OPENV *env) 337 | { 338 | RETURNV; 339 | } 340 | Opreturn pre_dstore_2(OPENV *env) 341 | { 342 | RETURNV; 343 | } 344 | Opreturn pre_dstore_3(OPENV *env) 345 | { 346 | RETURNV; 347 | } 348 | Opreturn pre_astore_0(OPENV *env) 349 | { 350 | RETURNV; 351 | } 352 | Opreturn pre_astore_1(OPENV *env) 353 | { 354 | RETURNV; 355 | } 356 | Opreturn pre_astore_2(OPENV *env) 357 | { 358 | RETURNV; 359 | } 360 | Opreturn pre_astore_3(OPENV *env) 361 | { 362 | RETURNV; 363 | } 364 | Opreturn pre_iastore(OPENV *env) 365 | { 366 | RETURNV; 367 | } 368 | Opreturn pre_lastore(OPENV *env) 369 | { 370 | RETURNV; 371 | } 372 | Opreturn pre_fastore(OPENV *env) 373 | { 374 | RETURNV; 375 | } 376 | Opreturn pre_dastore(OPENV *env) 377 | { 378 | RETURNV; 379 | } 380 | Opreturn pre_aastore(OPENV *env) 381 | { 382 | RETURNV; 383 | } 384 | Opreturn pre_bastore(OPENV *env) 385 | { 386 | RETURNV; 387 | } 388 | Opreturn pre_castore(OPENV *env) 389 | { 390 | RETURNV; 391 | } 392 | Opreturn pre_sastore(OPENV *env) 393 | { 394 | RETURNV; 395 | } 396 | Opreturn pre_pop(OPENV *env) 397 | { 398 | RETURNV; 399 | } 400 | Opreturn pre_pop2(OPENV *env) 401 | { 402 | RETURNV; 403 | } 404 | Opreturn pre_dup(OPENV *env) 405 | { 406 | RETURNV; 407 | } 408 | Opreturn pre_dup_x1(OPENV *env) 409 | { 410 | RETURNV; 411 | } 412 | Opreturn pre_dup_x2(OPENV *env) 413 | { 414 | RETURNV; 415 | } 416 | Opreturn pre_dup2(OPENV *env) 417 | { 418 | RETURNV; 419 | } 420 | Opreturn pre_dup2_x1(OPENV *env) 421 | { 422 | RETURNV; 423 | } 424 | Opreturn pre_dup2_x2(OPENV *env) 425 | { 426 | RETURNV; 427 | } 428 | Opreturn pre_swap(OPENV *env) 429 | { 430 | RETURNV; 431 | } 432 | Opreturn pre_iadd(OPENV *env) 433 | { 434 | RETURNV; 435 | } 436 | Opreturn pre_ladd(OPENV *env) 437 | { 438 | RETURNV; 439 | } 440 | Opreturn pre_fadd(OPENV *env) 441 | { 442 | RETURNV; 443 | } 444 | Opreturn pre_dadd(OPENV *env) 445 | { 446 | RETURNV; 447 | } 448 | Opreturn pre_isub(OPENV *env) 449 | { 450 | RETURNV; 451 | } 452 | Opreturn pre_lsub(OPENV *env) 453 | { 454 | RETURNV; 455 | } 456 | Opreturn pre_fsub(OPENV *env) 457 | { 458 | RETURNV; 459 | } 460 | Opreturn pre_dsub(OPENV *env) 461 | { 462 | RETURNV; 463 | } 464 | Opreturn pre_imul(OPENV *env) 465 | { 466 | RETURNV; 467 | } 468 | Opreturn pre_lmul(OPENV *env) 469 | { 470 | RETURNV; 471 | } 472 | Opreturn pre_fmul(OPENV *env) 473 | { 474 | RETURNV; 475 | } 476 | Opreturn pre_dmul(OPENV *env) 477 | { 478 | RETURNV; 479 | } 480 | Opreturn pre_idiv(OPENV *env) 481 | { 482 | RETURNV; 483 | } 484 | Opreturn pre_ldiv(OPENV *env) 485 | { 486 | RETURNV; 487 | } 488 | Opreturn pre_fdiv(OPENV *env) 489 | { 490 | RETURNV; 491 | } 492 | Opreturn pre_ddiv(OPENV *env) 493 | { 494 | RETURNV; 495 | } 496 | Opreturn pre_irem(OPENV *env) 497 | { 498 | RETURNV; 499 | } 500 | Opreturn pre_lrem(OPENV *env) 501 | { 502 | RETURNV; 503 | } 504 | Opreturn pre_frem(OPENV *env) 505 | { 506 | RETURNV; 507 | } 508 | Opreturn pre_drem(OPENV *env) 509 | { 510 | RETURNV; 511 | } 512 | Opreturn pre_ineg(OPENV *env) 513 | { 514 | RETURNV; 515 | } 516 | Opreturn pre_lneg(OPENV *env) 517 | { 518 | RETURNV; 519 | } 520 | Opreturn pre_fneg(OPENV *env) 521 | { 522 | RETURNV; 523 | } 524 | Opreturn pre_dneg(OPENV *env) 525 | { 526 | RETURNV; 527 | } 528 | Opreturn pre_ishl(OPENV *env) 529 | { 530 | RETURNV; 531 | } 532 | Opreturn pre_lshl(OPENV *env) 533 | { 534 | RETURNV; 535 | } 536 | Opreturn pre_ishr(OPENV *env) 537 | { 538 | RETURNV; 539 | } 540 | Opreturn pre_lshr(OPENV *env) 541 | { 542 | RETURNV; 543 | } 544 | Opreturn pre_iushr(OPENV *env) 545 | { 546 | RETURNV; 547 | } 548 | Opreturn pre_lushr(OPENV *env) 549 | { 550 | RETURNV; 551 | } 552 | Opreturn pre_iand(OPENV *env) 553 | { 554 | RETURNV; 555 | } 556 | Opreturn pre_land(OPENV *env) 557 | { 558 | RETURNV; 559 | } 560 | Opreturn pre_ior(OPENV *env) 561 | { 562 | RETURNV; 563 | } 564 | Opreturn pre_lor(OPENV *env) 565 | { 566 | RETURNV; 567 | } 568 | Opreturn pre_ixor(OPENV *env) 569 | { 570 | RETURNV; 571 | } 572 | Opreturn pre_lxor(OPENV *env) 573 | { 574 | RETURNV; 575 | } 576 | Opreturn pre_iinc(OPENV *env) 577 | { 578 | RETURNV; 579 | } 580 | Opreturn pre_i2l(OPENV *env) 581 | { 582 | RETURNV; 583 | } 584 | Opreturn pre_i2f(OPENV *env) 585 | { 586 | RETURNV; 587 | } 588 | Opreturn pre_i2d(OPENV *env) 589 | { 590 | RETURNV; 591 | } 592 | Opreturn pre_l2i(OPENV *env) 593 | { 594 | RETURNV; 595 | } 596 | Opreturn pre_l2f(OPENV *env) 597 | { 598 | RETURNV; 599 | } 600 | Opreturn pre_l2d(OPENV *env) 601 | { 602 | RETURNV; 603 | } 604 | Opreturn pre_f2i(OPENV *env) 605 | { 606 | RETURNV; 607 | } 608 | Opreturn pre_f2l(OPENV *env) 609 | { 610 | RETURNV; 611 | } 612 | Opreturn pre_f2d(OPENV *env) 613 | { 614 | RETURNV; 615 | } 616 | Opreturn pre_d2i(OPENV *env) 617 | { 618 | RETURNV; 619 | } 620 | Opreturn pre_d2l(OPENV *env) 621 | { 622 | RETURNV; 623 | } 624 | Opreturn pre_d2f(OPENV *env) 625 | { 626 | RETURNV; 627 | } 628 | Opreturn pre_i2b(OPENV *env) 629 | { 630 | RETURNV; 631 | } 632 | Opreturn pre_i2c(OPENV *env) 633 | { 634 | RETURNV; 635 | } 636 | Opreturn pre_i2s(OPENV *env) 637 | { 638 | RETURNV; 639 | } 640 | Opreturn pre_lcmp(OPENV *env) 641 | { 642 | RETURNV; 643 | } 644 | Opreturn pre_fcmpl(OPENV *env) 645 | { 646 | RETURNV; 647 | } 648 | Opreturn pre_fcmpg(OPENV *env) 649 | { 650 | RETURNV; 651 | } 652 | Opreturn pre_dcmpl(OPENV *env) 653 | { 654 | RETURNV; 655 | } 656 | Opreturn pre_dcmpg(OPENV *env) 657 | { 658 | RETURNV; 659 | } 660 | Opreturn pre_ifeq(OPENV *env) 661 | { 662 | BE2LE2(env->pc); 663 | PRINTSD(TO_SHORT(env->pc)); 664 | INC2_PC(env->pc); 665 | } 666 | Opreturn pre_ifne(OPENV *env) 667 | { 668 | BE2LE2(env->pc); 669 | PRINTSD(TO_SHORT(env->pc)); 670 | INC2_PC(env->pc); 671 | } 672 | Opreturn pre_iflt(OPENV *env) 673 | { 674 | BE2LE2(env->pc); 675 | PRINTSD(TO_SHORT(env->pc)); 676 | INC2_PC(env->pc); 677 | } 678 | Opreturn pre_ifge(OPENV *env) 679 | { 680 | BE2LE2(env->pc); 681 | PRINTSD(TO_SHORT(env->pc)); 682 | INC2_PC(env->pc); 683 | } 684 | Opreturn pre_ifgt(OPENV *env) 685 | { 686 | BE2LE2(env->pc); 687 | PRINTSD(TO_SHORT(env->pc)); 688 | INC2_PC(env->pc); 689 | } 690 | Opreturn pre_ifle(OPENV *env) 691 | { 692 | BE2LE2(env->pc); 693 | PRINTSD(TO_SHORT(env->pc)); 694 | INC2_PC(env->pc); 695 | } 696 | Opreturn pre_if_icmpeq(OPENV *env) 697 | { 698 | BE2LE2(env->pc); 699 | PRINTSD(TO_SHORT(env->pc)); 700 | INC2_PC(env->pc); 701 | } 702 | Opreturn pre_if_icmpne(OPENV *env) 703 | { 704 | BE2LE2(env->pc); 705 | PRINTSD(TO_SHORT(env->pc)); 706 | INC2_PC(env->pc); 707 | } 708 | Opreturn pre_if_icmplt(OPENV *env) 709 | { 710 | BE2LE2(env->pc); 711 | PRINTSD(TO_SHORT(env->pc)); 712 | INC2_PC(env->pc); 713 | } 714 | Opreturn pre_if_icmpge(OPENV *env) 715 | { 716 | BE2LE2(env->pc); 717 | PRINTSD(TO_SHORT(env->pc)); 718 | INC2_PC(env->pc); 719 | } 720 | Opreturn pre_if_icmpgt(OPENV *env) 721 | { 722 | BE2LE2(env->pc); 723 | PRINTSD(TO_SHORT(env->pc)); 724 | INC2_PC(env->pc); 725 | } 726 | Opreturn pre_if_icmple(OPENV *env) 727 | { 728 | BE2LE2(env->pc); 729 | PRINTSD(TO_SHORT(env->pc)); 730 | INC2_PC(env->pc); 731 | } 732 | Opreturn pre_if_acmpeq(OPENV *env) 733 | { 734 | BE2LE2(env->pc); 735 | PRINTSD(TO_SHORT(env->pc)); 736 | INC2_PC(env->pc); 737 | } 738 | Opreturn pre_if_acmpne(OPENV *env) 739 | { 740 | BE2LE2(env->pc); 741 | PRINTSD(TO_SHORT(env->pc)); 742 | INC2_PC(env->pc); 743 | } 744 | Opreturn pre_goto(OPENV *env) 745 | { 746 | BE2LE2(env->pc); 747 | PRINTSD(TO_SHORT(env->pc)); 748 | INC2_PC(env->pc); 749 | } 750 | Opreturn pre_jsr(OPENV *env) 751 | { 752 | BE2LE2(env->pc); 753 | PRINTSD(TO_SHORT(env->pc)); 754 | INC2_PC(env->pc); 755 | } 756 | Opreturn pre_ret(OPENV *env) 757 | { 758 | RETURNV; 759 | } 760 | Opreturn pre_tableswitch(OPENV *env) 761 | { 762 | int default_offset, low_offset, high_offset, i, switches, paddings; 763 | env->pc-=1; 764 | paddings = 4 - (env->pc - env->pc_start)%4; 765 | env->pc+=paddings; 766 | 767 | BE2LE4(env->pc); 768 | default_offset = TO_INT(env->pc); 769 | INC4_PC(env->pc); 770 | BE2LE4(env->pc); 771 | low_offset = TO_INT(env->pc); 772 | INC4_PC(env->pc); 773 | BE2LE4(env->pc); 774 | high_offset = TO_INT(env->pc); 775 | INC4_PC(env->pc); 776 | printf("default=%d,low=%d,high=%d\n", default_offset, low_offset, high_offset); 777 | switches = high_offset - low_offset +1; 778 | for(i=0;ipc); 780 | printf(" %d\n", TO_INT(env->pc)); 781 | INC4_PC(env->pc); 782 | } 783 | //exit(0); 784 | RETURNV; 785 | } 786 | Opreturn pre_lookupswitch(OPENV *env) 787 | { 788 | int default_offset, padding, i, key, npairs; 789 | PC pc_lookup_begin; 790 | env->pc-=1; 791 | pc_lookup_begin = env->pc; 792 | padding = (env->pc - env->pc_start)%4; 793 | if (padding > 0) { 794 | padding = 4 - padding; 795 | } 796 | env->pc+=padding; 797 | 798 | BE2LE4(env->pc); 799 | default_offset = TO_INT(env->pc); 800 | INC4_PC(env->pc); 801 | 802 | BE2LE4(env->pc); 803 | npairs = TO_INT(env->pc); 804 | INC4_PC(env->pc); 805 | debug("npairs=%d", npairs); 806 | for(i=0; i < npairs; i++) { 807 | BE2LE4(env->pc); 808 | printf("%d ", TO_INT(env->pc)); 809 | INC4_PC(env->pc); 810 | BE2LE4(env->pc); 811 | printf("%d\n", TO_INT(env->pc)); 812 | INC4_PC(env->pc); 813 | } 814 | 815 | RETURNV; 816 | } 817 | Opreturn pre_ireturn(OPENV *env) 818 | { 819 | RETURNV; 820 | } 821 | Opreturn pre_lreturn(OPENV *env) 822 | { 823 | RETURNV; 824 | } 825 | Opreturn pre_freturn(OPENV *env) 826 | { 827 | RETURNV; 828 | } 829 | Opreturn pre_dreturn(OPENV *env) 830 | { 831 | RETURNV; 832 | } 833 | Opreturn pre_areturn(OPENV *env) 834 | { 835 | RETURNV; 836 | } 837 | Opreturn pre_return(OPENV *env) 838 | { 839 | RETURNV; 840 | } 841 | Opreturn pre_getstatic(OPENV *env) 842 | { 843 | BE2LE2(env->pc); 844 | PRINTSD(TO_SHORT(env->pc)); 845 | INC2_PC(env->pc); 846 | } 847 | Opreturn pre_putstatic(OPENV *env) 848 | { 849 | BE2LE2(env->pc); 850 | PRINTSD(TO_SHORT(env->pc)); 851 | INC2_PC(env->pc); 852 | } 853 | Opreturn pre_getfield(OPENV *env) 854 | { 855 | BE2LE2(env->pc); 856 | PRINTSD(TO_SHORT(env->pc)); 857 | INC2_PC(env->pc); 858 | } 859 | Opreturn pre_putfield(OPENV *env) 860 | { 861 | BE2LE2(env->pc); 862 | PRINTSD(TO_SHORT(env->pc)); 863 | INC2_PC(env->pc); 864 | } 865 | Opreturn pre_invokevirtual(OPENV *env) 866 | { 867 | BE2LE2(env->pc); 868 | PRINTSD(TO_SHORT(env->pc)); 869 | INC2_PC(env->pc); 870 | } 871 | Opreturn pre_invokespecial(OPENV *env) 872 | { 873 | BE2LE2(env->pc); 874 | PRINTSD(TO_SHORT(env->pc)); 875 | INC2_PC(env->pc); 876 | } 877 | Opreturn pre_invokestatic(OPENV *env) 878 | { 879 | BE2LE2(env->pc); 880 | PRINTSD(TO_SHORT(env->pc)); 881 | INC2_PC(env->pc); 882 | } 883 | Opreturn pre_invokeinterface(OPENV *env) 884 | { 885 | BE2LE2(env->pc); 886 | PRINTSD(TO_SHORT(env->pc)); 887 | INC2_PC(env->pc); 888 | } 889 | Opreturn pre_invokedynamic(OPENV *env) 890 | { 891 | BE2LE2(env->pc); 892 | PRINTSD(TO_SHORT(env->pc)); 893 | INC2_PC(env->pc); 894 | } 895 | Opreturn pre_new(OPENV *env) 896 | { 897 | BE2LE2(env->pc); 898 | PRINTSD(TO_SHORT(env->pc)); 899 | INC2_PC(env->pc); 900 | } 901 | Opreturn pre_newarray(OPENV *env) 902 | { 903 | PRINTSD(TO_CHAR(env->pc)); 904 | INC_PC(env->pc); 905 | } 906 | Opreturn pre_anewarray(OPENV *env) 907 | { 908 | BE2LE2(env->pc); 909 | PRINTSD(TO_SHORT(env->pc)); 910 | INC2_PC(env->pc); 911 | } 912 | Opreturn pre_arraylength(OPENV *env) 913 | { 914 | RETURNV; 915 | } 916 | Opreturn pre_athrow(OPENV *env) 917 | { 918 | RETURNV; 919 | } 920 | Opreturn pre_checkcast(OPENV *env) 921 | { 922 | BE2LE2(env->pc); 923 | PRINTSD(TO_SHORT(env->pc)); 924 | INC2_PC(env->pc); 925 | } 926 | Opreturn pre_instanceof(OPENV *env) 927 | { 928 | BE2LE2(env->pc); 929 | PRINTSD(TO_SHORT(env->pc)); 930 | INC2_PC(env->pc); 931 | } 932 | Opreturn pre_monitorenter(OPENV *env) 933 | { 934 | RETURNV; 935 | } 936 | Opreturn pre_monitorexit(OPENV *env) 937 | { 938 | RETURNV; 939 | } 940 | Opreturn pre_wide(OPENV *env) 941 | { 942 | BE2LE4(env->pc); 943 | PRINTD(TO_INT(env->pc)); 944 | INC4_PC(env->pc); 945 | } 946 | Opreturn pre_multianewarray(OPENV *env) 947 | { 948 | BE2LE2(env->pc); 949 | PRINTD(TO_SHORT(env->pc)); 950 | INC2_PC(env->pc); 951 | } 952 | Opreturn pre_ifnull(OPENV *env) 953 | { 954 | BE2LE2(env->pc); 955 | PRINTD(TO_SHORT(env->pc)); 956 | INC2_PC(env->pc); 957 | } 958 | Opreturn pre_ifnonnull(OPENV *env) 959 | { 960 | BE2LE2(env->pc); 961 | PRINTD(TO_SHORT(env->pc)); 962 | INC2_PC(env->pc); 963 | } 964 | Opreturn pre_goto_w(OPENV *env) 965 | { 966 | BE2LE4(env->pc); 967 | PRINTD(TO_INT(env->pc)); 968 | INC4_PC(env->pc); 969 | } 970 | Opreturn pre_jsr_w(OPENV *env) 971 | { 972 | BE2LE4(env->pc); 973 | PRINTD(TO_INT(env->pc)); 974 | INC4_PC(env->pc); 975 | } 976 | Opreturn pre_breakpoint(OPENV *env) 977 | { 978 | PRINTD(TO_CHAR(env->pc)); 979 | } 980 | Opreturn pre_impdep1(OPENV *env) 981 | { 982 | PRINTD(TO_CHAR(env->pc)); 983 | } 984 | Opreturn pre_impdep2(OPENV *env) 985 | { 986 | PRINTD(TO_CHAR(env->pc)); 987 | } 988 | #endif 989 | -------------------------------------------------------------------------------- /src/myjvm/structs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef STRUCTS_H 10 | #define STRUCTS_H 11 | 12 | #include "constants.h" 13 | 14 | typedef struct _CONSTANT_Utf8_info { 15 | uchar tag; 16 | ushort length; 17 | char *bytes; 18 | } CONSTANT_Utf8_info; 19 | 20 | typedef struct _CONSTANT_String_info { 21 | uchar tag; 22 | ushort string_index; 23 | } CONSTANT_String_info; 24 | typedef struct _CONSTANT_Integer_info { 25 | uchar tag; 26 | int value; 27 | } CONSTANT_Integer_info; 28 | typedef struct _CONSTANT_Float_info { 29 | uchar tag; 30 | float value; 31 | } CONSTANT_Float_info; 32 | 33 | typedef struct _CONSTANT_Long_info { 34 | uchar tag; 35 | long value; 36 | } CONSTANT_Long_info; 37 | typedef struct _CONSTANT_Double_info { 38 | uchar tag; 39 | double value; 40 | } CONSTANT_Double_info; 41 | 42 | typedef struct _CONSTANT_NameAndType_info { 43 | uchar tag; 44 | ushort name_index; 45 | ushort descriptor_index; 46 | } CONSTANT_NameAndType_info; 47 | typedef struct _CONSTANT_MethodHandle_info { 48 | uchar tag; 49 | uchar reference_kind; 50 | ushort reference_index; 51 | } CONSTANT_MethodHandle_info; 52 | typedef struct _CONSTANT_MethodType_info { 53 | uchar tag; 54 | ushort descriptor_index; 55 | } CONSTANT_MethodType_info; 56 | typedef struct _CONSTANT_InvokeDynamic_info { 57 | uchar tag; 58 | ushort bootstrap_method_attr_index; 59 | ushort name_and_type_index; 60 | } CONSTANT_InvokeDynamic_info; 61 | 62 | typedef void** cp_info; 63 | 64 | typedef struct _attribute_info{ 65 | ushort attribute_name_index; 66 | uint attribute_length; 67 | uchar *info; 68 | } attribute_info; 69 | 70 | typedef struct _field_info{ 71 | ushort access_flags; 72 | ushort name_index; 73 | ushort descriptor_index; 74 | ushort attributes_count; 75 | attribute_info **attributes; 76 | ushort findex; // field index, [for fieldref] 77 | uchar ftype; // field type [for fieldref] 78 | } field_info; 79 | 80 | typedef struct _exception_table { 81 | ushort start_pc; 82 | ushort end_pc; 83 | ushort handler_pc; 84 | ushort catch_type; 85 | } exception_table; 86 | typedef struct _Code_attribute { 87 | ushort attribute_type; 88 | ushort max_stack; 89 | ushort max_locals; 90 | uint code_length; 91 | uchar *code; 92 | ushort exception_table_length; 93 | exception_table *exceptions; 94 | ushort attributes_count; 95 | attribute_info **attributes; 96 | } Code_attribute; 97 | 98 | typedef struct _method_info{ 99 | ushort access_flags; 100 | ushort name_index; 101 | ushort descriptor_index; 102 | ushort attributes_count; 103 | attribute_info **attributes; 104 | Code_attribute* code_attribute_addr; // address of code attribute 105 | ushort args_len; 106 | } method_info; 107 | 108 | typedef struct _ClassFile{ 109 | uint magic; 110 | ushort minor_version; 111 | ushort major_version; 112 | ushort constant_pool_count; 113 | cp_info constant_pool; 114 | ushort access_flags; 115 | ushort this_class; 116 | ushort super_class; 117 | ushort interface_count; 118 | ushort *interfaces; 119 | ushort fields_count; 120 | field_info **fields; 121 | ushort methods_count; 122 | method_info **methods; 123 | ushort attributes_count; 124 | attribute_info **attributes; 125 | struct _ClassFile *parent_class; 126 | int parent_fields_size; 127 | int fields_size; 128 | ushort static_field_size; 129 | char *static_fields; 130 | char clinit_runned; 131 | } ClassFile; 132 | 133 | typedef ClassFile Class; 134 | 135 | #include "method_table.h" 136 | 137 | typedef struct _CONSTANT_Fieldref_info { 138 | uchar tag; 139 | ushort class_index; 140 | ushort name_and_type_index; 141 | ushort findex; // field index, [for fieldref] 142 | uchar ftype; // field type [for fieldref] 143 | } CONSTANT_Fieldref_info; 144 | 145 | typedef struct _CONSTANT_Methodref_info { 146 | uchar tag; 147 | ushort class_index; 148 | ushort name_and_type_index; 149 | void* ref_addr; //real address, [for methodref] 150 | ushort args_len; 151 | Class *pclass; 152 | MethodTable *mtable; 153 | } CONSTANT_Methodref_info; 154 | 155 | typedef CONSTANT_Methodref_info CONSTANT_InterfaceMethodref_info; 156 | 157 | typedef struct _CONSTANT_Class_info { 158 | uchar tag; 159 | ushort name_index; 160 | Class* pclass; 161 | } CONSTANT_Class_info; 162 | 163 | typedef struct _line_number_table { 164 | ushort start_pc; 165 | ushort line_number; 166 | } line_number_table; 167 | 168 | typedef struct _LineNumberTable_attribute { 169 | ushort attribute_type; 170 | uint attribute_length; 171 | ushort table_length; 172 | line_number_table *tables; 173 | } LineNumberTable_attribute; 174 | 175 | typedef struct _local_variable_table { 176 | ushort start_pc; 177 | ushort length; 178 | ushort name_index; 179 | ushort descriptor_index; 180 | ushort index; 181 | } local_variable_table; 182 | typedef struct _LocalVariableTable_attribute { 183 | ushort attribute_type; 184 | uint attribute_length; 185 | ushort table_length; 186 | local_variable_table *tables; 187 | } LocalVariableTable_attribute; 188 | 189 | typedef struct _local_variable_type_table { 190 | ushort start_pc; 191 | ushort length; 192 | ushort name_index; 193 | ushort signature_index; 194 | ushort index; 195 | } local_variable_type_table; 196 | typedef struct _LocalVariableTypeTable_attribute { 197 | ushort attribute_type; 198 | uint attribute_length; 199 | ushort table_length; 200 | local_variable_type_table *tables; 201 | } LocalVariableTypeTable_attribute; 202 | 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /src/myjvm/test_jvm_types.c: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #include "jvm_debug.h" 10 | #include "op_core.h" 11 | #include 12 | 13 | void testArray() 14 | { 15 | CArray_int* arr = (CArray_int*)generalNewArray(10, 12); 16 | StackFrame* stf = newStackFrame(NULL, 10); 17 | OPENV* env = newOPENV(NULL); 18 | env->current_stack = stf; 19 | env->dbg = newDebugType(10, 20); 20 | PUSH_STACK(stf, arr, Reference); 21 | PUSH_STACK(stf, 0, int); 22 | PUSH_STACK(stf, 6, int); 23 | XASTORE(env, int); 24 | 25 | PUSH_STACK(stf, arr, Reference); 26 | PUSH_STACK(stf, 1, int); 27 | PUSH_STACK(stf, 9, int); 28 | XASTORE(env, int); 29 | 30 | debug("%d", arr->elements[0]); 31 | debug("%d", arr->elements[1]); 32 | 33 | PUSH_STACK(stf, arr, Reference); 34 | PUSH_STACK(stf, 0, int); 35 | XALOAD(env, int); 36 | debug("%d", PICK_STACK(stf, int)); 37 | 38 | PUSH_STACK(stf, arr, ArrayRef); 39 | OP_ARRAY_LENGTH(env); 40 | debug("%d", PICK_STACK(stf, int)); 41 | } 42 | 43 | 44 | void testFrameLocal() 45 | { 46 | StackFrame* stf = newTestStackFrame(NULL, 7, 10); 47 | int i; 48 | short s; 49 | long l; 50 | float f; 51 | double d; 52 | 53 | PUT_LOCAL(stf, 0, 3656, int); 54 | PUT_LOCAL(stf, 1, 16, short); 55 | PUT_LOCAL(stf, 2, 1234567, long); 56 | PUT_LOCAL(stf, 4, 2.5f, float); 57 | PUT_LOCAL(stf, 5, 12345.678, double); 58 | 59 | i = GET_LOCAL(stf, 0, int); 60 | s = GET_LOCAL(stf, 1, short); 61 | l = GET_LOCAL(stf, 2, long); 62 | f = GET_LOCAL(stf, 4, float); 63 | d = GET_LOCAL(stf, 5, double); 64 | 65 | printf("i=%d, s=%d, l=%ld, f=%f, d=%lf\n", i, s, l, f, d); 66 | } 67 | 68 | void tsetFrameStack() 69 | { 70 | StackFrame *stf = newTestStackFrame(NULL, 5, 10); 71 | int i; 72 | short s; 73 | long l; 74 | float f; 75 | double d; 76 | 77 | PUSH_STACK(stf, 2.67f, float); 78 | PUSH_STACK(stf, -1234, int); 79 | PUSH_STACK(stf, 1234567, long); 80 | PUSH_STACK(stf, 128, short); 81 | PUSH_STACK(stf, 4566.89, double); 82 | 83 | GET_STACK(stf, d, double); 84 | GET_STACK(stf, s, short); 85 | GET_STACK(stf, l, long); 86 | GET_STACK(stf, i, int); 87 | GET_STACK(stf, f, float); 88 | 89 | printf("d=%f, s=%d, l=%ld, i=%d, f=%f\n", d, s, l, i, f); 90 | } 91 | 92 | void testGetField(Class* pclass) 93 | { 94 | StackFrame *stf; 95 | OPENV *env; 96 | Object *obj; 97 | 98 | obj = newObject(NULL, pclass); 99 | 100 | stf = newStackFrame(NULL, 20); 101 | env = newOPENV(NULL); 102 | env->current_class = pclass; 103 | env->current_obj = obj; 104 | env->current_stack = stf; 105 | env->dbg = newDebugType(20, 256); 106 | 107 | // push stack 108 | PUSH_STACKR(env->current_stack, obj, Reference); 109 | 110 | PUSH_STACK(env->current_stack, 1234567, int); 111 | POP_STACK(env->current_stack); 112 | PUSH_STACK(env->current_stack, -126, byte); 113 | OP_PUT_FIELDI(obj, 8, byte); 114 | printf("byte: %d\n", GET_FIELD(obj, 8, int)); 115 | 116 | OP_GET_FIELDI(obj, 8, byte); 117 | printf("byte: %d\n", PICK_STACK(env->current_stack, byte)); 118 | } 119 | 120 | void testStaticField(Class* pclass) 121 | { 122 | StackFrame *stf; 123 | OPENV *env; 124 | Object *obj; 125 | 126 | obj = newObject(NULL,pclass); 127 | 128 | stf = newStackFrame(NULL, 20); 129 | env = newOPENV(NULL); 130 | env->current_class = pclass; 131 | env->current_obj = obj; 132 | env->current_stack = stf; 133 | env->dbg = newDebugType(20, 256); 134 | } 135 | -------------------------------------------------------------------------------- /src/myjvm/utils.c: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/myjvm/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * +-----------------------------------------------------------------+ 3 | * | myjvm writing a Java virtual machine step by step (C version) | 4 | * +-----------------------------------------------------------------+ 5 | * | Author: springlchy All Rights Reserved | 6 | * +-----------------------------------------------------------------+ 7 | */ 8 | 9 | #ifndef UTILS_H 10 | #define UTILS_H 11 | 12 | #include 13 | #include 14 | #include "constants.h" 15 | 16 | #define READ_U1(fp, dest) fread(dest, 1, 1, fp) 17 | #define READ_U2(fp, dest) \ 18 | READ_U1(fp, dest+1);\ 19 | READ_U1(fp, dest) 20 | 21 | #define READ_U4(fp, dest) \ 22 | READ_U2(fp, dest+2);\ 23 | READ_U2(fp, dest) 24 | 25 | #define READ_U8(fp, dest) \ 26 | READ_U4(fp, dest+4); \ 27 | READ_U4(fp, dest) 28 | 29 | char readByte(FILE *fp) 30 | { 31 | char c; 32 | READ_U1(fp, &c); 33 | return c; 34 | } 35 | 36 | uchar readU1(FILE *fp) 37 | { 38 | uchar uc; 39 | READ_U1(fp, &uc); 40 | return uc; 41 | } 42 | 43 | short readShort(FILE *fp) 44 | { 45 | char uc2[2]; 46 | READ_U2(fp, uc2); 47 | return *(short*)&uc2[0]; 48 | } 49 | 50 | ushort readUShort(FILE *fp) 51 | { 52 | uchar uc2[2]; 53 | READ_U2(fp, uc2); 54 | return *(ushort*)&uc2[0]; 55 | } 56 | 57 | float readFloat(FILE *fp) 58 | { 59 | char uc4[4]; 60 | READ_U4(fp, uc4); 61 | return *(float*)&uc4; 62 | } 63 | 64 | uint readUInt(FILE *fp) 65 | { 66 | uchar uc4[4]; 67 | READ_U4(fp, uc4); 68 | return *(uint*)&uc4; 69 | } 70 | 71 | int readInt(FILE *fp) 72 | { 73 | char uc4[4]; 74 | READ_U4(fp, uc4); 75 | return *(int*)&uc4; 76 | } 77 | 78 | long readLong(FILE *fp) 79 | { 80 | char uc8[8]; 81 | READ_U8(fp, uc8); 82 | return *(long*)&uc8; 83 | } 84 | double readDouble(FILE *fp) 85 | { 86 | char uc8[8]; 87 | READ_U8(fp, uc8); 88 | return *(double*)&uc8; 89 | } 90 | 91 | void readBytes(FILE *fp, uchar dest[], uint len) 92 | { 93 | fread(dest, len, 1, fp); 94 | } 95 | 96 | void displayHex(uchar s[], int len) 97 | { 98 | ushort i=0; 99 | printf("0x"); 100 | while(i < len) { 101 | printf("%02X ", s[i]); 102 | i++; 103 | } 104 | } 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /test/A.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/A.class -------------------------------------------------------------------------------- /test/Average.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Average.class -------------------------------------------------------------------------------- /test/Average.code: -------------------------------------------------------------------------------- 1 | Classfile /E:/JavaWeb/test/src/test/Average.class 2 | Last modified 2017-6-3; size 390 bytes 3 | MD5 checksum 4949687f2ce430f260550f8a572b9f02 4 | Compiled from "Average.java" 5 | public class test.Average 6 | SourceFile: "Average.java" 7 | minor version: 0 8 | major version: 52 9 | flags: ACC_PUBLIC, ACC_SUPER 10 | Constant pool: 11 | #1 = Methodref #3.#14 // java/lang/Object."":()V 12 | #2 = Class #15 // test/Average 13 | #3 = Class #16 // java/lang/Object 14 | #4 = Utf8 15 | #5 = Utf8 ()V 16 | #6 = Utf8 Code 17 | #7 = Utf8 LineNumberTable 18 | #8 = Utf8 main 19 | #9 = Utf8 ([Ljava/lang/String;)V 20 | #10 = Utf8 StackMapTable 21 | #11 = Class #17 // "[Ljava/lang/String;" 22 | #12 = Utf8 SourceFile 23 | #13 = Utf8 Average.java 24 | #14 = NameAndType #4:#5 // "":()V 25 | #15 = Utf8 test/Average 26 | #16 = Utf8 java/lang/Object 27 | #17 = Utf8 [Ljava/lang/String; 28 | { 29 | public test.Average(); 30 | descriptor: ()V 31 | flags: ACC_PUBLIC 32 | Code: 33 | stack=1, locals=1, args_size=1 34 | 0: aload_0 35 | 1: invokespecial #1 // Method java/lang/Object."":()V 36 | 4: return 37 | LineNumberTable: 38 | line 3: 0 39 | 40 | public static void main(java.lang.String[]); 41 | descriptor: ([Ljava/lang/String;)V 42 | flags: ACC_PUBLIC, ACC_STATIC 43 | Code: 44 | stack=4, locals=6, args_size=1 45 | 0: bipush 100 46 | 2: istore_3 47 | 3: iconst_0 48 | 4: istore 4 49 | 6: iconst_1 50 | 7: istore 5 51 | 9: iload 5 52 | 11: iload_3 53 | 12: if_icmpgt 28 54 | 15: iload 4 55 | 17: iload 5 56 | 19: iadd 57 | 20: istore 4 58 | 22: iinc 5, 1 59 | 25: goto 9 60 | 28: iload 4 61 | 30: i2d 62 | 31: iload_3 63 | 32: i2d 64 | 33: ddiv 65 | 34: dstore_1 66 | 35: return 67 | LineNumberTable: 68 | line 6: 0 69 | line 7: 3 70 | line 9: 6 71 | line 10: 15 72 | line 9: 22 73 | line 13: 28 74 | line 14: 35 75 | StackMapTable: number_of_entries = 2 76 | frame_type = 255 /* full_frame */ 77 | offset_delta = 9 78 | locals = [ class "[Ljava/lang/String;", top, top, int, int, int ] 79 | stack = [] 80 | frame_type = 250 /* chop */ 81 | offset_delta = 18 82 | 83 | } 84 | -------------------------------------------------------------------------------- /test/Average.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class Average{ 4 | public static void main(String[] args) { 5 | double avg; 6 | int n = 100; 7 | int sum = 0; 8 | 9 | for (int i=1; i<=n; i++) { 10 | sum += i; 11 | } 12 | 13 | avg = (double)(sum)/n; 14 | } 15 | } -------------------------------------------------------------------------------- /test/B.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/B.class -------------------------------------------------------------------------------- /test/C.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/C.class -------------------------------------------------------------------------------- /test/Child.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Child.class -------------------------------------------------------------------------------- /test/Child.code: -------------------------------------------------------------------------------- 1 | Classfile /E:/JavaWeb/test/src/test/Child.class 2 | Last modified 2017-6-6; size 335 bytes 3 | MD5 checksum 6cfea29d9e0150f7f261371e6afb83bb 4 | Compiled from "Child.java" 5 | class test.Child extends test.Parent 6 | SourceFile: "Child.java" 7 | minor version: 0 8 | major version: 52 9 | flags: ACC_SUPER 10 | Constant pool: 11 | #1 = Methodref #6.#17 // test/Parent."":()V 12 | #2 = Fieldref #5.#18 // test/Child.x2:I 13 | #3 = Methodref #5.#19 // test/Child.addXY:()I 14 | #4 = Methodref #6.#20 // test/Parent.getZ1:()I 15 | #5 = Class #21 // test/Child 16 | #6 = Class #22 // test/Parent 17 | #7 = Utf8 x2 18 | #8 = Utf8 I 19 | #9 = Utf8 20 | #10 = Utf8 ()V 21 | #11 = Utf8 Code 22 | #12 = Utf8 LineNumberTable 23 | #13 = Utf8 doSomething 24 | #14 = Utf8 ()I 25 | #15 = Utf8 SourceFile 26 | #16 = Utf8 Child.java 27 | #17 = NameAndType #9:#10 // "":()V 28 | #18 = NameAndType #7:#8 // x2:I 29 | #19 = NameAndType #23:#14 // addXY:()I 30 | #20 = NameAndType #24:#14 // getZ1:()I 31 | #21 = Utf8 test/Child 32 | #22 = Utf8 test/Parent 33 | #23 = Utf8 addXY 34 | #24 = Utf8 getZ1 35 | { 36 | test.Child(); 37 | descriptor: ()V 38 | flags: 39 | Code: 40 | stack=2, locals=1, args_size=1 41 | 0: aload_0 42 | 1: invokespecial #1 // Method test/Parent."":()V 43 | 4: aload_0 44 | 5: iconst_4 45 | 6: putfield #2 // Field x2:I 46 | 9: return 47 | LineNumberTable: 48 | line 3: 0 49 | line 5: 4 50 | 51 | public int doSomething(); 52 | descriptor: ()I 53 | flags: ACC_PUBLIC 54 | Code: 55 | stack=2, locals=2, args_size=1 56 | 0: aload_0 57 | 1: invokevirtual #3 // Method addXY:()I 58 | 4: istore_1 59 | 5: iload_1 60 | 6: aload_0 61 | 7: invokespecial #4 // Method test/Parent.getZ1:()I 62 | 10: iadd 63 | 11: aload_0 64 | 12: getfield #2 // Field x2:I 65 | 15: iadd 66 | 16: ireturn 67 | LineNumberTable: 68 | line 9: 0 69 | line 11: 5 70 | } 71 | -------------------------------------------------------------------------------- /test/Child.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Child extends Parent 4 | { 5 | private int x2 = 4; 6 | 7 | public int doSomething() 8 | { 9 | int xy = this.addXY(); // invoke protected method of parent class 10 | 11 | return xy + super.getZ1() + this.x2; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/D.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/D.class -------------------------------------------------------------------------------- /test/Dance.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Dance.class -------------------------------------------------------------------------------- /test/Employee.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Employee.class -------------------------------------------------------------------------------- /test/Employee.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Employee 4 | { 5 | private int baseSalary; 6 | Employee(int baseSalary) 7 | { 8 | this.baseSalary = baseSalary; 9 | } 10 | 11 | public int getSalary() 12 | { 13 | return this.baseSalary; 14 | } 15 | } -------------------------------------------------------------------------------- /test/Engineer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Engineer.class -------------------------------------------------------------------------------- /test/Engineer.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Engineer extends Employee 4 | { 5 | private int bonus; 6 | Engineer(int baseSalary, int bonus) 7 | { 8 | super(baseSalary); 9 | this.bonus = bonus; 10 | } 11 | public int getSalary() 12 | { 13 | return super.getSalary() + this.bonus; 14 | } 15 | } -------------------------------------------------------------------------------- /test/Fibonacci.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Fibonacci.class -------------------------------------------------------------------------------- /test/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class Fibonacci{ 4 | private int[] fa; 5 | private int maxSize; 6 | private int position; 7 | 8 | public Fibonacci(int maxSize) 9 | { 10 | this.maxSize = maxSize; 11 | this.fa = new int[maxSize]; 12 | this.fa[0] = this.fa[1] = 1; 13 | this.position = 1; 14 | } 15 | 16 | private int getFibN(int n) 17 | { 18 | if (n >= this.maxSize) { 19 | System.out.println("n is to big, max n should be: " + this.maxSize); 20 | return -1; 21 | } 22 | 23 | if (n > this.position) { 24 | for (int i=position+1; i<=n; i++) { 25 | this.fa[i] = this.fa[i-2] + this.fa[i-1]; 26 | } 27 | 28 | this.position = n; 29 | } 30 | 31 | return this.fa[n]; 32 | } 33 | 34 | public static void main(String[] args) 35 | { 36 | Fibonacci fib = new Fibonacci(100); 37 | int a = fib.getFibN(5); 38 | int b = fib.getFibN(10); 39 | 40 | System.out.println("a=" + a + ", b=" + b); 41 | } 42 | } -------------------------------------------------------------------------------- /test/Hello.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Hello.class -------------------------------------------------------------------------------- /test/Hello.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class Hello implements IMath{ 4 | static double C_DOUBLE = 12.45; 5 | public int xi = 789; 6 | protected long xl = 35; 7 | public float xf = -235.125f; 8 | public double db = 32.5; 9 | private int priv_i = 2; 10 | 11 | public int sum(int x, int y) 12 | { 13 | int s = 0; 14 | for(int i=x;i<=y;i++) { 15 | s+=i; 16 | } 17 | 18 | s += sub(x,y); 19 | return s+xi + this.priv_i; 20 | } 21 | 22 | private int sub(int x, int y) { 23 | return x-y; 24 | } 25 | } 26 | 27 | interface IMath { 28 | public int sum(int x, int y); 29 | } 30 | -------------------------------------------------------------------------------- /test/HelloStatic.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/HelloStatic.class -------------------------------------------------------------------------------- /test/HelloStatic.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class HelloStatic 4 | { 5 | private static int i= 15 ; 6 | private static float f = 2.6f; 7 | 8 | public static int getI() 9 | { 10 | return i; 11 | } 12 | 13 | public static float getF() 14 | { 15 | return f; 16 | } 17 | } -------------------------------------------------------------------------------- /test/IMath.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/IMath.class -------------------------------------------------------------------------------- /test/IOUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/IOUtil.class -------------------------------------------------------------------------------- /test/IOUtil.code: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | constant_pool_count: 15 3 | #1 Methodref #3.#12 // java/lang/Object.:()V 4 | #2 Class #13 // test/IOUtil 5 | #3 Class #14 // java/lang/Object 6 | #4 Utf8 7 | #5 Utf8 ()V 8 | #6 Utf8 Code 9 | #7 Utf8 LineNumberTable 10 | #8 Utf8 writeString 11 | #9 Utf8 (Ljava/lang/String;)V 12 | #10 Utf8 SourceFile 13 | #11 Utf8 IOUtil.java 14 | #12 NameAndType #4:#5 // :()V 15 | #13 Utf8 test/IOUtil 16 | #14 Utf8 java/lang/Object 17 | access_flag: 0020 ACC_SUPER 18 | this_class: #2 test/IOUtil 19 | super_class: #3 java/lang/Object 20 | -------------------------------------------- 21 | interface_count: 0 22 | -------------------------------------------- 23 | fields_count: 0 24 | -------------------------------------------- 25 | method=-----------code begin----------------- 26 | 0: aload_0 27 | 1: invokespecial #1 28 | 4: return 29 | -----------code end----------------- 30 | method=writeStringmethods_count: 2 31 | methods[0]: , [name_index=4] : [desc_index=5] ()V 32 | args_len=0 33 | attributes_count: 1 34 | attributes[0]: #6 // Code 35 | length=29 36 | methods[1]: ACC_PUBLIC ACC_STATIC ACC_NATIVE , [name_index=8] writeString: [desc_index=9] (Ljava/lang/String;)V 37 | args_len=4 38 | attributes_count: 0 39 | -------------------------------------------- 40 | -------------------------------------------------------------------------------- /test/IOUtil.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class IOUtil { 4 | public static native void writeString(String s); 5 | } 6 | -------------------------------------------------------------------------------- /test/Jazz.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Jazz.class -------------------------------------------------------------------------------- /test/Latin.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Latin.class -------------------------------------------------------------------------------- /test/Manager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Manager.class -------------------------------------------------------------------------------- /test/Manager.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Manager extends Employee 4 | { 5 | private int bonus; 6 | Manager(int baseSalary, int bonus) 7 | { 8 | super(baseSalary); 9 | this.bonus = bonus; 10 | } 11 | 12 | public int getSalary() 13 | { 14 | return 2 * super.getSalary() + bonus; 15 | } 16 | } -------------------------------------------------------------------------------- /test/Parent.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Parent.class -------------------------------------------------------------------------------- /test/Parent.code: -------------------------------------------------------------------------------- 1 | Classfile /E:/JavaWeb/test/src/test/Parent.class 2 | Last modified 2017-6-6; size 440 bytes 3 | MD5 checksum f70010a25b416f32436d416804b7567e 4 | Compiled from "Parent.java" 5 | class test.Parent 6 | SourceFile: "Parent.java" 7 | minor version: 0 8 | major version: 52 9 | flags: ACC_SUPER 10 | Constant pool: 11 | #1 = Methodref #6.#22 // java/lang/Object."":()V 12 | #2 = Fieldref #5.#23 // test/Parent.z1:I 13 | #3 = Fieldref #5.#24 // test/Parent.x1:I 14 | #4 = Fieldref #5.#25 // test/Parent.y1:I 15 | #5 = Class #26 // test/Parent 16 | #6 = Class #27 // java/lang/Object 17 | #7 = Utf8 x1 18 | #8 = Utf8 I 19 | #9 = Utf8 y1 20 | #10 = Utf8 z1 21 | #11 = Utf8 22 | #12 = Utf8 ()V 23 | #13 = Utf8 Code 24 | #14 = Utf8 LineNumberTable 25 | #15 = Utf8 setZ1 26 | #16 = Utf8 (I)V 27 | #17 = Utf8 getZ1 28 | #18 = Utf8 ()I 29 | #19 = Utf8 addXY 30 | #20 = Utf8 SourceFile 31 | #21 = Utf8 Parent.java 32 | #22 = NameAndType #11:#12 // "":()V 33 | #23 = NameAndType #10:#8 // z1:I 34 | #24 = NameAndType #7:#8 // x1:I 35 | #25 = NameAndType #9:#8 // y1:I 36 | #26 = Utf8 test/Parent 37 | #27 = Utf8 java/lang/Object 38 | { 39 | public int x1; 40 | descriptor: I 41 | flags: ACC_PUBLIC 42 | 43 | protected int y1; 44 | descriptor: I 45 | flags: ACC_PROTECTED 46 | 47 | test.Parent(); 48 | descriptor: ()V 49 | flags: 50 | Code: 51 | stack=1, locals=1, args_size=1 52 | 0: aload_0 53 | 1: invokespecial #1 // Method java/lang/Object."":()V 54 | 4: return 55 | LineNumberTable: 56 | line 3: 0 57 | 58 | public void setZ1(int); 59 | descriptor: (I)V 60 | flags: ACC_PUBLIC 61 | Code: 62 | stack=2, locals=2, args_size=2 63 | 0: aload_0 64 | 1: iload_1 65 | 2: putfield #2 // Field z1:I 66 | 5: return 67 | LineNumberTable: 68 | line 11: 0 69 | line 12: 5 70 | 71 | public int getZ1(); 72 | descriptor: ()I 73 | flags: ACC_PUBLIC 74 | Code: 75 | stack=1, locals=1, args_size=1 76 | 0: aload_0 77 | 1: getfield #2 // Field z1:I 78 | 4: ireturn 79 | LineNumberTable: 80 | line 15: 0 81 | 82 | protected int addXY(); 83 | descriptor: ()I 84 | flags: ACC_PROTECTED 85 | Code: 86 | stack=2, locals=1, args_size=1 87 | 0: aload_0 88 | 1: getfield #3 // Field x1:I 89 | 4: aload_0 90 | 5: getfield #4 // Field y1:I 91 | 8: iadd 92 | 9: ireturn 93 | LineNumberTable: 94 | line 20: 0 95 | } 96 | -------------------------------------------------------------------------------- /test/Parent.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Parent 4 | { 5 | public int x1; 6 | protected int y1; 7 | private int z1; 8 | 9 | public void setZ1(int z1) 10 | { 11 | this.z1 = z1; 12 | } 13 | public int getZ1() 14 | { 15 | return this.z1; 16 | } 17 | 18 | protected int addXY() 19 | { 20 | return this.x1 + this.y1; 21 | } 22 | } -------------------------------------------------------------------------------- /test/Point.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/Point.class -------------------------------------------------------------------------------- /test/Point.code: -------------------------------------------------------------------------------- 1 | Classfile /E:/JavaWeb/test/src/test/Point.class 2 | Last modified 2017-6-3; size 524 bytes 3 | MD5 checksum 266bd003a32e2dd08614e07476c93dd4 4 | Compiled from "Point.java" 5 | public class test.Point 6 | SourceFile: "Point.java" 7 | minor version: 0 8 | major version: 52 9 | flags: ACC_PUBLIC, ACC_SUPER 10 | Constant pool: 11 | #1 = Methodref #11.#25 // java/lang/Object."":()V 12 | #2 = Fieldref #4.#26 // test/Point.x:D 13 | #3 = Fieldref #4.#27 // test/Point.y:D 14 | #4 = Class #28 // test/Point 15 | #5 = Methodref #4.#29 // test/Point."":(DD)V 16 | #6 = Double 3.0d 17 | #8 = Double 4.0d 18 | #10 = Methodref #4.#30 // test/Point.distance:(Ltest/Point;)D 19 | #11 = Class #31 // java/lang/Object 20 | #12 = Utf8 x 21 | #13 = Utf8 D 22 | #14 = Utf8 y 23 | #15 = Utf8 24 | #16 = Utf8 (DD)V 25 | #17 = Utf8 Code 26 | #18 = Utf8 LineNumberTable 27 | #19 = Utf8 distance 28 | #20 = Utf8 (Ltest/Point;)D 29 | #21 = Utf8 main 30 | #22 = Utf8 ([Ljava/lang/String;)V 31 | #23 = Utf8 SourceFile 32 | #24 = Utf8 Point.java 33 | #25 = NameAndType #15:#32 // "":()V 34 | #26 = NameAndType #12:#13 // x:D 35 | #27 = NameAndType #14:#13 // y:D 36 | #28 = Utf8 test/Point 37 | #29 = NameAndType #15:#16 // "":(DD)V 38 | #30 = NameAndType #19:#20 // distance:(Ltest/Point;)D 39 | #31 = Utf8 java/lang/Object 40 | #32 = Utf8 ()V 41 | { 42 | public test.Point(double, double); 43 | descriptor: (DD)V 44 | flags: ACC_PUBLIC 45 | Code: 46 | stack=3, locals=5, args_size=3 47 | 0: aload_0 48 | 1: invokespecial #1 // Method java/lang/Object."":()V 49 | 4: aload_0 50 | 5: dload_1 51 | 6: putfield #2 // Field x:D 52 | 9: aload_0 53 | 10: dload_3 54 | 11: putfield #3 // Field y:D 55 | 14: return 56 | LineNumberTable: 57 | line 8: 0 58 | line 9: 4 59 | line 10: 9 60 | line 11: 14 61 | 62 | public static void main(java.lang.String[]); 63 | descriptor: ([Ljava/lang/String;)V 64 | flags: ACC_PUBLIC, ACC_STATIC 65 | Code: 66 | stack=6, locals=5, args_size=1 67 | 0: new #4 // class test/Point 68 | 3: dup 69 | 4: dconst_0 70 | 5: dconst_0 71 | 6: invokespecial #5 // Method "":(DD)V 72 | 9: astore_1 73 | 10: new #4 // class test/Point 74 | 13: dup 75 | 14: ldc2_w #6 // double 3.0d 76 | 17: ldc2_w #8 // double 4.0d 77 | 20: invokespecial #5 // Method "":(DD)V 78 | 23: astore_2 79 | 24: aload_1 80 | 25: aload_2 81 | 26: invokespecial #10 // Method distance:(Ltest/Point;)D 82 | 29: dstore_3 83 | 30: return 84 | LineNumberTable: 85 | line 23: 0 86 | line 24: 10 87 | line 26: 24 88 | line 27: 30 89 | } 90 | -------------------------------------------------------------------------------- /test/Point.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class Point{ 4 | private double x; 5 | private double y; 6 | 7 | public Point(double x, double y) 8 | { 9 | this.x = x; 10 | this.y = y; 11 | } 12 | 13 | private double distance(Point p) 14 | { 15 | double dx = p.x - this.x; 16 | double dy = p.y - this.y; 17 | 18 | return dx*dx + dy *dy; 19 | } 20 | 21 | public static void main(String[] args) 22 | { 23 | Point p1 = new Point(0,0); 24 | Point p2 = new Point(3.0, 4.0); 25 | 26 | double dist = p1.distance(p2); 27 | } 28 | } -------------------------------------------------------------------------------- /test/TestAArray.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestAArray.class -------------------------------------------------------------------------------- /test/TestAArray.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class TestAArray{ 4 | private int ai; 5 | public static void main(String[] args) { 6 | TestAArray[] arrs = new TestAArray[3]; 7 | arrs[0] = new TestAArray(); 8 | arrs[1] = new TestAArray(); 9 | 10 | arrs[0].ai = 10; 11 | arrs[1].ai = 110; 12 | 13 | int result = arrs[0].ai + arrs[1].ai; 14 | } 15 | } -------------------------------------------------------------------------------- /test/TestArray.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestArray.class -------------------------------------------------------------------------------- /test/TestArray.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class TestArray{ 4 | public static void main(String[] args) { 5 | int[] a= new int[3]; 6 | 7 | a[0] = 1; 8 | a[1] = 2; 9 | int result = a[0] + a[1]; 10 | 11 | float[] f = new float[2]; 12 | f[0] = 1.1f; 13 | f[1] = 2.3f; 14 | float rresult = f[0] + f[1]; 15 | 16 | long[] l = new long[2]; 17 | l[0] = 123456; 18 | l[1] = 78901; 19 | long lresult = l[0] + l[1]; 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /test/TestInheritance.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestInheritance.class -------------------------------------------------------------------------------- /test/TestInheritance.code: -------------------------------------------------------------------------------- 1 | Classfile /E:/JavaWeb/test/src/test/TestInheritance.class 2 | Last modified 2017-6-6; size 438 bytes 3 | MD5 checksum a6cbd70a0a37ec4c8a5762c0599c7933 4 | Compiled from "TestInheritance.java" 5 | class test.TestInheritance 6 | SourceFile: "TestInheritance.java" 7 | minor version: 0 8 | major version: 52 9 | flags: ACC_SUPER 10 | Constant pool: 11 | #1 = Methodref #9.#18 // java/lang/Object."":()V 12 | #2 = Class #19 // test/Child 13 | #3 = Methodref #2.#18 // test/Child."":()V 14 | #4 = Methodref #2.#20 // test/Child.setZ1:(I)V 15 | #5 = Fieldref #2.#21 // test/Child.x1:I 16 | #6 = Fieldref #2.#22 // test/Child.y1:I 17 | #7 = Methodref #2.#23 // test/Child.doSomething:()I 18 | #8 = Class #24 // test/TestInheritance 19 | #9 = Class #25 // java/lang/Object 20 | #10 = Utf8 21 | #11 = Utf8 ()V 22 | #12 = Utf8 Code 23 | #13 = Utf8 LineNumberTable 24 | #14 = Utf8 main 25 | #15 = Utf8 ([Ljava/lang/String;)V 26 | #16 = Utf8 SourceFile 27 | #17 = Utf8 TestInheritance.java 28 | #18 = NameAndType #10:#11 // "":()V 29 | #19 = Utf8 test/Child 30 | #20 = NameAndType #26:#27 // setZ1:(I)V 31 | #21 = NameAndType #28:#29 // x1:I 32 | #22 = NameAndType #30:#29 // y1:I 33 | #23 = NameAndType #31:#32 // doSomething:()I 34 | #24 = Utf8 test/TestInheritance 35 | #25 = Utf8 java/lang/Object 36 | #26 = Utf8 setZ1 37 | #27 = Utf8 (I)V 38 | #28 = Utf8 x1 39 | #29 = Utf8 I 40 | #30 = Utf8 y1 41 | #31 = Utf8 doSomething 42 | #32 = Utf8 ()I 43 | { 44 | test.TestInheritance(); 45 | descriptor: ()V 46 | flags: 47 | Code: 48 | stack=1, locals=1, args_size=1 49 | 0: aload_0 50 | 1: invokespecial #1 // Method java/lang/Object."":()V 51 | 4: return 52 | LineNumberTable: 53 | line 3: 0 54 | 55 | public static void main(java.lang.String[]); 56 | descriptor: ([Ljava/lang/String;)V 57 | flags: ACC_PUBLIC, ACC_STATIC 58 | Code: 59 | stack=2, locals=3, args_size=1 60 | 0: new #2 // class test/Child 61 | 3: dup 62 | 4: invokespecial #3 // Method test/Child."":()V 63 | 7: astore_1 64 | 8: aload_1 65 | 9: iconst_3 66 | 10: invokevirtual #4 // Method test/Child.setZ1:(I)V 67 | 13: aload_1 68 | 14: iconst_1 69 | 15: putfield #5 // Field test/Child.x1:I 70 | 18: aload_1 71 | 19: iconst_2 72 | 20: putfield #6 // Field test/Child.y1:I 73 | 23: aload_1 74 | 24: invokevirtual #7 // Method test/Child.doSomething:()I 75 | 27: istore_2 76 | 28: return 77 | LineNumberTable: 78 | line 7: 0 79 | line 9: 8 80 | line 10: 13 81 | line 11: 18 82 | line 13: 23 83 | line 14: 28 84 | } 85 | -------------------------------------------------------------------------------- /test/TestInheritance.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class TestInheritance 4 | { 5 | public static void main(String[] args) 6 | { 7 | Child someone = new Child(); 8 | 9 | someone.setZ1(3); // invoke public method of parent class 10 | someone.x1 = 1; // access public field 11 | someone.y1 = 2; // access protected field 12 | 13 | int result = someone.doSomething(); 14 | } 15 | } -------------------------------------------------------------------------------- /test/TestMultiAArray.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestMultiAArray.class -------------------------------------------------------------------------------- /test/TestMultiAArray.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class TestMultiAArray{ 4 | private int ai; 5 | public static void main(String[] args) { 6 | int[][] arr_int = new int[3][4]; 7 | 8 | arr_int[0][1] = 7; 9 | arr_int[0][3] = 8; 10 | 11 | int a = arr_int[0][1]; 12 | } 13 | } -------------------------------------------------------------------------------- /test/TestPoly.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestPoly.class -------------------------------------------------------------------------------- /test/TestPoly.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class TestPoly 4 | { 5 | private int getSalary(Employee e) 6 | { 7 | return e.getSalary(); 8 | } 9 | 10 | public static void main(String[] args) 11 | { 12 | TestPoly obj = new TestPoly(); 13 | Employee emp = new Employee(100); 14 | Employee eng = new Engineer(150, 50); 15 | Employee mgr = new Manager(100, 100); 16 | 17 | int salary1 = obj.getSalary(emp); 18 | int salary2 = obj.getSalary(eng); 19 | int salary3 = obj.getSalary(mgr); 20 | 21 | int result = salary1; 22 | result = salary2; 23 | result = salary3; 24 | } 25 | } -------------------------------------------------------------------------------- /test/TestPoly2.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class Dance { 4 | public void play(){ 5 | System.out.println("Dance.play"); 6 | } 7 | public void play(int i){ 8 | System.out.println("Dance.play" + i); 9 | } 10 | } 11 | 12 | class Latin extends Dance { 13 | public void play(){ 14 | System.out.println("Latin.play"); 15 | } 16 | public void play(char c){ 17 | System.out.println("Latin.play" + c); 18 | } 19 | } 20 | class Jazz extends Dance { 21 | public void play(){ 22 | System.out.println("Jazz.play"); 23 | } 24 | public void play(double d){ 25 | System.out.println("Jazz.play" + d); 26 | } 27 | } 28 | 29 | public class TestPoly { 30 | public void perform(Dance dance){ 31 | dance.play(); 32 | } 33 | public static void main(String[] args){ 34 | new TestPoly().perform(new Latin()); // Upcasting 35 | new TestPoly().perform(new Jazz()); // Upcasting 36 | new TestPoly().perform(new Dance()); // Upcasting 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/TestPoly3.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestPoly3.class -------------------------------------------------------------------------------- /test/TestPoly3.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class TestPoly3 4 | { 5 | public static void main(String[] args) 6 | { 7 | A a1 = new A(); 8 | A a2 = new B(); 9 | B b = new B(); 10 | C c = new C(); 11 | D d = new D(); 12 | 13 | // System.out.println("1---" + a1.show(b)); 14 | // System.out.println("2---" + a1.show(c)); 15 | // System.out.println("3---" + a1.show(d)); 16 | System.out.println("4---" + a2.show(b)); 17 | // System.out.println("5---" + a2.show(c)); 18 | // System.out.println("6---" + a2.show(d)); 19 | } 20 | } 21 | 22 | class A 23 | { 24 | public String show(D obj) 25 | { 26 | return "A and D"; 27 | } 28 | 29 | public String show(A obj) 30 | { 31 | return "A and A"; 32 | } 33 | } 34 | 35 | class B extends A 36 | { 37 | public String show(B obj) 38 | { 39 | return "B and B"; 40 | } 41 | 42 | public String show(A obj) 43 | { 44 | return "B and A"; 45 | } 46 | } 47 | 48 | class C extends B 49 | { 50 | 51 | } 52 | 53 | class D extends B 54 | { 55 | 56 | } -------------------------------------------------------------------------------- /test/TestStatic.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestStatic.class -------------------------------------------------------------------------------- /test/TestStatic.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class TestStatic 4 | { 5 | static int i = 3 ; 6 | static float f = 10.25f; 7 | 8 | public static void main(String[] args) 9 | { 10 | int x = TestStatic.i + HelloStatic.getI(); 11 | float y = TestStatic.f + HelloStatic.getF(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/TestString.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestString.class -------------------------------------------------------------------------------- /test/TestString.code: -------------------------------------------------------------------------------- 1 | -------------------------------------------- 2 | constant_pool_count: 41 3 | access_flag: 0020 ACC_SUPER 4 | this_class: #10 test/TestString 5 | super_class: #11 java/lang/Object 6 | -------------------------------------------- 7 | interface_count: 0 8 | -------------------------------------------- 9 | fields_count: 0 10 | -------------------------------------------- 11 | method=-----------code begin----------------- 12 | 0: aload_0 13 | 1: invokespecial #1 14 | 4: return 15 | -----------code end----------------- 16 | method=write-----------code begin----------------- 17 | 0: new #2 18 | 3: dup 19 | 4: invokespecial #3 20 | 7: ldc #4 21 | 9: invokevirtual #5 22 | 12: iload_0 23 | 13: invokevirtual #6 24 | 16: invokevirtual #7 25 | 19: invokestatic #8 26 | 22: return 27 | -----------code end----------------- 28 | method=main-----------code begin----------------- 29 | 0: bipush 30 | 2: invokestatic #9 31 | 5: return 32 | -----------code end----------------- 33 | methods_count: 3 34 | methods[0]: , [name_index=12] : [desc_index=13] ()V 35 | args_len=0 36 | attributes_count: 1 37 | attributes[0]: #14 // Code 38 | length=29 39 | methods[1]: ACC_PRIVATE ACC_STATIC , [name_index=16] write: [desc_index=17] (I)V 40 | args_len=4 41 | attributes_count: 1 42 | attributes[0]: #14 // Code 43 | length=51 44 | methods[2]: ACC_PUBLIC ACC_STATIC , [name_index=18] main: [desc_index=19] ([Ljava/lang/String;)V 45 | args_len=4 46 | attributes_count: 1 47 | attributes[0]: #14 // Code 48 | length=34 49 | -------------------------------------------- 50 | -------------------------------------------------------------------------------- /test/TestString.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | class TestString 4 | { 5 | 6 | private static void write(int i) 7 | { 8 | IOUtil.writeString("hello: " + i); 9 | } 10 | public static void main(String[] args) 11 | { 12 | write(100); 13 | } 14 | } -------------------------------------------------------------------------------- /test/TestSwitch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springlchy/myjvm/97df228d1c5ed2b7e332490e844b67824c252d12/test/TestSwitch.class -------------------------------------------------------------------------------- /test/TestSwitch.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | public class TestSwitch extends Hello{ 4 | static int C_INT=4567; 5 | static short C_SHORT = 124; 6 | static long C_LONG = 1234566; 7 | static float C_FLOAT = 123.456f; 8 | 9 | private float f = 3.68f; // 5 10 | private short si = 15; // 6 11 | private int ii = 1223; // 7 12 | private byte b = -126; // 8 13 | private char c = 'A'; // 9 14 | private long l = 1234567; // 10 15 | private double d = 123456.789; // 12 16 | 17 | private static int xadd(int x, int y) { 18 | return x + y + 1; 19 | } 20 | public static void main(String[] args) 21 | { 22 | //Hello obj = new Hello(); 23 | TestSwitch t = new TestSwitch(); 24 | int res1 = t.C_INT + 1; 25 | short res2 = t.C_SHORT--; 26 | long res3 = TestSwitch.C_LONG + 4; 27 | float res4 = TestSwitch.C_FLOAT + 3.5f; 28 | double res5 = TestSwitch.C_DOUBLE + 2.6; 29 | int res6 = xadd(7,10); 30 | } 31 | 32 | // private float fadd() 33 | // { 34 | // return f + si; 35 | // } 36 | private int add() 37 | { 38 | return b + ii; 39 | } 40 | 41 | // private float divide() 42 | // { 43 | // return this.xf/(float)(this.xl); 44 | // } 45 | } 46 | 47 | --------------------------------------------------------------------------------