字节码(.class)文件解读
字节码文件是什么
我们在命令后使用 java
命令,就能将java源文件(.java)编译成对应的字节码文件(.class)。字节码文件是一种八位字节的二进制流文件,各个数据项按照一定顺序从前到后紧密排列。因此,这样的安排会使得字节码文件非常紧凑,可以被jvm快速的加载到内存中,并且占用较少的内存空间。
java源文件在被编译器编译之后,每个类(或者接口)都单独占据一个字节码文件。类中所有信息都在字节码文件中有所描述,由于字节码文件非常灵活,它对类的描述能力甚至强于java源文件。
字节码文件中的信息是一项一项排列的,每一项都有各自固定的长度:有的占一个字节,有的占两个字节,有的占四个或八个字节。数据项不同的长度分别用u1, u2, u4, u8表示,对应数据项在字节码文件中占据1,2,4,8个字节。
字节码文件的结构
一个字节码文件由十部分构成:MagicNumber,Version,Constant_pool,Access_flag,This_class,Super_class,Interfaces,Fields,Methods和Attributes。可以用下面的表来展示他们的排列顺序和每一部分数据项的大小:
下面分别对每一项进行展开:
(1)magic:存在于字节码文件的开头四个字节,存放着字节码文件的魔数,他是一个固定值 0xCAFEBABE(英文就是java那个咖啡的图标)。如果是十六进制的CAFEBABE,那么这个文件符合字节码文件的标准;如果不是,则不能被jvm所识别。
(2)minor_version和major_version:紧跟着魔数的就是次版本号和主版本号。例如版本1.8.0,那么主版本号就是1.8,而此版本号对应是0。版本号与某一个整数之间有映射关系,因此只要将major_version的十六进制数转化为十进制,再查表找到映射关系,就可以知道java编译器的版本号。
(3)constant_pool:版本号后面为常量池,常量池是字节码文件中一个非常重要的部分。常量池存放了文字字符串,常量值,当前类的类名,字段名,方法名,各个字段和方法的描述符,对当前类的字段和方法的引用信息,当前类中对其他类的引用信息等等。几乎包含了类中所有信息的描述。
首先常量池开头两个字节描述了常量池中数据项的数目。常量池中的数据也是一项一项紧密排列的,各个数据项通过索引来访问。每一个数据项都有自己的数据类型,由开头的一个字节(标志值tag)决定,映射关系如下表所示:
每一种不同的数据类型,都对应不同的结构,例如CONSTANT_Methodref:
CONSTANT_Methodref_info {u1 tag; //u1表示占一个字节u2 class_index; //u2表示占两个字节u2 name_and_type_index; //u2表示占两个字节}
再比如CONSTANT_Utf8结构:
CONSTANT_Utf8_info {u1 tag;u2 length;u1 bytes[length];}
总而言之,每一个不同的数据类型都对应不同的组织结构。
(4)access_flag:保存了当前类的访问权限,包括了public,private,protected等等。
(5)this_class:保存了当前类的全局限定名在常量池中的索引。
(6)super_class:保存了当前类的父类全局限定名在常量池中的索引。
(7)interfaces:保存了当前类实现的接口列表,包括两个部分:interfaces_count和interfaces[interfaces_count]。前者表示当前类实现的接口数量,两个字节表示(因此理论上一个类最多实现65535个接口);后者表示包含interfaces_count个接口的全局限定名索引的数组。
(8)fields:保存了当前类中的成员列表,也是分为两部分:fields_count和fields[fields_count]。前者表示一个类中的成员个数,后者表示字段详细信息的列表,如下所示:
field_info {u2 access_flags;u2 name_index;u2 descriptor_index;u2 attributes_count;attribute_info attributes[attributes_count];}
详细信息包括了访问权限,成员名在常量池中的索引,类型描述符在常量池的索引,一些其他的属性(比如volatile之类的,但count如果是0,这个字段也就不存在了)。
(9)methods:保存了当前类的方法列表,包含两部分的内容:methods_count和methods[methods_count]。前者是该类或者接口显示定义的方法的数量,后者包含方法信息的一个详细列表,每一个方法信息如下:
method_info {u2 access_flags;u2 name_index;u2 descriptor_index;u2 attributes_count;attribute_info attributes[attributes_count];}
这里的attribute比较复杂,涉及到操作数栈、局部变量表等等信息,不展开了。感兴趣的话可以看下结尾引用的那篇文章。
(10)attributes:包含了当前类的attributes列表,包含attributes_count和 attributes[attributes_count]。属性不仅仅可以出现在这个字段,如果出现在这个地方,则是对整个字节码文件所对应的类或者接口的描述;如果出现在fields或者methods中,则是对该字段或者该方法的额外信息的描述。
每一个attribute的结构如下:
SourceFile_attribute {u2 attribute_name_index;u4 attribute_length;u2 sourcefile_index;}
最常见的一个属性就是attribute_name_index指向常量池中的SourceFile,而sourcefile_index指向常量池中的xxx.java(也就是这个字节码文件的源文件)。
总结
字节码文件中的十部分结构简单的分析如上所述,包含了让jvm识别的magic;java的版本号;常量池(各种成员名,方法名,类名,源文件名,方法描述符等等),这些常量信息被后面的field,method等等所引用;访问权限;类名和父类全限定名;实现的接口信息;类中成员和方法;类的额外属性。
如果想了解更具体的,可以参考一下深入理解JVM之Java字节码(.class)文件详解
最后放一个java代码,和编译后字节码文件的一部分信息(用javap反编译相当于对字节码文件进行解密):
源代码:
public class Hello{private int test;public int test(){return test;}}
字节码文件:
javap反编译得到每一部分的值:
参考
- https://blog.csdn.net/weelyy/article/details/78969412
- 《深入理解java虚拟机》
字节码(.class)文件解读相关推荐
- 使用三种方式创建Class字节码类文件对象
/*** 使用三种方式创建Class字节码类文件对象** @author silence*/ public class Demo1 {public static void main(String[] ...
- 进程创建java源代码_Java程序执行流程:1.创建Java源程序2.编译源程序3.运行class(字节码)文件...
参考答案如下 2. 要准确理解复盘,程序1创程序程序哪几个关键词是不可缺少的? 执行字节影响电流对人体伤害程度的主要因素是()? 流程Sydney was established in: IE.建J件 ...
- 从一个class文件深入理解Java字节码结构
前言 我们都知道,Java程序最终是转换成class文件执行在虚拟机上的,那么class文件是个怎样的结构,虚拟机又是如何处理去执行class文件里面的内容呢,这篇文章带你深入理解Java字节码中的结 ...
- 这一次,彻底弄懂 Java 字节码文件!
作者 | 东升的思考 责编 | Elle 不啰嗦,直接从最最简单的一段Java源代码开启Java整体字节码分析之旅. Java 源码文件 package com.dskj.jvm.bytecode; ...
- java 字节码分析_Java 字节码实践 - 解读
最近刚看完 深入理解 Java 虚拟机 一书中的第 6 章 (类文件结构),便迫不及待地自己写一个小的 Demo,来自己分析一把 Java 源文件经过编译之后成为字节码文件到底是个什么东西?先由一个简 ...
- Java反编译字节码文件
如何查看 Java 的字节码文件? 在 Java 中,字节码文件.class实际上是二进制文件,并不能直接查看.要想查看,我们只能通过反编译对其进行解析,然后查看解析后的源码. 如何反编译字节码文件 ...
- python字节码大全
ddis --- Python 字节码反汇编器 Source code: Lib/dis.py dis 模块通过反汇编支持CPython的 bytecode 分析.该模块作为输入的 CPython 字 ...
- idea如何反编译字节码指令_美团点评:Java字节码增强技术,线上问题诊断利器...
作者简介:泽恩,美团到店住宿业务研发团队工程师.文章转载于公众号:美团技术团队 1. 字节码 1.1 什么是字节码? Java之所以可以"一次编译,到处运行",一是因为JVM针对各 ...
- Java 指令与字节码
Java 指令与字节码 查看class文件 编写简单java代码 编译代码 查看class文件 Java字节码总的结构表 常量池 常量池容量计数器 字面量和符号引用 全限定名 简单名称 描述符 常量类 ...
- Python字节码介绍
了解 Python 字节码是什么,Python 如何使用它来执行你的代码,以及知道它是如何帮到你的. 如果你曾经编写过 Python,或者只是使用过 Python,你或许经常会看到 Python 源代 ...
最新文章
- Redis、Kafka 和 Pulsar 消息队列对比,写得太好了!
- keil复制代码乱码_win7系统下Keil复制中文注释到记事本出现乱码的解决方法
- html和css入门 (三)
- python 开发gui浏览器_Python编程之gui程序实现简单文件浏览器代码
- 查看SQL SERVER数据库的连接数
- stm32f103电子钟心得体会_浅谈STM32_RTC闹钟
- 如何将nodejs项目程序部署到阿里云服务器上
- java对象--多态的好处
- 有关Silverlight浮动窗体组件的研究——Silverlight学习笔记(3)
- XMLHttpReq.onreadystatechange 传递参数
- 网上图书订阅系统的WBS图,和WBS字典
- Substance Painter 创建头发实验
- iOS 通过商品短链接跳转京东商品详情页
- minio 分片上传
- 贝尔曼福特_福特自行车之旅
- C - Wrap very long lines of input into two or more shorter lines
- 菜鸟站长之家带你了解什么是百度SEO快排技术
- n维椭球体积公式_2020中考物理知识汇总:公式大全
- 拟真机器人拯救者奖励_《X战警:黑队》万磁王大战哨兵机器人,他就是变种人的拯救者!...
- (一)操作系统的基本概念