类和对象相关指令
本节继续来学习类和对象相关指令
putstatic和getstatic指令
putstatic指令给类的某个静态变量赋值,它需要两个操作数,第一个操作数是uint16索引,来自字节码。通过这个索引可以从当前类的运行时常量池中找到一个字段符号引用,解析这个字段符号引用就可以知道给类的哪个静态变量赋值。第二个操作数是要赋给静态变量的值,从操作数栈中弹出。该指令实现代码位于putstatic.go文件中:
|
|
getstatic指令和putstatic指令正好相反,它取出类的某个静态变量值,然后推入操作数栈顶。其实现代码位于getstatic.go文件中,代码与putstatic类似,这里就不贴出来了,参照项目源码。
putfield和getfield指令
putfield指令给实例变量赋值,它需要三个操作数。前两个操作数是常量池索引和变量值,用法和putstatic差不多。第三个操作数时对象引用,从操作数栈中弹出。实现代码位于putfield.go文件中:
getfield指令获取对象的实例变量值,然后推入操作数栈,它需要两个操作数。第一个操作数是uint16索引,用法和前面一样。第二个操作数是对象引用,和putfield指令类似,其实现代码位于getfield.go文件中,这里就不贴出来了,参照项目源码。
instanceof和checkcast指令
instanceof指令判断对象是否是某个类的实例(或对象的类是否实现了某个接口),并把结果推入操作数栈。instanceof指令需要两个操作数。第一个操作数是uint16索引,从方法的字节码中获取,通过这个索引可以从当前类的运行时常量池中找到一个类符号引用。第二个数是对象引用,从操作数栈中弹出。该实现代码位于instanceof.go文件中:
checkcast指令和instanceof指令很像,区别在于:instanceof指令会改变操作数栈(弹出对象引用,入栈判断结果);checkcast则不改变操作数栈(如果判断失败,直接跑出异常),checkcast指令实现代码位于checkcast.go文件中,和instanceof指令类似,这里不贴出来了,参照项目源码。
下面来重点来实现IsInstanceOf()函数,修改object.go文件:
真正的逻辑在Class结构体的isAssignableFrom()函数中,这个方法稍微有些复杂,单独定义在/rtdata/heap/class_hierarchy.go文件中: