ClassLoader是Java技术中非常主要的概念,原因是它用来加载Java Class。如果没有Class,也就没有对象;没有对象,就没有之后的一切了。
Java ClassLoader的默认实现是一种双亲结构,即总是尝试让Parent ClassLoader加载类。这样有一些优点,当然也有很大的限制,比如就不利于不同Module对多版本类的加载。更多的细节,在下面我做的PPT里。
还有些新的理解和发现。
- 自定义的ClassLoader可以把Parent ClassLoader设置为null,如果再把loadClass函数重写,就可以完全屏蔽default classLoader的影响。如OSGi的Bundle ClassLoader的最终的Parent就不是Bootstrap ClassLoader(Bundle ClassLoader的实现还是会去从默认ClassLoader去加载java.*的类)。
- 程序执行时,ClassLoader的选择。做几个小实验你就会发现,默认的ClassLoader是“加载当前执行函数所在类的ClassLoader”。在OpenJDK的源码中一通Search,就可以找到一些端倪。
在源文件src\interp\engine\interp.c中,有executeJava()函数中,执行ByteCode之前,先准备了MethodBlock的指针,它中间
|
uintptr_t *executeJava() { ... uintptr_t *arg1; register CodePntr pc; ExecEnv *ee = getExecEnv(); Frame *frame = ee->last_frame; register uintptr_t *lvars = frame->lvars; register uintptr_t *ostack = frame->ostack; Object *this = (Object*)lvars[0]; <strong>MethodBlock *new_mb, *mb = frame->mb;</strong> ConstantPool *cp = &(CLASS_CB(mb->class)->constant_pool); |
可以看看GETSTATIC这个指令的实现(此指令会在读取类的静态方法时调用)。可以看到resolveField()方法,并在mb的Class指针传入。idx是Static Field对应Constant Pool里的index。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
... DEF_OPC_RW(OPC_GETSTATIC, ({ int idx, cache, opcode; FieldBlock *fb; Operand operand; WITH_OPCODE_CHANGE_CP_DINDEX(OPC_GETSTATIC, idx, cache); frame->last_pc = pc; <strong>fb = resolveField(mb->class, idx);</strong> if(fb != NULL) initClass(fb->class); if(exceptionOccurred0(ee)) goto throwException; if((*fb->type == 'J') || (*fb->type == 'D')) opcode = OPC_GETSTATIC2_QUICK; else if(*fb->type == 'L' || *fb->type == '[') opcode = OPC_GETSTATIC_QUICK_REF; else opcode = OPC_GETSTATIC_QUICK; operand.pntr = fb; OPCODE_REWRITE(opcode, cache, operand); REDISPATCH });) ... |
resolveField中被调用resolveClass函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
FieldBlock *resolveField(Class *class, int cp_index) { ConstantPool *cp = &(CLASS_CB(class)->constant_pool); FieldBlock *fb = NULL; retry: switch(CP_TYPE(cp, cp_index)) { ... case CONSTANT_Fieldref: { Class *resolved_class; char *fieldname, *fieldtype; int cl_idx = CP_FIELD_CLASS(cp, cp_index); int name_type_idx = CP_FIELD_NAME_TYPE(cp, cp_index); MBARRIER(); if(CP_TYPE(cp, cp_index) != CONSTANT_Fieldref) goto retry; fieldname = CP_UTF8(cp, CP_NAME_TYPE_NAME(cp, name_type_idx)); fieldtype = CP_UTF8(cp, CP_NAME_TYPE_TYPE(cp, name_type_idx)); <strong>resolved_class = resolveClass(class, cl_idx, TRUE, FALSE);</strong> ... break; } } return fb; } |
resolveClass又回调用findClassFromClass(其实是个Macro),同样传入class指针。看看Macro的定义,就可以很清楚了。
|
#define findClassFromClass(classname, class) \ (CLASS_CB(class)->name == classname ? class : \ findClassFromClassLoader(classname, CLASS_CB(class)->class_loader)) |
是从ClassBlock结构中找到对应的ClassLoader.
其实记住这个结论就好。这样就可以完全打错传统的ClassLoader的限制,比如OSGi Plugin/Bundle里的所有类就是由OSGi自己的加载器加载的,非常灵活,可以实现非常牛逼的功能!