在这篇文章中我们来一起看一下 class 文件的结构,来进一步加深我们对虚拟机的类加载机制和类机制的理解。本文参考了 《深入理解 Java 虚拟机》一书。 解析 .class 文件 我们都知道一个 Java 类(.java)文件在被 Java 编译器(javac) 编译过后,如果语法没有错误,则会生成一个对应的 .class 文件,这个 .class 文件是一个二进制文件,用一定的格式保存了我们书写的类的所有信息。 除了 ConstantValue 以外,Java 虚拟机还有很多其他类型的属性表,最常见的便是 Code 表,它的结构我们在分析类文件中的方法属性时会介绍,如果虚拟机在进行属性表解析时发现属性表名不是其可以识别 其实 验证过程是最复杂的,因为这个过程需要扫描整个在加载过程中得到得到的 .class 文件格式的二进制数据,也就是相当于将我们在上面模拟的解析 .class 文件的过程,并且判断相关的数据是否合法,比如文件的魔数是否为
类文件结构public class TestClass {private int m;public int inc() {return m + 1; }}1.魔数 每个Class文件的头四个字节被称为 这个索引指向了一个 Class 常量表项,它标识了这个方法所属的类或接口:name_and_type_index 3 指向常量池中的某个 NameAndType 项。 TestClass.java"4.访问标志 在常量池之后就是2个字节代表访问标志 access_flags。 又印证了java会给每一个类隐式定义一个构造方法。 而我的方法明明没有参数,为什么又有Arg_size=1呢? Java语言的潜规则:在任实例方法中,都可以通过this访问到方法所属的对象——哈哈哈哈,我猜大家平时在写代码的时候在方法内引用当前类的属性都不会显式的把this.给写出来,而是直接拿属性了。
Class文件是以8位字节为基础单位的二进制流,各部分中间没有分隔符。遇到8位字节以上的空间数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。 Class文件采用类似C语言的伪结构体来存储,这种伪结构体只有两种数据类型:无符号数和表。无符号数以u1,u2,u4,u8四种,数字代表字节数。 表用于描述有层次关系的复合结构数据,整个Class文件本质上就是一张表。 2.接口的访问信息 类索引、父类索引 和接口索引集合 存储类、父类、接口的 文件索引 字段表集合 1.字段作用域 2.是否static 3.可变性 4.并发可见性 5.可否被序列化 6.字段数据类型 7 因为Java不支持多重继承,所以父类索引只有一个,除了java.lang.Object外,所有Java类都有父类,因此除了java.lang.Object,所有java类的父类索引都不为0。
运行机制 开篇 源代码HelloWorld.java /** * Created by jack on 2017/3/16. : Bad version number in .class file 就是由于JDK1.6编译的文件版本号超过了JDK1.5虚拟机所接受的范围 Java class文件是二进制文件。 Class类文件结构 class文件的结构 简单讲,jvm的class文件是针对jvm的私家定制。只要运行在jvm上byte code,都需要按照class文件format来。否则jvm解析不了。 官网文档: The Java Virtual Machine class file format class文件时java虚拟机执行引擎的数据入口,也是java技术体系的基础支柱之一,了解class文件的结构对后面进一步了解虚拟机执行引擎有很重要的意义 class文件是一组以八位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在class文件中,中间没有添加任何分隔符,这使得整个class文件中存储的内容几乎全部都是程序运行的必要数据,没有空隙存在
-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> .*; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; /** * 使用 Java的mail包解析 标准的 .eml格式的邮件文件 * * @author * @date 2019/08/07 */ public class EmlUtil { // 定义发件人 HashMap<>(); parserFile(file.getAbsolutePath()); return result; } /** * 解析文件
java的运行过程 在运行一段java代码的时候需要经过编译,验证,加载和运行,具体如下图: ? 这个系列的文章是为了探讨Java字节码是什么样的结构,如何能够准确的表达我们代码的含义。 ---- JDK中如何解析class文件 在原生的JDK中有对java字节码的读取的工具类com.sun.tools,具体使用如下: File file=new File("/Users/fuwei/work class文件的基本结构 根据JVM的虚拟机规范(SE8)提供的资料,字节码对应的结构体如下: ClassFile { u4 magic; u2 在我们了解了class的结构之后,就可以开始试着解析class文件。 解析过程 读取类文件 private DataInputStream dataInputStream; public ClassReadCursor(String filePath) {
本文将为你介绍如果使用Java的Scanner类来读取或者解析CSV文件。 我的CSV文件(user.csv)内容如下 Rockey,22,India Bill,23,US Sonia,23,Germany 接下来我们首先从创建映射上述属性的实体User.java public ,本例中我们采用文件的方式。 CSVParsingExample.java import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class CSVParsingExample { public static void
Java虚拟机不和包括Java在内任何语言绑定,它只与Class文件这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息。 二.Class文件结构 根据Java虚拟机规范,类文件由单个ClassFile结构组成: ClassFile{ u4 magic; //Class 文件的标志 u2 [attributes_count];//属性表集合 } 根据Java虚拟机规范规定,Class文件格式采用一种类似C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号和表 无符号数属于基本的数据类型 当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建或运行时解析并翻译到具体的内存地址中。 ,所以父类索引只有一个,除了 java.lang.Object 之外,所有的 java 类都有父类,因此除了 java.lang.Object 外,所有 Java 类的父类索引都不为 0。
我们可以查看上述字节码的二进制文件用16进制查看: ? 字节码的二进制文件对应表示为: CA FE BA BE 00 00 00 34 那么前面的cafebabe就是魔数,而0000 和0034则分别是主版本号和次版本号。 、父类索引和接口索引集合 在class文件中,将用这三项来标识类的继承关系。 除了java.lang.Object类之外所有类都有父类,故除了java.lang.Object类之外,所有类该字段值都不为0) interfaces_count 2个字节 接口索引计数器,如果该类没有实现任何接口 这个类属性值表示的内容为: SourceFile: "HelloByteCode.java" 至此,我们完整解析了class类的字节码。
“ 我们都知道Java虚拟机不和包括Java在的任何语言绑定,它只与Class文件这种特定的二进制文件格式所关联。而Class文件是由java文件经过javac编译器编译后生成的。” ? 01 — Class类文件结构 在深入理解Java虚拟机一书中是先介绍概念然后具体分析,这里我就反过来描述,我们先看一下class文件,这里我打开一个本地被编译过的class文件,我们看到它是乱码的。 类和接口的全限定名 2. 字段的名称和描述符 3. 方法的名称和描述符 那常量池入口之后的十六进制表示什么呢? 当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析并翻译到具体的内存地址之中。 Java虚拟机规范规定,Class文件格式采用类似C语言结构体的伪结构来存储数据,这种结构只有两种数据类型:无符号数和表
而 class 文件便是一组以 8 位字节为基础单位流的二进制流,各个数据项目严格按照顺序紧凑地排列在 class 文件之中,中间没有添加任何分隔符,所以整个class 文件中存储的内容几乎都是程序运行的必要数据 3、无符号数和表 在介绍这些十六进制之前,我们先介绍 Class 文件的数据类型。 Class 文件采用一种类似于 C 语言结构体的伪结构来存储,这种伪结构只有两种数据类型:无符号数和表。 4、魔数 每个 class 文件的头 4 个字节称为魔数(Magic Number),它的唯一作用是:标识该文件是一个Java类文件。 如果没有识别到该标志,则说明该文件不是Java类文件或者文件已受损。 由上图,我们可以看到前 4 个字节是 cafe babe。 当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析并翻译到具体的内存地址之中。关于类的创建和动态连接的内容,下篇博客会详细介绍。
Java虚拟机不和特定的语言绑定,它只与 “Class文件” 这种特定的二进制文件格式所关联。Class文件中包含了 Java虚拟机指令集和符号表以及若干其他辅助信息。 Class 类文件的结构 ---- Class 文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class文件之中,中间没有任何分隔符,这使得整个 Class文件中存储的内容几乎全部是程序运行的必要数据 Java虚拟机规范中规定,Class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表,后面的解析都要以这两种数据类型为基础,所以这里先介绍这两个概念。 根据 Java 虚拟机规范,类文件由单个 ClassFile 结构组成: ClassFile { u4 magic; //Class 文件的标志 u2 包括下面三类常量: 【1】类和接口的全限定名; 【2】字段的名称和描述符; 【3】方法的名称和描述符; 常量池中每一项常量都是一个表,这14种表有一个共同的特点:开始的第一位是一个 u1 类型的标志位
本文,我们编写JAVA程序来解析class文件,读者注意,阅读本文前先详细了解Class文件结构,可参考笔者前一篇文章:Class文件结构(1)—手动解析每一个字节,你看不懂 代码地址:https "); } } } 3.解析版本号 class文件结构的版本号分为主版本号和副版本号,它们共同构成class文件格式的版本号[1]。 在实现常量池解析器之前,我们需要先根据《Java虚拟机规范》中描述的每个常量结构创建对应的Java类型。 在创建完各常量结构对应的Java类,和实现各常量结构的解析方法后,我们再来完成整个常量池的解析工作。 了解Class文件结构是学习Java虚拟机字节码指令的前提条件。 下一篇我们正式学习字节码指令!
通过 Dockerfile 开发人员可以快速创建自定义镜像,这篇文章就为大家来介绍一下 Dockerfile的文件结构 Dockerfile 内容包含四部分: 基础镜像信息 维护者信息 镜像操作指令 容器启动时执行的指令 下面我们通过一个 Dockerfile 文件来具体讲解一下: # 这个 Dockerfile 是基于 ubuntu:xeniel 镜像来创建容器 FROM ubuntu:xeniel nginx RUN echo "\ndaemi off;">>/etc/nginx/nginx.conf CMD /usr/sbin/nginx 第一行通过注释的方式描述了这个 Dockerfile 文件是基于
二、整个MP3 文件结构: MP3 文件大体分为三部分:TAG_V2(ID3V2),音频数据,TAG_V1(ID3V1) a). 而且ID3V2 结构比ID3V1 的结构要复杂得多,但比前者全面且可以伸缩和扩展。 下面就介绍一下ID3V2.3: 每个ID3V2.3 的标签都一个标签头和若干个标签帧或一个扩展标签头组成。 数据结构如下: char Header[3]; /*必须为”ID3″否则认为标签不存在*/ char Ver; /*版本号ID3V2.3 就记录3*/ char Revision; /*副版本号此版本记录为 所以格式如下 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 计算大小时要将0 去掉,得到一个28 位的二进制数,就是标签大小(不懂为什么要这样做),计算公式如下: int ,从前面可知本帧为V1,L3类型, ->128K 第21到22位:采样率,其值为00,从前面知本帧为 MPEG 1-> 44.1K 第23位:帧长调节,其值为0 ->无需调整 第24位:未使用 第
File类基础解析3 文件过滤器优化 什么是文件过滤器? java.io.FileFilter 是一个接口,是File的过滤器。 该接口的对象可以传递给File类的 listFiles(FileFilter) 作为参数, 接口中只有一个方法 boolean accept(File pathname) :测试pathname是否应该包含在当前 accept 方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回 false。保留规则: 1. 要么是.java文件。 2. 通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接打印 package File; import java.io.File; import java.io.FileFilter; public class Main { public static void main(String[] args) { //要遍历的文件夹的根目录
ArrayList 类本身就是表示一种线性结构的类,那么继承于 AbstractList 类也是理所当然。 Vector 这个类其实和 ArrayList 类相当像,也是利用数组储存元素,同时也可以动态的管理元素,我们可以看看它的类继承结构图: ? Stack 最后来看看 Stack 类,这个类继承了 Vector 类,提供了数据结构中 栈 的实现。我们来看看它的类继承图: ? 好了,到这里我们就把 List 接口下的一些具体类解析完了。 Stack :继承于 Vector 类,提供了数据结构中 栈 的相关操作方法,线程安全。
如果你也和我一样,不了解类结构和类加载,但是工作中又涉及到字节码相关内容,相信后面两篇文章会对你有所帮助。 我们所编写的每一行代码,要在机器上运行最终都需要编译成二进制的机器码 CPU 才能识别。 它们和 Java 语言一样都会被编译器编译成字节码文件,然后由虚拟机来执行。所以说类文件(字节码文件)具有语言无关性。 二. Class 文件结构 Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据严格按照顺序紧凑的排列在 Class 文件中,中间无任何分隔符,这使得整个 Class 文件中存储的内容几乎全部都是程序运行的必要数据 Java 虚拟机规范规定 Class 文件格式采用一种类似与 C 语言结构体的微结构体来存储数据,这种伪结构体中只有两种数据类型:无符号数和表。 建议想要深入了解的同学可以自己动手将 Java 类编译成二进制字节码文件,根据文章里介绍的类文件结构逐个字符去对照和实验,有助于加深理解。
如果你也和我一样,不了解类结构和类加载,但是工作中又涉及到字节码相关内容,相信后面两篇文章会对你有所帮助。 我们所编写的每一行代码,要在机器上运行最终都需要编译成二进制的机器码 CPU 才能识别。 Class 文件结构 Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据严格按照顺序紧凑的排列在 Class 文件中,中间无任何分隔符,这使得整个 Class 文件中存储的内容几乎全部都是程序运行的必要数据 Java 虚拟机规范规定 Class 文件格式采用一种类似与 C 语言结构体的微结构体来存储数据,这种伪结构体中只有两种数据类型:无符号数和表。 建议想要深入了解的同学可以自己动手将 Java 类编译成二进制字节码文件,根据文章里介绍的类文件结构逐个字符去对照和实验,有助于加深理解。 关于「类文件结构」我们就介绍到这里,下一篇我们来聊聊「虚拟机的类加载机制」。 参考资料: 《深入理解 Java 虚拟机:JVM 高级特性与最佳实践(第 2 版)》 ----
Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class文件”这种特定的二进制文件格式所关联,Class文件中包含了Java虚拟机指令集和符号表以及若干其他辅助信息。 任一门功能性语言都可以表示为一个能被Java虚拟机所接受的有效的Class文件,所以虚拟机并不关系Class的来源是何种语言2.Class类文件的结构任何一个Class文件都对应着唯一一个类或接口的定义信息 Class文件说一组以8位字节为基础单位的二进制流,各个数据项目严格的按照顺序紧凑地排列在Class文件中,中间没有任何分隔符,所以Class文件中存储的内容几乎都是程序运行的必要数据,没有空隙存在当遇到需要占用 8位字节以上空间的数据项时,则会按照高位在前的放松分割成若干个8位字节进行存储Class文件格式采用一种类似于V语言结构体的伪结构体存储数据,伪结构中只有两周数据类型:无符号数、表无符号数属于基本数据类型 当虚拟机运行时,,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。