我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何解析Java虚拟机的Class文件

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何解析Java虚拟机的Class文件

这篇文章给大家介绍如何解析Java虚拟机的Class文件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

前面发了几篇学习笔记,但是看这些东西总是感觉很"玄乎",来一篇实战的东西来揭一下"JVM"的面纱,让"SSH"时代的童鞋们来熟悉一下Java的"老祖爷"JVM。由于自己的水平有限,所以大家在看过程中发了什么问题,或者您有什么疑问请及时提出来,我及时解决。如果您有什么建议,那么更好大家一块讨论。

1、源码文件

public class LearningClassFile {      //普通变量      private int id1;      //静态变量      private static int id2;      //常量      private final int id3 = 4;      //静态常量      private static final int id4 = 5;                 public LearningClassFile() {      }             public LearningClassFile(int id1, int id2) {          this.id1 = id1;          this.id2 = id2;      }             //使用public修饰的addPub方法      public void addPub(int a, int b) {          int result = a + b;          System.out.println(result);      }             //使用private修饰的addPri方法      private void addPri(int a, int b) {          int result = a + b;          System.out.println(result);      }             //使用static修饰的方法      public static void addSta() {          int result = id2 + id4;          System.out.println(result);      }             public static final void addFinal(int a, int b) {          int result = a + b;          System.out.println(result);      }             public static void main(String[] args) {          LearningClassFile lcf = new LearningClassFile(1, 2);          lcf.addPub(1, 2);          lcf.addPri(1, 2);          addSta();          addFinal(1, 2);      }  }

Class文件:

Compiled from "LearningClassFile.java" public class LearningClassFile extends java.lang.Object    SourceFile: "LearningClassFile.java"   minor version: 0   major version: 50 //运行时常量池:用于存放编译期生成的各种字面量和符号引用。    Constant pool:  //从父类Object继承的默认构造方法  //观察该方法的特征:无参,返回类型void  const #1 = Method       #13.#35;        //  java/lang/Object."<init>":()V  //常量id3  //"#7.#36; //  LearningClassFile.id3:I"  //#7:查找常量池中的类名LearningClassFile  //#36-->"const #36 = NameAndType #17:#15;//  id3:I"  //NameAndType字面的意思是名称和类型。即id3是变量的名称,I表示id3是int类型  //综合描述:LearningClassFile中的id3是int类型  const #2 = Field        #7.#36; //  LearningClassFile.id3:I  const #3 = Field        #7.#37; //  LearningClassFile.id1:I  const #4 = Field        #7.#38; //  LearningClassFile.id2:I  //将System的out存储至常量池  //System类中out被public static final修饰的  //"public final static PrintStream out = nullPrintStream();"  //综合描述:System类的out属性是PrintStream类型  const #5 = Field        #39.#40;        //  java/lang/System.out:Ljava/io/PrintS  tream;  //将PrintStream的Println()方法存储至常量池  //该方法的参数为I,返回值为void  const #6 = Method       #41.#42;        //  java/io/PrintStream.println:(I)V  //类LearningClassFIle  const #7 = class        #43;    //  LearningClassFile  //构造函数  //该构造函数需传入两个int类型的变量  const #8 = Method       #7.#44; //  LearningClassFile."<init>":(II)V  //LearningClassFile的addPub方法  //#4-->"const #45 = NameAndType #27:#26;//  addPub:(II)V"  //#27-->"const #27 = Asciz       addPub;"    方法的名称为:addPub  //#26-->"const #26 = Asciz       (II)V;"     方法的类型:两个int类型的参数,返回类型为void  const #9 = Method       #7.#45; //  LearningClassFile.addPub:(II)V  const #10 = Method      #7.#46; //  LearningClassFile.addPri:(II)V  const #11 = Method      #7.#47; //  LearningClassFile.addSta:()V  const #12 = Method      #7.#48; //  LearningClassFile.addFinal:(II)V  const #13 = class       #49;    //  java/lang/Object  const #14 = Asciz       id1;  const #15 = Asciz       I;  const #16 = Asciz       id2;  const #17 = Asciz       id3;  //ConstantValue属性表示一个常量字段的值  //即final修饰的属性  const #18 = Asciz       ConstantValue;  //对于final修饰的常量直接将类型和值存入常量池  const #19 = int 4;  const #20 = Asciz       id4;  const #21 = int 5;  const #22 = Asciz       <init>;  const #23 = Asciz       ()V;  //Code属性只为***一个方法、实例类初始化方法或类初始化方法保存Java虚拟机指令及相关辅助信息  //简而言之:保存方法编译后的指令信息  const #24 = Asciz       Code;  //java源码行号与编译后的字节码指令的对应表  const #25 = Asciz       LineNumberTable;  const #26 = Asciz       (II)V;  const #27 = Asciz       addPub;  const #28 = Asciz       addPri;  const #29 = Asciz       addSta;  const #30 = Asciz       addFinal;  const #31 = Asciz       main;  const #32 = Asciz       ([Ljava/lang/String;)V;  //java 源码文件  const #33 = Asciz       SourceFile;  const #34 = Asciz       LearningClassFile.java;  const #35 = NameAndType #22:#23;//  "<init>":()V  const #36 = NameAndType #17:#15;//  id3:I  const #37 = NameAndType #14:#15;//  id1:I  const #38 = NameAndType #16:#15;//  id2:I  const #39 = class       #50;    //  java/lang/System  const #40 = NameAndType #51:#52;//  out:Ljava/io/PrintStream;  const #41 = class       #53;    //  java/io/PrintStream  const #42 = NameAndType #54:#55;//  println:(I)V  const #43 = Asciz       LearningClassFile;  const #44 = NameAndType #22:#26;//  "<init>":(II)V  const #45 = NameAndType #27:#26;//  addPub:(II)V  const #46 = NameAndType #28:#26;//  addPri:(II)V  const #47 = NameAndType #29:#23;//  addSta:()V  const #48 = NameAndType #30:#26;//  addFinal:(II)V  const #49 = Asciz       java/lang/Object;  const #50 = Asciz       java/lang/System;  const #51 = Asciz       out;  const #52 = Asciz       Ljava/io/PrintStream;;  const #53 = Asciz       java/io/PrintStream;  const #54 = Asciz       println;  const #55 = Asciz       (I)V;     {  //默认构造方法  public LearningClassFile();    Code:     Stack=2, Locals=1, Args_size=1    0:   aload_0         1:   invokespecial   #1; //Method java/lang/Object."<init>":()V     //将id3的引用推送至栈顶     4:   aload_0     //将4推送至栈顶     5:   iconst_4     //将4赋值给id3     6:   putfield        #2; //Field id3:I     9:   return   LineNumberTable:     line 11: 0   //public LearningClassFile() {                  //对于final类型的实例变量在每个构造方法中都会进行一次初始化。     line 7: 4    //    private final int id3 = 4;      line 12: 9   //}        public LearningClassFile(int, int);    Code:     Stack=2, Locals=3, Args_size=3    0:   aload_0     1:   invokespecial   #1; //Method java/lang/Object."<init>":()V     4:   aload_0     5:   iconst_4     6:   putfield        #2; //Field id3:I     9:   aload_0     10:  iload_1     11:  putfield        #3; //Field id1:I     14:  aload_0     15:  pop     16:  iload_2     17:  putstatic       #4; //Field id2:I     20:  return   LineNumberTable:     line 14: 0    //public LearningClassFile(int id1, int id2) {                   //对于final类型的实例变量在每个构造方法中都会进行一次初始化。     line 7: 4     //    private final int id3 = 4;        line 15: 9    //    this.id1 = id1;     line 16: 14   //    this.id2 = id2;     line 17: 20   //}        public void addPub(int, int);    Code:     Stack=2, Locals=4, Args_size=3    0:   iload_1     1:   iload_2     2:   iadd     3:   istore_3     4:   getstatic       #5; //Field java/lang/System.out:Ljava/io/PrintStream;     7:   iload_3     8:   invokevirtual   #6; //Method java/io/PrintStream.println:(I)V     11:  return   LineNumberTable:     line 21: 0    //    int result = a + b;      line 22: 4    //    System.out.println(result);     line 23: 11   // }        public static void addSta();    Code:     Stack=2, Locals=1, Args_size=0    //获取静态变量id2推送至栈顶     0:   getstatic       #4; //Field id2:I     //直接从常量池中取出id4的值5推送至栈顶     3:   iconst_5     //执行相加操作     4:   iadd     //将计算结果推送至栈顶     5:   istore_0     //获取静态与out     6:   getstatic       #5; //Field java/lang/System.out:Ljava/io/PrintStream;     //取出计算结果     9:   iload_0     //调用println方法     10:  invokevirtual   #6; //Method java/io/PrintStream.println:(I)V     //方法正常结束     13:  return   LineNumberTable:     line 33: 0    //     int result = id2 + id4;     line 34: 6    //     System.out.println(result);     line 35: 13   //}        public static final void addFinal(int, int);    Code:     Stack=2, Locals=3, Args_size=2    0:   iload_0     1:   iload_1     2:   iadd     3:   istore_2     4:   getstatic       #5; //Field java/lang/System.out:Ljava/io/PrintStream;     7:   iload_2     8:   invokevirtual   #6; //Method java/io/PrintStream.println:(I)V     11:  return   LineNumberTable:     line 38: 0    line 39: 4    line 40: 11       public static void main(java.lang.String[]);    Code:     Stack=4, Locals=2, Args_size=1    //创建一个LearningClassFile对象,并将对象的引用推送至栈顶     0:   new     #7; //class LearningClassFile     //将对象的引用进行备份推送至栈顶     //使用原有的引用值调用实例方法,现在置于栈顶的引用值的位置将被接下来的操作覆盖。     3:   dup     //将构造函数中的参数1推送至栈顶     4:   iconst_1     5:   iconst_2     //执行构造方法     6:   invokespecial   #8; //Method "<init>":(II)V     //将栈顶引用型数值存入第二个本地变量     9:   astore_1     10:  aload_1     11:  iconst_1     12:  iconst_2     //调用实例方法     13:  invokevirtual   #9; //Method addPub:(II)V     16:  aload_1     17:  iconst_1     18:  iconst_2     19:  invokespecial   #10; //Method addPri:(II)V     //调用静态方法     22:  invokestatic    #11; //Method addSta:()V     25:  iconst_1     26:  iconst_2     27:  invokestatic    #12; //Method addFinal:(II)V     30:  return   LineNumberTable:     line 43: 0     //   LearningClassFile lcf = new LearningClassFile(1, 2);     line 44: 10    //   lcf.addPub(1, 2);     line 45: 16    //   lcf.addPri(1, 2);     line 46: 22    //   addSta();     line 47: 25    //   addFinal(1, 2);     line 48: 30    //}  }

final变量和static final变量的区别:

(1)实例常量和类常量的区别

(2)初识方式不同:从class字节码来看final修饰的变量会出现在每个构造方法中进行一次初始化;static final类型的变量必须在定义的时候进行初始化。 理解"编译期可知,运行期不变": 编译器可确定调用方法的版本,符合这个标准的方法主要有两种:私有方法,静态方法。

详情请看:深入理解JVM读书笔记--字节码执行引擎。

2、final变量和static final变量的区别:

(1)实例常量和类常量的区别

(2)初始化方式不同:从class字节码来看final修饰的变量会出现在每个构造方法中进行一次初始化;static final类型的变量必须在定义的时候进行初始化。

3、理解"编译期可知,运行期不变":

编译器可确定调用方法的版本,符合这个标准的方法主要有两种:私有方法,静态方法。

关于如何解析Java虚拟机的Class文件就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何解析Java虚拟机的Class文件

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何解析Java虚拟机的Class文件

这篇文章给大家介绍如何解析Java虚拟机的Class文件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前面发了几篇学习笔记,但是看这些东西总是感觉很"玄乎",来一篇实战的东西来揭一下"JVM"的面纱,让"SSH"时代的
2023-06-17

Java虚拟机,类文件结构深度解析

Java类文件结构Java虚拟机不和包括Java在内的任何语言绑定,只与 "Class文件" 这种特定的二进制文件所关联, Class文件中包含了Java虚拟机指令集合符号表以及若干其它辅助信息。 Java虚拟机作为一个通用的、机器无关的执
2023-06-02

如何理解Java 虚拟机中HotSpot 虚拟机对象

今天就跟大家聊聊有关如何理解Java 虚拟机中HotSpot 虚拟机对象,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、对象的创建对象的创建步骤:1. 类加载检查虚拟机遇到一条 n
2023-06-05

Java虚拟机装载和初始化一个class类代码解析

在 java 应用程序开发中,只有被 java 虚拟机装载的 Class 类型才能在程序中使用。只要生成的字节码符合 java 虚拟机的指令集和文件格式,就可以在 JVM 上运行,这为 java 的跨平台性提供条件。下面,我们来看看虚拟机是
2023-05-31

如何理解JAVA虚拟主机

今天就跟大家聊聊有关如何理解JAVA虚拟主机,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。其实虚拟主机也可以称之为网站空间,就是把一台运行在互联网上的物理服务器,划分为多个虚拟服务器
2023-06-07

虚拟主机文件删不了如何解决

如果您无法删除虚拟主机中的文件,请尝试以下解决方法:1. 确认权限:检查您是否具有足够的权限来删除该文件。您可能需要登录到虚拟主机的管理面板或使用FTP客户端来管理文件。2. 修改文件权限:在FTP客户端或通过SSH登录到虚拟主机,尝试修改
2023-08-23

如何迁移虚拟主机文件

迁移虚拟主机文件可以通过以下步骤进行:1. 备份文件:首先,在源服务器上备份所有虚拟主机的文件。可以使用压缩工具,如tar或zip,将所有文件打包为一个压缩文件,或者使用rsync命令将文件复制到另一个位置。2. 导出数据库:如果虚拟主机使
2023-08-16

如何向centos虚拟机传文件

有几种方法可以向CentOS虚拟机传输文件:1、使用SSH传输:可以使用SCP(Secure Copy)或SFTP(Secure File Transfer Protocol)通过SSH连接向CentOS虚拟机传输文件。在本地计算机上打开
如何向centos虚拟机传文件
2024-05-21

如何查看虚拟机的日志文件

要查看虚拟机的日志文件,可以按照以下步骤操作:打开虚拟机管理软件,比如VirtualBox、VMware等。在虚拟机管理软件中选择要查看日志的虚拟机。在虚拟机的菜单或设置中找到日志选项。点击日志选项,可以查看虚拟机的各种日志信息,比如
如何查看虚拟机的日志文件
2024-06-11

虚拟主机如何传文件进去

虚拟主机是一个共享的服务器空间,可以通过多种方式将文件传输到虚拟主机中。以下是几种常见的方法:1. FTP(文件传输协议):使用FTP客户端软件,通过FTP协议将文件上传到虚拟主机。你需要提供虚拟主机的FTP服务器地址、用户名和密码。2.
2023-08-30

如何给虚拟主机转移文件

要将文件转移到虚拟主机上,你可以采取以下步骤:1. 通过FTP(文件传输协议)连接到虚拟主机。你可以使用FTP客户端软件(如FileZilla)或命令行工具(如ftp命令)来进行连接。2. 使用你的虚拟主机提供的FTP登录凭据登录到虚拟主机
2023-08-25

虚拟主机里文件打不开如何解决

虚拟主机中的文件无法打开可能有多种原因。以下是一些可能的解决方法:1. 检查文件权限:确保文件的权限设置正确。文件权限应该允许服务器处理程序读取和执行文件。一般来说,对于网页文件,权限应设置为644,对于可执行脚本文件,权限应设置为755。
2023-09-12

如何上传文件到虚拟主机

要上传文件到虚拟主机,您可以按照以下步骤操作:1. 获取虚拟主机的FTP登录信息。通常,您需要知道FTP服务器的主机名、用户名和密码。这些信息通常由您的虚拟主机提供商提供。2. 下载一个FTP客户端软件,例如FileZilla、WinSCP
2023-08-23

虚拟主机泛解析如何绑定

虚拟主机泛解析是一种 DNS 设置,允许将多个子域名指向同一个 IP 地址。这通常用于创建多个虚拟主机,而无需为每个主机配置单独的 DNS 记录。要绑定虚拟主机泛解析,您需要按照以下步骤进行操作:1. 登录您的域名注册商或 DNS 提供商的
2023-08-31

本机文件如何发送到虚拟主机

要将本机文件发送到虚拟主机,您可以使用以下几种方法:1. FTP(文件传输协议):使用FTP客户端连接到虚拟主机,并将文件通过FTP上传到虚拟主机的指定目录中。2. SSH(Secure Shell):使用SSH客户端连接到虚拟主机,在命令
2023-08-26

云虚拟主机删除不了文件如何解决

如果无法删除云虚拟主机上的文件,可以尝试以下解决方法:1. 确认权限:确保你拥有足够的权限来删除文件。如果你是管理员或超级用户,可以尝试使用管理员权限删除文件。2. 检查文件锁定:如果文件正在被其他程序或进程使用,可能无法删除。可以尝试关闭
2023-09-08

如何上传虚拟主机web文件夹

上传虚拟主机的web文件夹可以通过以下步骤进行:1. 获取虚拟主机的FTP(文件传输协议)登录信息,包括FTP服务器地址、用户名和密码。这些信息通常由虚拟主机提供商提供。2. 下载并安装一个FTP客户端软件,如FileZilla、WS_FT
2023-08-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录