【实战JVM】-基础篇-01-JVM通识-字节码详解

【实战JVM】-基础篇-01-JVM通识-字节码详解-类的声明周期-加载器

  • 1 初识JVM
    • 1.1 什么是JVM
    • 1.2 JVM的功能
      • 1.2.1 即时编译
    • 1.3 常见JVM
  • 2 字节码文件详解
    • 2.1 Java虚拟机的组成
    • 2.2 字节码文件的组成
      • 2.2.1 正确打开字节码文件
      • 2.2.2 字节码组成
      • 2.2.3 基础信息
        • 2.2.3.1 魔数
        • 2.2.3.1 主副版本号
      • 2.2.4 常量池
      • 2.2.5 方法
    • 2.3 linux中打开字节码文件
    • 2.4 字节码常用工具 Arthas
      • 2.4.1 安装Arthas
      • 2.4.2 Arthas功能
        • 2.4.2.1 获取系统实时面板-dashboard
        • 2.4.2.2 加载特定类的字节码-dump
        • 2.4.2.3 反编译已加载类的源码-jad
        • 2.4.2.4 查看JVM已加载的类信息-sc


1 初识JVM

1.1 什么是JVM

在这里插入图片描述
在这里插入图片描述

1.2 JVM的功能

在这里插入图片描述

1.2.1 即时编译

即时编译Just-In-Time 简称JIT进行性能的优化,最终到达接近C、C++的性能

在这里插入图片描述
在这里插入图片描述

将热点代码转换为机器码后保存至RAM,下次执行时直接从RAM中调用。

在这里插入图片描述

1.3 常见JVM

在这里插入图片描述

java -version

在这里插入图片描述

2 字节码文件详解

2.1 Java虚拟机的组成

在这里插入图片描述

2.2 字节码文件的组成

2.2.1 正确打开字节码文件

安装jclasslib

在这里插入图片描述
打开任意一个class文件
在这里插入图片描述

2.2.2 字节码组成

  • 基础信息(一般信息+接口):

    • 魔数、字节码对应的java版本号,访问标识(public、final等),以及这个类父类是哪个,以及实现了哪些接口
  • 常量池:

    • 保存了字符串常量、类、接口名、字段名。主要在字节码指令中使用。
    • 在这里插入图片描述
  • 字段:

    • 当前类或接口的字段信息,包括名字,描述符,访问标识。

    • private final static int a1=0
      
    • 在这里插入图片描述

  • 方法:

    • 当前类或接口的声明的方法信息字节码指令
    • 在这里插入图片描述
  • 属性:

    • 类的属性,比如源码的名字、内部类的列表等
    • 在这里插入图片描述

2.2.3 基础信息

在这里插入图片描述

在这里插入图片描述

2.2.3.1 魔数

在这里插入图片描述

在这里插入图片描述

打开二进制的png文件,就是以89504E47开始的

在这里插入图片描述

jpg则以FFD8FF开始

在这里插入图片描述

java字节码则是以CAFEBABE开始

在这里插入图片描述

2.2.3.1 主副版本号

在这里插入图片描述

52对应jdk1.8 61则对应jdk17

2.2.4 常量池

public class HelloWorld{public static final String a1= "a1a1a1";public static final String a2= "a1a1a1";public static void main(String[] args){System.out.println("Hello world!");}
}

查看编译后的class文件

在这里插入图片描述

两个都是常量,且指向同一块常量值索引,CONSTANT_String_info存放着cp_info #33,依旧是个索引

在这里插入图片描述

查看cp_info #33,这时候字面量才是a1a1a1

在这里插入图片描述

为什么要两级索引呢?这是因为在jvm中的运行时数据区域中有这方法区,方法区主要用来存储已被虚拟机加载的类的信息、常量、静态变量和即时编译器编译后的代码等数据。方法区里有一个运行时常量池,用于存放静态编译产生的字面量和符号引用。该常量池具有动态性,也就是说常量并不一定是编译时确定,运行时生成的常量也会存在这个常量池中。

在这里插入图片描述

public class HelloWorld{public static final String a1= "abc";public static final String a2= "abc";public static final String abc= "abc";public static void main(String[] args){System.out.println("Hello world!");}
}

比如字段名和常量名都叫abc,但常量名是abc是String类型,而字段名是无类型的,但是都指向utf8格式的abc

在这里插入图片描述

2.2.5 方法

public static void main(String[] args){int i=0;i=i++;System.out.println(i);
}

对应字节码:

 0 iconst_0   			//操作数栈: [] -> [0],将常量值0压入操作数栈。1 istore_1   			//操作数栈: [0] -> [],将操作数栈顶的整数值(0)存入本地变量1。2 iload_1    			//操作数栈: [] -> [0],将本地变量1中的整数值(0)加载到操作数栈。3 iinc 1 by 1 			//本地变量1的值增加1。原值是0,现在变为1。6 istore_1				//操作数栈: [0] -> [],将操作数栈顶的整数值存入本地变量1。本地变量: [1]-> [0],7 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>  //获取System.out的值并压入操作数栈。
10 iload_1				//操作数栈: [Ljava/io/PrintStream;] -> [Ljava/io/PrintStream;, 0],将本地变量1中的整数值加载到操作数栈。
11 invokevirtual #3 <java/io/PrintStream.println : (I)V>
14 return

i处于局部变量表的1号位

在这里插入图片描述

如果换成++i

public static void main(String[] args){int i=0;i=++i;System.out.println(i);
}
 0 iconst_01 istore_1				//0放到本地变量表2 iinc 1 by 1			//本地变量表先自增,0->15 iload_1				//将本地变量1中的整数值(1)加载到操作数栈。6 istore_1				//操作数栈: [1] -> [],将操作数栈顶的整数值存入本地变量1。本地变量: [1]-> [1],7 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
10 iload_1
11 invokevirtual #3 <java/io/PrintStream.println : (I)V>
14 return

这样就不会发生i=i++这种覆盖赋值的情况了。

作业:

int i=0,j=0,k=0;
i++;
j=j+1;
k+=1;

i和k一样快,都是把0从操作数栈中放入本地变量中直接操作本地变量自增。

j最慢,从本地变量表中加载到操作数栈中,再加载1,再相加,再放入本地变量表。

2.3 linux中打开字节码文件

在这里插入图片描述

javap -v 字节码文件名称

2.4 字节码常用工具 Arthas

2.4.1 安装Arthas

在这里插入图片描述

启动arthas

在这里插入图片描述

先启动项目再分析

public class ArthasDemo {public static void main(String[] args) {while (true) {try {Thread.sleep(2000L);} catch (InterruptedException e) {e.printStackTrace();}}}
}

在arthas工作目录中启动

java -Dfile.encoding=UTF-8 -jar arthas-boot.jar

-Dfile.encoding=UTF-8是让arthas以utf8格式启动,这样不会乱码
在这里插入图片描述

成功捕获到ArthasDemo,选择3回车进入arthas内部,他还自动下载了arthas3.7.2版本

3

在这里插入图片描述

2.4.2 Arthas功能

在这里插入图片描述

2.4.2.1 获取系统实时面板-dashboard

在这里插入图片描述

我们设置每隔两秒刷新一次,刷新3次

dashboard -i 2000 -n 3

在这里插入图片描述

只显示1次

在这里插入图片描述

2.4.2.2 加载特定类的字节码-dump

在这里插入图片描述

dump -d D:/File/StudyJavaFile/JavaStudy/JVM/low/day01/resource/ com.sjb.arthas.ArthasDemo

在这里插入图片描述

在这里插入图片描述

这样就获取了运行时的java文件的字节码信息

2.4.2.3 反编译已加载类的源码-jad
jad com.sjb.arthas.ArthasDemo

在这里插入图片描述

和我们的源码几乎一致

案例

在这里插入图片描述

启动springboot-classfile后

在这里插入图片描述

public UserVO user(@PathVariable("type") Integer type,@PathVariable("id") Integer id){//前边有一大堆逻辑,巴拉巴拉if(type==UserType.REGULAR.getType()){return new UserVO(id,"普通用户无权限查看");}return new UserVO(id,"这是尊贵的收费用户才能看的秘密!");
}

不能用==来判断类型,需要equals

在这里插入图片描述

在这里插入图片描述

即使是普通用户,但是因为用的==判断的类型,也能进入vip用户

使用jad查看

jad com.itheima.springbootclassfile.controller.UserController

在这里插入图片描述

定位到问题信息,以供以后热更新

2.4.2.4 查看JVM已加载的类信息-sc

在这里插入图片描述

sc -d 类名(java.lang.String)

查看当前类的类加载器,如果为空,则为启动类加载器。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】右值引用 移动语义

目录 前言一、右值引用与移动语义1.1 左值引用和右值引用1.2 右值引用使用场景和意义1.3 右值引用引用左值及其一些更深入的使用场景分析1.3.1 完美转发 二、新的类功能三、可变参数模板 前言 本篇文章我们继续来聊聊C11新增的一些语法——右值引用&#xff0c;我们在之前就已…

进程间通信的方式中,socket和消息队列的区别

进程间通信的方式中&#xff0c;socket和消息队列的区别 进程间通信方式中&#xff0c;socket和消息队列的主要区别在于通信的方式和跨机通信的能力。 socket是通过网络传输的方式来实现进程间通信&#xff0c;并且可以跨主机&#xff1b;而消息队列是通过内核提供的缓冲区进…

Flutter 中的 AbsorbPointer 小部件:全面指南

Flutter 中的 AbsorbPointer 小部件&#xff1a;全面指南 在Flutter中&#xff0c;AbsorbPointer是一个特殊的小部件&#xff0c;用于吸收&#xff08;或“吞噬”&#xff09;所有传递到其子组件的指针事件&#xff08;如触摸或鼠标点击&#xff09;。这在某些情况下非常有用&…

民国漫画杂志《时代漫画》第22期.PDF

时代漫画22.PDF: https://url03.ctfile.com/f/1779803-1248634856-2c7010?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

Typescript高级: 深入理解Extract类型

概述 在TypeScript这一逐渐成为前端开发首选的静态类型检查语言中&#xff0c;类型系统提供了丰富的工具来帮助开发者编写更加健壮和可维护的代码。其中&#xff0c;Extract<T, U>是一个强大的内置实用类型&#xff0c;用于从一个联合类型T中提取出属于另一个类型U的那些…

AIGC 006-textual-inversion使用文本反转实现个性化文本到图像生成!

AIGC 006-textual-inversion使用文本反转实现个性化文本到图像生成&#xff01; 文章目录 0 论文工作1 论文方法2 效果 0 论文工作 这篇论文 (An Image is Worth One Word: Personalizing Text-to-Image Generation using Textual Inversion) 提出了一种新颖的技术&#xff0c…

Modal.method() 不显示头部的问题

ant-design中的Modal组件有两种用法&#xff1a; 第一种是用标签&#xff1a;<a-modal></a-modal> 第二种是用Api&#xff1a;Modal.info、Modal.warning、Modal.confirm...... 一开始项目中这两种用法是混用的&#xff0c;后面UI改造&#xff0c;需要统一样式&…

一个程序员的牢狱生涯(37)任务

星期一 任 务 我走回大镣面前后,把双手抱着的衣服递给大镣,但我并没有把手里的东西也递给他。现在的大镣坐着,我站着,这个时候要给大镣的话,肯定能被身边的棍子或六子看到,甚至被所有号子里的人都看到。因为此时,所有人的目光都盯着我手里的衣服,盯着我和大镣看。 “镣…

Shell字符串变量

目标 能够使用字符串的3种方式 掌握Shell字符串拼接 掌握shell字符串截取的常用格式 能够定义Shell索引数组和关联数组 能够使用内置命令alias,echo,read,exit,declare操作 掌握Shell的运算符操作 Shell字符串变量 介绍 字符串&#xff08;String&#xff09;就是一系…

使用LabVIEW时遇到VISA属性错误 -1073807331的解决方案

在LabVIEW或VeriStand中使用VISA属性时&#xff0c;可能会遇到错误 -1073807331。这一错误的具体描述如下&#xff1a; 解决方案 导致VISA属性出现此错误的原因主要有以下四种&#xff1a; 属性不被使用的串行总线支持 示例 A.1&#xff1a;Is Port Connected VISA属性仅支持由…

React(四)memo、useCallback、useMemo Hook

目录 (一)memo API 1.先想一个情景 2.用法 (1)props传入普通数据类型的情况 (2)props传入对象的情况 (3)props传入函数的情况 (4)使用自定义比较函数 3.什么时候使用memo&#xff1f; (二)useMemo Hook 1.用法 2.useMemo实现组件记忆化 3.useMemo实现函数记忆化 …

如何停止 iPad 和 iPhone 之间共享短信,独立接收和发送消息

概括 在当今高度互联的数字世界中&#xff0c;Apple 设备之间的无缝连接性提供了极大的便利&#xff0c;尤其是在消息同步方面。iPhone 和 iPad 用户通常可以享受到设备间短信的自动同步功能&#xff0c;这意味着无论是在哪个设备上&#xff0c;用户都可以接收和回复消息。然而…

2024.5.26.python.exercise

# # 导入包 # from pyecharts.charts import Bar, Timeline # from pyecharts.options import LabelOpts, TitleOpts # from pyecharts.globals import ThemeType # # # 从文件中读取信息 # GDP_file open("1960-2019全球GDP数据.csv", "r", encoding&quo…

A. Maximize?

time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given an integer x&#x1d465;. Your task is to find any integer y&#x1d466; (1≤y<x)(1≤&#x1d466;<&#x1d465;) su…

深入理解python列表与字典:数据结构的选择与性能差异

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、列表与字典&#xff1a;基础数据结构的对比 二、列表&#xff1a;逐个遍历的查找方式 …

Ceres求解优化问题

1. 简介 Ceres Solver是专门用于求解非线性最小二乘问题的C开源库,研究SLAM方向不过滤波和优化两个技术路线,因此常用Ceres库解决实际项目中的优化问题,当然还有g2o同样可用,但就说明文档而言,Ceres对新用户更友好,g2o提供不多的文档,更多是需要参考其它开源项目使用,所以笔者…

【JAVA】接口

前面我们说了说抽象类相关内容&#xff0c;这篇我们主要聊聊接口相关内容&#xff0c;这部分很重要&#xff0c;大家引起关注。 1. 接口 1.1 接口的概念 接口就是公共的行为规范标准&#xff0c;大家在实现时&#xff0c;只要符合规范标准&#xff0c;就可以通用。在Java中&am…

力扣 739. 每日温度 python AC

单调栈 class Solution:def dailyTemperatures(self, temperatures):size len(temperatures)ll []ans [0] * sizefor i in range(size - 1, -1, -1):while ll and temperatures[i] > temperatures[ll[-1]]:ll.pop()if ll:ans[i] ll[-1] - ill.append(i)return ans

C语言 数组——向函数传递数组

目录 把数组传给函数&#xff08;Passing Arrays to Functions&#xff09; 向函数传递一维数组 向函数传递二维数组 数组在学生成绩管理中的应用 例&#xff1a;计算每个学生的平均分 把数组传给函数&#xff08;Passing Arrays to Functions&#xff09; 向函数传递一维…

gnocchi学习小结

背景 总结gnocchi 4.4版本gnocchi-metricd工作流程 入口 gnocchi.cli.metricd metricd stop after processing metric默认为0&#xff0c;调servicemanager run MetricdServiceManager __init__ 服务逻辑封装到MetricdServiceManager初始化中 主要由MetricProcessor, Met…