类文件解析及引申的一系列仇怨
目录
一:java的Class文件
(1)类文件结构(Class File Structure)
(2)jdk编译版本 与 字节码的指令对照
(3)从类结构角度解释为什么可以跨平台
二:编译器 与 解释器的纷争
(1)编译器
(2)解释器
(3)编译器与解释器的区别
三:JVM 中常用术语汇总
1:语言
2:字节,字符,比特
3:二进制文件
4:文件读取工具
一:java的Class文件
(1)类文件结构(Class File Structure)
ClassFile {u4 magic;u2 minor_version;u2 major_version;u2 constant_pool_count;cp_info contant_pool[constant_pool_count – 1];u2 access_flags;u2 this_class;u2 super_class;u2 interfaces_count;u2 interfaces[interfaces_count];u2 fields_count;field_info fields[fields_count];u2 methods_count;method_info methods[methods_count];u2 attributes_count;attribute_info attributes[attributes_count];
}
magic,minor_version,major_version | 指定关于类版本以及编译的 JDK 版本的信息 |
constant_pool | 与符号表类似,但是它包含更多信息 |
access_flags | 提供类修饰符列表 |
this_class | 索引到 constant_pool 提供了完整的类名,例如,org/jamesdbloom/foo/Bar |
super_class | 索引到 constant_pool 提供标识符引用到父类,例如,java/lang/Object |
interfaces | 索引列表到 constant_pool 提供标识符引用到所有实现的接口 |
fields | 索引列表到 constant_pool 为每个字段提供完整的描述 |
methods | 索引列表到 constant_pool 为每个方法签名提供完整的描述,如果方法不是抽象的或 native 的,也会呈现字节码 |
attributes | 不同值列表,提供类的额外信息,包括注解 RetentionPolicy.CLASS 或 RetentionPolicy.RUNTIME |
可以通过 javap 命令查看被编译的 Java 类的字节码。
如果编译以下这个简单的类:
package org.jvminternals;public class SimpleClass {public void sayHello() {System.out.println("Hello");}}
那么执行
javap -v -p -s -sysinfo -constants classes/org/jvminternals/SimpleClass.class
会得到字节码
public class org.jvminternals.SimpleClassSourceFile: "SimpleClass.java"minor version: 0major version: 51flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref #6.#17 // java/lang/Object."<init>":()V#2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;#3 = String #20 // "Hello"#4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V#5 = Class #23 // org/jvminternals/SimpleClass#6 = Class #24 // java/lang/Object#7 = Utf8 <init>#8 = Utf8 ()V#9 = Utf8 Code#10 = Utf8 LineNumberTable#11 = Utf8 LocalVariableTable#12 = Utf8 this#13 = Utf8 Lorg/jvminternals/SimpleClass;#14 = Utf8 sayHello#15 = Utf8 SourceFile#16 = Utf8 SimpleClass.java#17 = NameAndType #7:#8 // "<init>":()V#18 = Class #25 // java/lang/System#19 = NameAndType #26:#27 // out:Ljava/io/PrintStream;#20 = Utf8 Hello#21 = Class #28 // java/io/PrintStream#22 = NameAndType #29:#30 // println:(Ljava/lang/String;)V#23 = Utf8 org/jvminternals/SimpleClass#24 = Utf8 java/lang/Object#25 = Utf8 java/lang/System#26 = Utf8 out#27 = Utf8 Ljava/io/PrintStream;#28 = Utf8 java/io/PrintStream#29 = Utf8 println#30 = Utf8 (Ljava/lang/String;)V
{public org.jvminternals.SimpleClass();Signature: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1 // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 3: 0LocalVariableTable:Start Length Slot Name Signature0 5 0 this Lorg/jvminternals/SimpleClass;public void sayHello();Signature: ()Vflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc #3 // String "Hello"5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: returnLineNumberTable:line 6: 0line 7: 8LocalVariableTable:Start Length Slot Name Signature0 9 0 this Lorg/jvminternals/SimpleClass;
}
这个类文件展示了三个主要部分,常量池、构造器和 sayHello 方法。
- 常量池 - 提供了字符表相同的信息
- 方法 - 每个方法包括四个方面
- 签名 和 访问标志位(access flags)
- 字节码
- 行号表(LineNumberTable)- 为 debugger 工具提供信息,为字节码指令保存行号,例如,第 6 行在 sayHello 方法中的字节码是 0 ,第 7 行对应的字节码是 8 。
- 本地变量表 - 列出了帧内所有的本地变量,在两个示例中,只有一个本地变量就是 this 。
以下的字节码操作数会在类文件中被用到。
aload_0 | 这个操作码是一组以 aload_<n> 为格式的操作码中的一个。它们都会装载一个对象的引用到操作数栈里。<n> 指的是本地变量列表的访问位置,只能通过 0、1、2 或 3 来访问。也有其他类似的操作码用来装载值,但不是用作对象引用的 iload_<n>,lload_<n>,float_<n> 和 dload_<n> 这里 i 是对应 int,l 对应 long,f 对应 float,d 对应 double。本地变量的索引位置大于 3 的可以分别通过 iload、lload、float、dload 以及 aload 来装载。这些所有的操作码都以单个操作数来指定要装载的本地变量的索引位置。 |
ldc | 这个操作码用来将常量从运行时常量池压入到操作数栈中。 |
getstatic | 这个操作码用来将静态值从运行时常量池内的一个静态字段列表中压入到操作数栈内。 |
invokespecial,invokevirtual | 这两个操作码是一组用来调用方法操作码其中的两个,它们是 invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual。在这个类文件中,invokespecial 和 invokevirtual 同时被用到,不同之处在于 invokevirtual 调用对象类上的一个方法,而 invokespecial 指令用来调用实例初始化的方法、私有方法或者当前类父类中的方法。 |
return |
这个操作码是一组操作码中的一个,它们是:ireturn,lreturn,freturn,dreturn,areturn 和 return。每个操作码都是与类型相关的返回语句。i 对应 int,l 对应 long,f 对应 float,d 对应 double 然后 a 是对象引用。不带首字母的 return 返回 void。 |
(2)jdk编译版本 与 字节码的指令对照
major minor Java platform version
45 (0x2D) 3 1.0
45 (0x2D) 3 1.1
46 (0x2E) 0 1.2
47 (0x2F) 0 1.3
48 (0x30) 0 1.4
49 (0x31) 0 1.5
50 (0x32) 0 1.6
51 (0x33) 0 1.7
(3)从类结构角度解释为什么可以跨平台
java字节码有着自己的代码识别规范,其中不包含对特定硬件的调用或者识别
那些指令被包含在JVM虚拟机中实现
结果:所以Java代码可以跨平台的使用,不用考虑兼容性问题!
二:编译器 与 解释器的纷争
(1)编译器
编译器就是将“一种语言(通常为高级语言)”翻译为“另一种语言(通常为低级语言)”的程序。
编译器的主要工作流程:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)
作用:优化中间代码(Intermediat
e representation)以及生成机器代码(Code Generation
例如:java,scala 等
(2)解释器
又译为直译器,是一种电脑程序,能够把高级编程语言一行一行直接转译运行。解释器不会一次把整个程序转译出来,只像一位“中间人”
例如:javaScript,python 等
(3)编译器与解释器的区别
三:JVM 中常用术语汇总
1:语言
(1)(机器码)机器语言(machine language):是一种指令集的体系。这种指令集,称机器码,是电脑的CPU可直接解读的数据
(2)汇编语言:汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言
(3)字节码
定义:字节码(Byte-code)是一种包含执行程序,由一序列 op 代码/数据对组成的二进制文件,是一种中间码
地位:源码(高级语言)《———字节码———》机器码
例子:
1 public void add(java.lang.String);
2 Code:
3 0: aload_0
4 1: getfield #15; //Field admin:Lcom/nhn/user/UserAdmin;
5 4: aload_1
6 5: invokevirtual #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;
7 8: pop
8 9: return
Java 字节码指令集包括操作码和操作数。如 invokevirtual 这种操作码需要 2 字节的操作数
aload_0 、 getfield 和 invokevirtual 用 1 个字节的字节数来表示(aload_0 = 0x2a、getfield = 0xb4、invokevirtual = 0xb6)。
因此,Java 字节码指令的操作码的最大值是 256
2:字节,字符,比特
(1)字节(Byte):
一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间.
英文标点2占一个字节,中文标点占两个字节.
1字节(Byte) = 8位(bit)
(2)比特(Bit):
亦称二进制位。新港台:位元
比特指二进制中的一位,是二进制最小信息单位。
1比特就是1位
(3)字符,字节,比特 的关系:
字符 》= 字节 》 比特
8bit(位)=1Byte(字节)
3:二进制文件
(1)定义:
广义的二进制文件即指文件,由文件在外部设备的存放形式为二进制而得名。
狭义的二进制文件即除文本文件以外的文件。
(2)列举一个二进制文件如下:
00000000h:0F 01 00 00 0F 03 00 00 12 53 21 45 58 62 35 34; .........S!EXb54
00000010h:41 42 43 44 45 46 47 48 49 47 4B 4C 4D 4E 4F 50; ABCDEFGHIGKLMNOP
(3)特点:二进制文件只是储存数据,并不写明数据类型
如何使用:必须知道数据储存方式,第几个字节到第几个字节是什么类型的数据,储存的数据是什么含义
(4)引申:不同语言的核心区别:(从文件读取的角度)
把语言类型 和 编码格式区分开来
语言类型的区分:
严格来说,它们最后被机器读取为“0”,“1”的一串二进制数据
重要的是它们在转变过程中,依据语言特定的 “数据存储规则”,来形成特定的含义
(5)传统语言与Java对比之编译后的文件差异:
1>C或者C++ 编译后的文,本地可直接执行(它直接依据与不同的系统,例如.exe 后缀文件)
1>>C或者C++等传统语言
使用这些传统语言写的程序通常首先被编译,然后被连接成单独的、专门支持特定硬件平台和操作系统的二进制文件
2>>因为这个二进制文件包含了对目标处理器(操作系统)的机器语言
2>java的字节码必须依赖于虚拟机JVM运行
1>>Java编译器把Java源文件的指令翻译成字节码,这种字节码就是Java虚拟机的“机器语言”,与特定的操作系统无关
4:文件读取工具
(1)class为十六进制:
————UltraEdit 编辑
(2)查看 class 字节码:
1>jdk自带:javap -c
2>Java Bytecode Editor:解析程序(层次更清晰)
直接运行jbe.sh即可看到UI面板
tip:
Windows7中如何直接运行sh命令
但是:Windows7中可以直接用bat命令
类文件解析及引申的一系列仇怨相关推荐
- 类文件解析003-解析常量池
本文我们来介绍ClassFileParser 解析常量池的过程.解析常量池的过程是在ClassFileParser::parseClassFile 通过parse_constant_pool 来实现的 ...
- 解析HTML文件 - 运用SgmlReader类来解析HTML文件
运用.NET Framework类来解析HTML文件.读取数据并不是最容易的.虽然你可以用.NET Framework中的许多类(如StreamReader)来逐行解析文件,但XmlReader提供的 ...
- java怎编写么解析一个类型_DAY3:你必须知道的java虚拟机之类篇——类文件的结构...
马上过年啦,不知道大家今年有没有投资基金股票呢?是赚的盆满钵满还是拍断大腿,可以评论区一起交流交流,秀一秀哈哈,反正我是没来得及上车. 暴富西不可能暴富的啦,打工人嘛几能写写文章啦-记得点赞➕关注呀 ...
- dom4j工具类_基于DOM4J的XML文件解析类
XML文件解析分四类方式:DOM解析:SAX解析:JDOM解析:DOM4J解析.其中前两种属于基础方法,是官方提供的平台无关的解析方式:后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于ja ...
- 最全的基于c++的serialport.cpp与serialport.h类文件(解析版)
最全的基于c++的serialport.cpp与serialport.h类文件(解析版) 备注 参考原文件为:serialport.cpp与serialport.h类文件源代码 作者:c344935 ...
- java解析mdb文件_Access MDB文件解析查询,Access数据库解析工具类MdbUtils
Access MDB文件解析查询,Access数据库解析工具类MdbUtils ================================ ©Copyright 蕃薯耀 2018年9月18日 h ...
- 一个CUE文件解析类
网络上的APE文件通常附带一个CUE文件,该文件包含了此CD碟片的作者,曲目等信息,要能支持对APE文件的选曲以及必要信息的显示,必须实现CUE文件的解析.这是实现初步功能的CUE文件解析类,还有待完 ...
- Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析
转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...
- Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)
本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 上篇文章<<Android中measure过程.WRAP_CONTENT详解以及xml布局文 ...
- jmap 文件解析_干货分享丨jvm系列:dump文件深度分析
摘要:java内存dump是jvm运行时内存的一份快照,利用它可以分析是否存在内存浪费,可以检查内存管理是否合理,当发生OOM的时候,可以找出问题的原因.那么dump文件的内容是什么样的呢? JVM ...
最新文章
- java中mymaps_Java MyLocationStyle.myLocationType方法代码示例
- SpringSecurity认证流程回顾
- 【转载】oracle闪回技术详解之闪回drop(神奇的flashback)
- springboot几种注入_Spring Boot中使用JdbcTemplate访问数据库
- yii2笔记: 单元测试
- 必填校验加变色,点击颜色消失
- Qt模态界面设置setWindowModality禁止其他界面响应
- 「区块链+人工智能」:来自谷歌、IBM、百度的真实案例
- 数字图像处理(三)——频域滤波
- 零基础带你学习MySQL—日期函数(十五)
- 兴致勃勃的意思是什么,怎么用兴致勃勃造句?
- 程序员,如何从平庸走向理想?答:干困难事!
- oracle如何创建基表,创建本地基表的物化视图
- 使用iText对pdf中查找关键字坐标进行填充
- 如何解决农村产权交易难的问题
- Google的GDrive美如水中之月
- DDoS攻击新玩法 暴雪上演营销新方式
- 讲讲多拨的额外骚操作(多拨附加教程)
- 阿哲学了就来聊——Java反射
- MyEclipse 2020下载