JVM——类加载与字节码技术—字节码指令

2.字节码指令

2.1 入门

jvm的解释器可以识别平台无关的字节码指令,解释为机器码执行。

 

 

 2a b7  00 01  b1

this .    init() return

 

准备了System.out对象,准备了参数“hello world”,准备了对象的方法println(String)V,并return

2.2 javap 工具

这里常量池直接把查询结果放在了右边。 

有了javap,终于不用看那狗屎字节码文件了 

这部分是方法信息里的init构造方法。

 main方法

有参数类型,访问类型,方法属性,局部变量表,方法参数信息等等

2.3 图解方法执行流程

1)原始 java 代码

b是Short类型的最大值+1。 

2)编译后的字节码文件

3)常量池载入运行时常量池

java代码执行时会由java虚拟机的类加载器将main方法所在类进行类加载。

类加载就是把class文件里的字节数据读取到内存里面。

运行时常量池是方法区的组成部分

 32768对应的是源代码里面的short.value+1,比较小的数字不会存储在常量池,比如10,10会跟着方法的字节码指令存一起,一旦数字范围超过整数最大值就会存储在常量池中。

4)方法字节码载入方法区

5) main 线程开始运行,分配栈帧内存

绿色区域是局部变量表,蓝色是操作数。字节码指令里面有一个栈的最大深度和局部变量表的长度。这两项决定了栈帧内存大小。

6)执行引擎开始执行字节码

bipush 10

istore_1

 然后a被复制为10,对应操作就是a=10

1dc #3

 istore 2

  

iload1

局部变量表中不能执行a+b的操作,所以,执行引擎会对它们进行一个读取。

iload2

iadd

 iadd操作是将操作数栈中的两个数取出来相加再放回去。

istore 3

给c赋值

 

getstatic #4

这个是到常量池中找一个成员变量的引用。这里是找System.out。找到之后不是把对象放入操作数栈,而是获取引用

 

 iload_3

执行打印需要参数c,所以将局部变量表中c的值32778读入到操作数栈

 

 invokevirtual #5

在常量池中找到5号条目,执行println(I)方法,参数 l 表示整数。

 println方法执行时会找到方法区中新的方法,然后分配一个新的栈帧

执行时会把32778作为参数传递给新的栈帧中作为整数参数完成打印操作。

 return

 2.4练习-分析a++

分析

a++执行的指令是iinc,但是这玩意直接原地拉屎变大,不需要进栈又出栈。

a++是iload先,++a是iinc先

iinc的两个参数,一个是要对哪个槽位做自增,一个是自增多少。

 

 

 

 

 

 

 到这里第一个加法结束了。

 

2.5 条件判断指令

 

 较小的数用iconst表示,-1到5的数

ifne 不成立时会跳转到12行,压20入栈然后往下执行。

成立时就直接往下执行然后到goto跳过12,14,直接返回

 

2.6 循环控制指令

 依旧是if+goto

 if_icmpge判断是否大于等于10,是的话就跳到14

do_while

for循环

2.7 练习 - 判断结果

 先load,再iinc,最后istore,又把栈里的load到的数据放回去了。

先把0读进操作数栈的,然后局部变量表上x自增1变成,然后将局部变量表上的0赋值给x.

2.8 构造方法

1) <cinit>()v

静态变量初始化,静态代码块从上到下依次执行

 

cinit是整个类的构造方法。

2) <init>()V

init是实例的构造方法。

从上到下有成员变量,初始化代码块,有参构造。

最后答案是s3 30

2.9方法调用

类中从上到下有构造方法,私有方法,final方法,公共方法,静态方法。

通过对象和类型都调用了静态方法 

有三种指令出现。

invokevirtual是动态绑定,公共方法有可能子类也有可能父类,要在运行时确定。

另外两个都是静态绑定,可以直接找到执行地址。

执行new的时候会先分配内存给它,然后把对象的引用放到操作数栈。

dup是对栈顶的复制,操作数栈里有两个相同的引用。

invokespecial会根据栈顶的引用调用对应的构造方法。 这里消耗一个引用

astore_1会根据剩余的引用出栈存储到局部变量表中。这里消耗一个引用

执行到d.test4()时先把引用放入栈,但由于静态方法不需要引用,所以又pop弹出了,然后用invokestatic执行test4了。

要调用静态方法直接用类名去调用即可,否则会产生多余的虚拟机指令。

2.10 多态的原理

在上面有一个invokevirtual不能直接找到地址去执行,需要找到是父类还是子类。

研究invokevirtual就是研究多态的原理

面试高频题:讲讲什么是多态,底层原理是啥

1) 运行代码

64位操作系统为了节省内存用了指针压缩,查看地址时要换算不方便

 

代码中一个Animal父类,一个抽象方法eat(),一个toString方法,还有两个子类继承了Animal父类。

在公共类中有一个test方法,参数是Animal,这里产生了多态,实际对象可能是cat,也可能是dog. 

2)运行 HSDB 工具

JDK9之后,执行JHSDB HSDB 

 

3)找某个对象

 

 查询语句和sql语句十分相似,这里通过查询类型别名查到dog对象在内存中的地址。

这里虚拟机中只有一个dog对象,所以查到的是唯一dog.

4)查看对象内存结构

5) 查看对象 Class 的内存地址

 第二行是类型指针,用类型指针继续查

 上面是类的结构。

6)查看类的 vtable

接着找类中的方法,多态的方法存在vtable虚方法表中。在类结构的最后。

 是该类的地址加上1B8就是vtable地址。vtable长度是6。

然后看见6个支持重写的方法的入口地址。

7)验证方法地址

在虚方法表中的最后一个方法对应的就是dog类的eat方法。

 因为dog类没有重写父类,用的是Animal的toString方法。

 ​​​​​​​

方法表中的第一项有Object的finalize,clone,equals方法 ,因为Animal和dog都没有重写这些方法。

8) 小结

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

类加载阶段指的是 验证、准备、解析 这三个阶段,即加载之后,初始化之前、 

2.11 异常处理

try-catch

2 4 是try中的内容, try中如果没有发生异常,就会直接去到12了。

借助Exception table异常表检测[2~5)行内容,不包含5,2~4有异常会先跟声明的异常是否一致或是子类异常,是的话就会进入第8行。

第8行astore_2是把异常对象的引用地址存储下面局部变量的e槽位上,就是catch那一行的执行。

9,11就是i=20.

多个single-catch 块的情况

 

 

与try_catch的相差不多。

multi-catch 的情况

直接一个catch块捕获多个异常。

 

finally

 字节码

因为有可能发生Exception父类的异常,所以异常表里面又多了别的异常类型。 

finally的工作方法就是将finally中的东西放在每一个分支后面,在reutrn前面,以此保证一定会被执行。

因此有三个分支,一个是try,一个是Exception的catch,一个是非Exception的catch.

 2.12 练习 - finally 面试题

finally 出现了 return

 正确答案是20。

 

 简单来说,就是即使报了异常,但是最后还是执行finally例的ireturn,不会执行athrow

抛异常和返回值,这两个是冲突的,只能执行一个,平时绝对不能在finally中return

该代码最后正常执行完没有除零报错。

finally 对返回值影响

 最后返回的是10

2.13 synchronized

new时复制了一份,一个用于调用构造方法,一个是给了局部变量表。

synchronized(lock)先将lock引用加载到操作数栈,然后又复制了一份。

待会一个给monitorenter 指令用,一个给了monitorexit指令用,加锁和解锁。

然后一个lock存入局部变量表2槽,剩下那个给了monitorenter 加锁。

然后12~17是打印指令

20~22是把2号槽位的引用加载到栈顶并给monitorexit解锁,然后goto return正常结束。

 如果12~22有异常会进到25.

25将错误保存到局部变量表。26~27将lock引用给monitorexit解锁。

28,29加载异常类抛出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/86978.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何优化因为高亮造成的大文本(大字段)检索缓慢问题

首先还是说一下背景&#xff0c;工作中用到了 elasticsearch 的检索以及高亮展示&#xff0c;但是索引中的content字段是读取的大文本内容&#xff0c;所以后果就是索引的单个字段很大&#xff0c;造成单独检索请求的时候速度还可以&#xff0c;但是加入高亮之后检索请求的耗时…

Prometheus+Grafana+AlertManager监控Linux主机状态

文章目录 PrometheusGrafanaAlertManager监控平台搭建开始监控Grafana连接Prometheus数据源导入Grafana模板监控Linux主机状态 同系列文章 PrometheusGrafanaAlertManager监控平台搭建 Docker搭建并配置Prometheus Docker拉取并配置Grafana Docker安装并配置Node-Exporter …

WordArt Designer:基于用户驱动与大语言模型的艺术字生成

AIGC推荐 FaceChain人物写真开源项目&#xff0c;支持风格与穿着自定义&#xff0c;登顶github趋势榜首&#xff01; 前言 本文介绍了一个基于用户驱动&#xff0c;依赖于大型语言模型(LLMs)的艺术字生成框架&#xff0c;WordArt Designer。 该系统包含四个关键模块:LLM引擎、…

微人事 登录问题完善

重启服务端的时候&#xff0c;发现前端页面会操作不了&#xff0c;这样后端session会失效&#xff0c;我们就需要让页面重新跳转到登录页 springsecurity配置类后端配置 前端拦截器进行拦截跳转

【C++数据结构】二叉搜索树

【C数据结构】二叉搜索树 目录 【C数据结构】二叉搜索树二叉搜索树概念二叉搜索树操作二叉搜索树的查找二叉搜索树的插入二叉搜索树的删除二叉搜索树的实现二叉搜索树的应用二叉搜索树的性能分析 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.8.22 前言&#xff1a;二…

SpringMVC入门笔记

一、SpringMVC简介 1. 什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体类Bean&#xff1…

怎么维护自己的电脑

文章目录 我的电脑日常维护措施维护技巧键盘&屏幕清洁清理磁盘空间控制温度 电脑换电池 无论是学习还是工作&#xff0c;电脑都是IT人必不可少的重要武器&#xff0c;一台好电脑除了自身配置要经得起考验&#xff0c;后期主人对它的维护也是决定它寿命的重要因素&#xff0…

如何使用NLP库解析Python中的文本

Python是一种强大的面向对象的编程&#xff08;object-oriented programming&#xff0c;OOP&#xff09;语言&#xff0c;在人工智能领域有着广泛的用途。正是鉴于其实用性&#xff0c;以Google为首的大型科技公司&#xff0c;已经对其开发了Tensorflow等代码库&#xff0c;帮…

Flask狼书笔记 | 03_模板

文章目录 3 模板3.1 模板基本使用3.2 模板结构组织3.3 模板进阶 3 模板 模板&#xff08;template&#xff09;&#xff1a;包含固定内容和动态部分的可重用文件。Jinja2模板引擎可用于任何纯文本文件。 3.1 模板基本使用 HTML实体&#xff1a;https://dev.w3.org/html5/htm…

Ubuntu系统安装之后首需要做的事情

Ubuntu系统的初步环境搭建 1、换源2、显卡3、浏览器4、输入法5、终端6、ROS7、VSCode8、设置时间与win一致9、 TimeShift10、 Anaconda&#xff08;考虑装不装&#xff09; 1、换源 点开Software&&Update&#xff0c;找到Ubuntu Software中的Download from&#xff0c…

数据通信——传输层(UDP)

引言 我们上网观看比赛的时候&#xff0c;一旦网络信号出现问题&#xff0c;那可就太难受了&#xff0c;这意味着卡顿的时间内&#xff0c;你会错过这段时间内的内容。这种特性要归功于UDP&#xff08;User Datagram Protocol&#xff09;用户数据报协议。 无连接性 一般的&am…

IntelliJ IDEA maven配置,设置pom.xml的配置文件

IntelliJ IDEA项目&#xff0c;选择 文件 设置&#xff0c;弹窗 构建、执行、部署 构建工具 Maven就可以 maven配置好以后&#xff0c;在pom.xml的配置文件中就可以设置对应的jar包了&#xff0c;这样构建的时候自动需要的jar&#xff0c;在项目中导入即 需要的jar包设置在po…

解锁ChatGLM-6B的潜力:优化大语言模型训练,突破任务困难与答案解析难题

解锁ChatGLM-6B的潜力&#xff1a;优化大语言模型训练&#xff0c;突破任务困难与答案解析难题 LLM&#xff08;Large Language Model&#xff09;通常拥有大量的先验知识&#xff0c;使得其在许多自然语言处理任务上都有着不错的性能。 但&#xff0c;想要直接利用 LLM 完成…

UML 类图

1、概述 目录 1、概述 1.1、UML概念 1.2、类图的概念 2、类的表示方式 2.1、普通类 2.2、抽象类 2.3、接口 3、类与类关系的表示 3.1、关联关系&#xff08;Association&#xff09; 3.1.1、单向关联 3.1.2、双向关联 3.1.3、自关联 3.2、聚合关系&#xff08;aggre…

无涯教程-TensorFlow - 单词嵌入

Word embedding是从离散对象(如单词)映射到向量和实数的概念&#xff0c;可将离散的输入对象有效地转换为有用的向量。 Word embedding的输入如下所示: blue: (0.01359, 0.00075997, 0.24608, ..., -0.2524, 1.0048, 0.06259) blues: (0.01396, 0.11887, -0.48963, ..., 0.03…

【Unity】Text文本组件的一些操作

Unity的Text组件的几种常见的操作方法 Text组件是Unity中用于在UI界面上显示文本的组件。它包含了一些常见的属性和方法&#xff0c;可以用来控制文本的内容、外观和交互。以下是一些常见的Text组件的操作&#xff1a; 设置文本内容&#xff1a;通过直接在Unity编辑器中的Text…

SpringCloud学习笔记(三)_服务提供者集群与服务发现Discovery

服务提供者集群 既然SpringCloud的是微服务结构&#xff0c;那么对于同一种服务&#xff0c;当然不可能只有一个节点&#xff0c;需要部署多个节点 架构图如下&#xff1a; 由上可以看出存在多个同一种服务提供者&#xff08;Service Provider&#xff09; 搭建服务提供者集…

Mybatis-动态sql和分页

目录 一.什么是Mybatis动态分页 二.mybatis中的动态SQL 在BookMaaper.xml中写sql BookMapper BookBiz接口类 BookBizImpl实现接口类 demo测试类 ​编辑 测试结果 三.mybatis中的模糊查询 mybatis中的#与$有是什么区别 在BookMapper.xml里面建立三个模糊查询 ​编辑 …

腾讯云-对象存储服务(COS)的使用总结

简介 对象存储&#xff08;Cloud Object Storage&#xff0c;COS&#xff09;是腾讯云提供的一种存储海量文件的分布式存储服务&#xff0c;具有高扩展性、低成本、可靠安全等优点。通过控制台、API、SDK 和工具等多样化方式&#xff0c;用户可简单、快速地接入 COS&#xff0…

73 # 发布自己的 http-server 到 npm

1、添加 .npmignore 文件&#xff0c;忽略不需要的文件 public2、去官网https://www.npmjs.com/检查自己的包名是否被占用 3、切换到官方源&#xff0c;然后检查确认 nrm use npm nrm ls4、登录 npm 账号 npm login5、发布 npm publish6、查看发布情况&#xff0c;发布成功…