java 字节码文件详解

每一个class字节码文件都唯一对应一个类或接口,class文件中记录中类或接口的基本信息,但反之不成立,不是每一个类或接口都有一个唯一对应的字节码文件,首先类或接口的字节码可以不以文件的方式存储,可以直接从内存中生成字节码,而不产生.class文件,动态代理的原理就是直接内存中生成字节码流,根据加载字节码流进行类加载操作,类实例化,生成代理对象。

字节码文件记录的信息:魔术,class文件主次版本,常量池数量及常量池表,类或接口的访问标志,类索引,超类索引,接口数量及接口表,字段数量及字段表,方法数量及方法表,属性属性及属性表

魔术:四个字节,用于定义此字节码文件是否符合虚拟机规范,保证字节码文件不会威胁虚拟机的安全,若为cafebabe则表示字节码符合虚拟机规范

主次版本号:四个字节,前两字节表示次版本号,后两字节表示主版本号,用于定义编译的字节码文件格式版本,第版本虚拟机拒绝运行高版本字节码文件,但高版本虚拟机会向下兼容低版本字节码文件

常量池数量及常量池表:这部分主要统计类或接口的字面量和符号引用,用于每个类或接口拥有的字面量和符号引用属性不一定相同,所有需要两个字节的长度来表示常量池数目,常量池数目计数从1开始,比如类或接口中总共有两个字面量符号引用,则常量池数目为2,注意,不是从0开始计数,0可能另有用处,可以用来表示类或接口中未出现的引用,用来表示超级父类java.long.Object全限定名的索引,常量池表是一个数组,一共有18种类型,每一种类型有一个tag属性与之对应,constant_utf8_info用于表示文本字符串,类和接口全限定名,字段名称及描述符,方法名称及描述符等常量信息,constant_integer_info用于存储int类型的常量信息,只存储int类型的值,不存储其他符合引用信息,比如 final int a=1 符号引用信息为a,值为1,constant_float_info用于存储float类型常量信息,也是只存储float值,不存储引用信息,constant_long_info用于存储long类型的常量信息,constant_double_info用于存储double类型的常量信息,constant_class_info用于存储指向常量池列表constant_unf8_info类和接口全限定名的有效引用,constant_string_info用于存储指定常量池列表constant_utf8_info某常量项的有效索引,指向文本字符串,constant_fieldref_info用于存储指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的有效索引,constant_methodref_info用于存储指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的有效索引,constant_interfacemethodref_info用于存储指向常量池列表constant_class_info常量项和constant_nameandtype_info常量项的有效索引,constant_nameandtype_info用于存储指向常量池列表constant_utf8_info常量项的有效索引,可以通过所有找到对应类及描述符,constant_methodtype_info用于存储指向常量池constant_utf8_info常量项,表示方法类型,找到对应的方法描述符,constant_methodhandle_info用于表示方法句柄,属性reference_kind表示方法句柄的类型,1-4表示为字段创建的方法句柄,5-8表示为类方法(构造、实例、静态)创建的句柄,9表示为接口方法创建的句柄,reference_index属性指向根据reference_kind对应的常量池列表,constant_invokedynamic_info用于存储当前字节码文件中引导方法bootstrap_method数组的有效索引和指向常量池constant_nameandtype_info常量项的有效索引

访问标志:两个字节,用于定义字节码文件所表示的类或接口的访问权限,如判断是类还是接口,类是否被abstract修饰,类是否被final修饰,  acc_interface表示是接口,acc_annotation表示是注解类型,acc_enum表示是枚举类型,acc_public 表示类或接口是public访问权限,acc_final表示类不允许被继承,acc_abstract表示类为抽象类,acc_super表示类调用实例方法时需进行特殊操作

类索引及父类索引:四个字节,用于存储指向常量池constant_class_info对应的有效索引,而constant_class_info存储常量池列表的constant_utf8_info常量项索引,根据此索引可找到类和父类的全限定名

接口数量及接口表:接口属性用于存储当前类或接口的直接超类接口数量,接口表是一个数组,记住,只有常量池表从1开始计数,其余都是从数组下表0开始计数,接口表数组的每一个数组元素存储此类或接口的直接超类接口的有效索引,根据此索引找到constant_class_info对应的常量项,根据constant_class_info可找到对应直接超类接口的全限定名

字段数量及字段表:字段数量用于存储类或接口的字段数目,包括类字段和实例字段,字段表为一个数组,每一个数组元素都相当于一个field_info结构的对象,field_info结构包含字段完整信息:字段标识符,字段访问修饰符,字段是类字段还是实例字段,字段是否为常量等,注意:此处字段表示当前类或接口的字段,不包括从超类或接口继承的字段,java语法规范不允许同一个类或接口中出现同一字段名的不同字段,但是class文件中却可以允许出现相同字段名的不同字段,只有字段的描述符不同即可,field_info结构属性:access_flags用于存储字段的访问标志,acc_private,acc_protected,acc_public,acc_final,acc_static,acc_volatile等,注意:acc_final与acc_volatile不能同时出现在同一字段,name_index指向常量池constant_utf8_info常量项的有效索引,获取当前字段的简单名称,descriptor_index指向常量池constant_utf8_info常量项的有效索引,获取当前字段的描述符,attribute_count,attributes[attributes_count]这两项表示字段的属性信息,用于描述字段相关信息,attribute数组每一个元素都是一个attribute_info结构的元素

方法数量及方法表:方法数量用于存储当前类或接口的方法数目,包括实例方法,类方法,抽象方法,方法表是一个数组,每一个数组元素都是一个method_info结构,method_info结构包含方法的完整信息:方法描述符,访问修饰符,是否为final方法,是否为abstract方法等,注意:此处的方法数组只是表示当前类或接口的所有方法,并不包括从超类及父接口继承来的方法,java语法规范java类或接口中不允许出现方法签名完全一样的方法同时出现,会编译报错,而字节码层面却允许方法签名完全相同的方法同时出现,只需要保证方法的返回值类型不同,method_info结构属性与field_info一致,但acc_flags类型不尽相同,注意acc_abstract不能与acc_final,acc_static,acc_private,acc_synchronized,acc_native同时使用,接口方法中只能使用acc_public,acc_abstract,此处我有一个疑问,接口中default方法有没有对应的访问标志,注意:<init>方法只能使用acc_private,acc_protected,acc_public访问标志

属性数量及属性表:属性数量表示当前字节码文件中attribute_info表数目,属性表是一个数组,每一个数组元素都是attribute_info结构,attribute_info结构表示属性的完整信息:第一项指向常量池constant_utf8_info某常量项的有效索引,根据此索引可找到属性对应名称,属性可以出现在classFile,字段表,方法表中,用以描述相关信息,attribute_info结构完整信息:attribute_name_index指向常量池constant_utf8_info常量项的有效索引,获取属性名称,attribute_length用于指明info数组长度,info[attribute_length]用于存储属性的数据信息,必须实现的数据信息:Code,ConstantValue,Exceptions,  code属性用于描述method_info的具体相关信息,attribute_name_index指向常量池constant_utf8_info常量项的有效索引,获取属性名称,即code,attribute_length表示attribute表示attribute_info长度,不包括attribute_name_index和attribute_length的初始6字节,max_stack描述当前方法最大栈深度,max_locals描述当前方法的局部变量表,code_length表示code数组长度,code[]表示当前方法编译后的字节码,  ContantVaue位于field_info结构中,用于通知虚拟机对类变量进行初始化,即字段需要被acc_static修饰,当前类常量不需要ContantValue通知虚拟机执行初始化,早就执行好了,实例字段此时不需要初始化,

原文地址:https://www.cnblogs.com/zzlove2018/p/9097885.html

时间: 2024-11-09 04:00:56

java 字节码文件详解的相关文章

JAVA字节码文件之第二篇(常量池)

一.常量池的内容 一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库,比如java类中定义的方法与变量信息.常量池中主要存储两类常量:字面量(文本字符串,final的常量)与符号引用(类和接口的全限定名,字段的名称和描述符,方法的名称和描述符 一.常量池的结构 二.常量池的分析 常量池(也称常量表):主版本号之后就是常量池的开始位置:java类所对应的常量池主要由常量池数量和常量池数组两部分组成,常量池数量是主版本号之后的两个字节:常量池数组在常

【java】查看Java字节码文件内容的方法+使用javap找不到类 解决方法

研究synchronized底层实现,涉及到查看java字节码的需要 前提是,你的PC已经成功安装了JDK并别配置了环境变量. ==========查看方法========= 一.javap查看简约字节码方式 1.准备一个java文件 例如,文件所在目录在此处 Student.java文件内容如下: package com.sxd.sweeping.test.synchron; public class Student implements Runnable{ static int age; p

java中三种方式获得类的字节码文件对象

package get_class_method; public class ReflectDemo { /** * @param args */ public static void main(String[] args) { getClassObject1(); getClassObject2(); getClassObject3(); } public static void getClassObject1(){ Person p = new Person(); System.out.pr

java 第3节 详解第一个Java程序

2016-06-28 1 编写源程序 2 编译源文件 首先进入源文件所在的目录 cd 文件目录 javac HelloWorld.java 3 运行程序 java HelloWorld 4 详解第一个程序 5 字节码的解释与执行 C++ 编译后得到的是可执行文件 编译型语言 Java 编译后得到的是.class字节码文件 解释型语言 字节码:是一套在Java运行系统(JVM)中执行的高度优化的指令集. [参考资料] [1] Java轻松入门经典教程[完整版]

Java中反射机制详解

序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射,所以回过头来把这个给重新补一下,自己欠下的债,迟早是要还的. ---WH 一.什么是反射? 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的

Java虚拟机工作原理详解

原文地址:http://blog.csdn.net/bingduanlbd/article/details/8363734 一.类加载器 首先来看一下java程序的执行过程. 从这个框图很容易大体上了解java程序工作原理.首先,你写好java代码,保存到硬盘当中.然后你在命令行中输入 [java] view plaincopy javac YourClassName.java 此时,你的java代码就被编译成字节码(.class).如果你是在Eclipse IDE或者其他开发工具中,你保存代码

Java并发关键字Volatile 详解

Java并发关键字Volatile 详解 问题引出: 1.Volatile是什么? 2.Volatile有哪些特性? 3.Volatile每个特性的底层实现原理是什么? 相关内容补充: 缓存一致性协议:MESI ? 由于计算机储存设备(硬盘等)的读写速度和CPU的计算速度有着几个数量级别的差距,为了不让CPU停下来等待读写,在CPU和存储设备之间加了高速缓存,每个CPU都有自己的高速缓存,而且他们共享同一个主内存区域,当他们都要同步到主内存时,如果每个CPU缓存里的数据都不一样,这时应该以哪个数

Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

作者:亦山 推荐:hh375的图书馆 class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象: class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的.具体class文件是怎样组织类信息的,可以参考 此博文:深入理解Java Class文件格式系列.或者

Java 动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出二进制数据,加载到内存中,解析.class 文件内的信息,生成对应的 Class对象: class字节码文件是根据JVM虚拟机规范中规定的字节码组织规则生成的.具体class文件是怎样组织类信息的,可以参考 此博文:深入理解Java Class文件格式系列.或者是Java虚拟机规范. 下面通过一段代