首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Java字节码角度分析多态原理 ——提升硬实力8

  • 25-03-07 20:01
  • 3807
  • 7069
blog.csdn.net

在前面的文章中,有详细地介绍java字节码相关的知识,有兴趣的可以提前了解一下。

1.Java字节码的一段旅行经历——提升硬实力1

2.Java字节码角度分析a++ ——提升硬实力2

3.Java字节码角度分析条件判断指令 ——提升硬实力3

4.Java字节码角度分析循环控制 ——提升硬实力4

5.Java字节码角度分析判断结果 ——提升硬实力5

6.Java字节码角度分析构造方法 ——提升硬实力6

7.Java字节码角度分析方法调用 ——提升硬实力7


通过:7.Java字节码角度分析方法调用 ——提升硬实力7,我们已经知道了如下知识:

  1. invokespecial只能调用三类方法:方法、private方法、super.method()。因为这三类方法的调用对象在编译时就可以确定。
  2. invokevirtual是一种动态分派的调用指令:也就是引用的类型并不能决定方法属于哪个类型。

接下来,我们将以字节码的视角来分析java多态原理,先来看一下java多态实现的示例:

  1. // 从字节码角度来分析:多态原理
  2. /**
  3. * 演示多态原理,注意加上下面的 JVM参数,禁用指针压缩
  4. * -XX:-UseCompressedOops -XX:-UseCompressedClassPointers
  5. */
  6. public class T12_ByteAnalyseDuoTai {
  7. // 此处,就会有多态应用。
  8. public static void test(Animal animal) {
  9. // 因为animal有可能是狗,也可能是猫,且不同对象eat方法实现不一样
  10. // 后续将演示eat方法是哪个对象调用,从字节码角度对eat方法查找调用过程
  11. animal.eat();
  12. System.out.println(animal.toString());
  13. }
  14. public static void main(String[] args) throws IOException {
  15. test(new Cat());
  16. test(new Dog());
  17. System.in.read();
  18. }
  19. }
  20. abstract class Animal {
  21. public abstract void eat();
  22. @Override
  23. public String toString() {
  24. return "我是" + this.getClass().getSimpleName();
  25. }
  26. }
  27. class Dog extends Animal {
  28. @Override
  29. public void eat() {
  30. System.out.println("啃骨头");
  31. }
  32. }
  33. class Cat extends Animal {
  34. @Override
  35. public void eat() {
  36. System.out.println("吃鱼");
  37. }
  38. }

上述代码通过:javap -v T12_ByteAnalyseDuoTai.class进行反编译,得到如下字节码。得到:动态方法在字节码层面是通过invokevirtual 来调用的。

上述代码产生的多态应用,因为Animal具体实例有可能是狗,也可能是猫,且不同对象 eat() 方法实现不一样,接下来将演示 eat() 方法是哪个对象调用,从字节码角度对 eat() 方法查找调用过程

1、运行代码

  • 停在System.in.read() 方法上,这时运行jps获取进程id

2、运行HSDB工具

  • 进入JDK安装目录,执行:java -cp ./lib/sa-jdi.jar sun.jvm.hotspot.HSDB
  • 进入图形界面attach 进程id

3、HSDB - HotSpot Debugger -> Tools -> Find Object by Query

输入查询语句:select d from com.jvm.t07_bytecode.T12_ByteAnalyseDuoTai.Dog d,如下图

    

点击Dog 对象内存地址,就会得到Dog对象在内存的实际表示,如下图:

接下来,继续通过Dog对象内存地址继续查看Dog对象在内存的表现形式

我们复制0x000000001c794028,继续在【Tools】-> 【Inspector】查看对象在java内存的完整表示,如下:

接下来,继续查找多态方法。多态方法是存在于一张叫vtable虚方法表中,在Dog类对象在java内存的完整表示最后面。找到虚方法表,需要在当前地址 0x000000001c794028 加上 1B8 = 0x000000001c7941E0

接下来通过【Windows】 -> 【console】查找Dog类对应的虚方法表信息,指令如下:其中6是指虚方法表的长度

  • mem 0x000000001c7941E0 6

得到了Dog类对应所有重写方法的入口地址,如下图:

上述说的Dog类所有重写的方法,具体对应哪些方法呢。我们知道Dog类继承自Animal,Animal继承自Object。接下来,分别从Dog、Animal、Object类进行查找。通过【Tools】 -> 【Class Browser】

说明:Dog类vtable虚方法表中调用的 eat() 方法是 Dog 类的 eat() 方法,不是 Cat 类的 eat() 方法,也不是 Animal 类的 eat() 方法。

 

接下来继续虚方法表vtable其他方法调用的是哪个方法,查找Dog类的父类Animal类, 如下图:

说明:Dog类虚方法表中 toString() 方法调用的是 Animal 的 toString() 方法,因为 Dog 类没有 toString() 方法,因父类 Animal 有 toString() 方法。

 

最后,再来看一下Object类,如下图:

总结:通过对象找到它的 Class 类,获取到它的虚方法表后,就能确定虚方法表中每个方法实际的方法入口地址。有的来自于自己(eat方法),有的来自于父类(toString方法)。将来,对象调用方法时,就能明确知道调用哪个方法了。最后提醒大家,虚方法表是在类的加载过程的链接阶段生成的,所以在链接阶段就已经确定了虚方法表每个方法的入口地址


小结

一句话总结:invokevirtual 指令调用的对象vtable中的方法。

多态方法调用,当执行 invokevirtual指令时,

  1. 先通过栈帧中的对象引用找到对象
  2. 分析对象头,找到对象的实际Class
  3. Class结构中有vtable,它在类加载的链接阶段就已经根据方法的重写规则生成好了
  4. 查表到得方法的具体地址
  5. 执行方法的字节码

多态方法调用,需要在执行过程中经过虚方法表多次查找,过程比较复杂。如果从细微的效率来说,它是不如static。

当然jvm底层也做很多虚方法表查找过程的优化,比如缓存、经常查找的方法放入缓存,这样查找较快。如果Animal只有Dog继承,没有Cat继承的话,jvm会将多态转换为单态,这样加快方法的寻址速度。

 


文章最后,给大家推荐一些受欢迎的技术博客链接:

  1. Hadoop相关技术博客链接
  2. Spark 核心技术链接
  3. JAVA相关的深度技术博客链接
  4. 超全干货--Flink思维导图,花了3周左右编写、校对
  5. 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
  6. 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
  7. 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂

 


欢迎扫描下方的二维码或 搜索 公众号“10点进修”,我们会有更多、且及时的资料推送给您,欢迎多多交流!

                                           

       

注:本文转载自blog.csdn.net的不埋雷的探长的文章"https://blog.csdn.net/weixin_32265569/article/details/108018667"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top