![Java虚拟机字节码:从入门到实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/230/35091230/b_35091230.jpg)
解析this与super
在Class文件结构中,紧挨着访问标志access_flags项的是this_class和super_class这两项,也都是U2类型。this_class存储的是常量池中某项常量的索引,super_class要么为0,要么也是存储常量池中某项常量的索引[1]。this_class和super_class指向的常量必须是一个CONSTANT_Class_info结构的常量。
只有Object类的super_class可以为0,接口的super_class指向常量池中Object类的CONSTANT_Class_info常量。
this_class与super_class的解析器实现非常简单,如代码清单2-37所示。
代码清单2-37 this_class与super_class解析器
public class ThisAndSuperClassHandler implements BaseByteCodeHandler { @Override public int order() { return 4; } @Override public void read(ByteBuffer codeBuf, ClassFile classFile) throws Exception { classFile.setThis_class(new U2(codeBuf.get(), codeBuf.get())); classFile.setSuper_class(new U2(codeBuf.get(), codeBuf.get())); } }
由于该项目已经完成了常量池的解析,在解析获取到this_class与super_class之后,我们就可以先根据this_class的值到常量池取得对应的CONSTANT_Class_info常量,再从取得的CONSTANT_Class_info常量中获取该常量的name_index的值,最后根据name_index再回到常量池中取得对应的CONSTANT_Utf8_info常量,这样就能获取到具体的类名了。该过程描述如图2.6所示。
![](https://epubservercos.yuewen.com/0CE4E9/18727238908638606/epubprivate/OEBPS/Images/001_image21.jpg?sign=1739020650-nMiuHE1GER0ytSdYc9uFfXX3QPC4K10e-0-b4092208d4e06360f89beb6e05513182)
图2.6 获取this_class指向的类名
现在我们编写单元测试验证this与super解析器。为了直观的显示解析结果,我们需要在单元测试用例中,将解析后的this_class与super_class指向的CONSTANT_Class_info常量转为CONSTANT_Utf8_info常量,直接输出字符串类名。如代码清单2-38所示。
代码清单2-38 this与super解析器单元测试
public class ThisAndSuperHandlerTest { @Test public void testThisAndSuperHandlerHandler() throws Exception { ByteBuffer codeBuf = ClassFileAnalysisMain.readFile("RecursionAlgorithmMain.class"); ClassFile classFile = ClassFileAnalysiser.analysis(codeBuf); // this_class U2 this_class = classFile.getThis_class(); // 根据this_class到常量池获取CONSTANT_Class_info常量 // 由于常量池的索引是从1开始的,所以需要将索引减1取得数组下标 CONSTANT_Class_info this_class_cpInfo = (CONSTANT_Class_info) classFile.getConstant_pool()[this_class.toInt() - 1]; CONSTANT_Utf8_info this_class_name= (CONSTANT_Utf8_info) classFile.getConstant_pool() [this_class_cpInfo.getName_index().toInt()-1]; System.out.println(this_class_name); // super_class U2 super_class = classFile.getSuper_class(); CONSTANT_Class_info super_class_cpInfo = (CONSTANT_Class_info) classFile.getConstant_pool() [super_class.toInt() - 1]; CONSTANT_Utf8_info supor_class_name = (CONSTANT_Utf8_info) classFile.getConstant_pool() [super_class_cpInfo.getName_index().toInt()-1]; System.out.println(supor_class_name); } }
单元测试结果输出如图2.7所示。
![](https://epubservercos.yuewen.com/0CE4E9/18727238908638606/epubprivate/OEBPS/Images/001_image22.jpg?sign=1739020650-jHinaBd6iWFblqbhA8ILv7GZJii1R2XS-0-caa8fadf896d1045c2b2938017506a3c)
图2.7 this与super解析器单元测试
从输出的结果可以看出,该class文件的类名为RecursionAlgorithmMain,父类的类名为Object。
注释:
[1] 常量池索引都是从1开始的,0就表示不使用