文档章节

Class文件解读(一)

打破突破
 打破突破
发布于 2017/04/09 21:40
字数 1288
阅读 97
收藏 0

        java虚拟机规范中的java虚拟机的跨语言性及跨平台性,多半归功于定义中的Class文件,Class文件解耦了虚拟机平台的具体实现与具体的编程语言,也业务开发角度理解,可以将它抽象成接口对接文档(当然只是为了方便理解),既然是已经拟定的文档,那么必然存在一定的规则,在了解具体Class文件规范之前需要对Class文件有一个整体的认识。

        首先Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当需要需要占用8位字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8位字节进行存储。

        根据java虚拟机规范的规定,Class文件格式采用类似于c语言中结构体的伪结构(仅仅是数据组合的一种既定方式)来存储数据,在该伪结构中只有两种数据类型:无符号数和表。

        无符号数属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节、和8个字节的无符号数,常用于表述数字(比如常量池的count、方法表count、属性表count等)、索引引用、数值量或按照UTF-8编码构成的字符串值。

        表在结构上是由无符号数和其他表构成的用语表述具有层次关系的复合结构,整个class文件也可以看成是一张特殊的表。

在介绍具体的Class文件结构之前,需要提醒的是class文件中对于字节码的顺序、长度都有严格的定义,具体的虚拟机实现必须遵循这样的规范(不然一次编译到处运行只能是梦想),当然Class文件规范中也允许虚拟机实现在遵循java标准虚拟机规范的前提下自由定义其他属性以提高虚拟机在某方面的性能。

Class文件结构:

            

       无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式(这应该比较好理解,很多协议中都用了类似的思想,在数据报文头中先告诉接受端报文内容的整体信息,根据这些信息去解析报文数据,如netty中的编码器和解码器、http协议等),这时称这一系列连续的某一类型的数据为某一类型的集合。

详解Class文件结构:

为方便进一步理解,将使用下面的例子进行讲解:

package org.lucas.clazz;

/**
 * Created by BG260733 on 2017-04-09.
 */
public class TestClass {

    private int n;

    private static final int m = 5;

    public int inc() {
        return m + n;
    }

}

说明:以下class文件均由winHex十六进制打开。

magic:

       每个class文件的头4个字节称为魔数(Magic Number),它的唯一作用时确定这个文件是否为一个能被虚拟机接受的class文件(不代表能成功解析)。很多文件存储标准中都是在文件内容中嵌入魔术来进行身份识别,之所以不使用文件名(包括后缀)来作为文件的识别方式,主要是出于安全方面的考虑,文件名可能会被外部频繁改动。Class文件的魔术值为:OxCAFEBABY,是不是自带浪漫气息。

minor_version

        仅接着魔数后面的第5个和第6个两个字节,表示能够解析执行该class文件的虚拟机次版本号。

major_version

        第7个和第8个两个字节,表示能够解析执行该class文件的虚拟机主版本号。

            

下表列出了从JDK1.1到JDK1.7,主流JDK版本编译器输出的默认和可支持的Class文件版本号。

           

        -target标志表示允许编译器生成特定版本的Java类文件格式。

        -source标志表示允许编译器将新的语言构造(如Lambda表达式、try-with-resources以及switch中使用字符串等等)看做错误。一些新语言特性(比如Lambda表达式)需要使用特定的字节码功能(比如invokedynamic),因此,-source指定的版本比-target指定的版本还新往往是不可能的。

 

博主本打算将Class文件所有内容由一篇文章讲述清楚、但实际编写过程中发现待表述的信息量还是太大,为了方便读者阅读,特将此篇分为五到六篇文章,未完待续~

 

下篇:https://my.oschina.net/u/3345762/blog/880152

 

© 著作权归作者所有

共有 人打赏支持
打破突破

打破突破

粉丝 24
博文 26
码字总数 28638
作品 0
杭州
高级程序员
私信 提问
从动态代理,看Class文件结构定义

前言 这篇内容是上一篇动态代理是如何"坑掉了"我4500块钱的补充,进一步分析篇。 建议二者结合食用,醇香绵软,入口即化。 好了,不扯淡了,开始... 正文 2、Class 文件的格式 这里为啥是2开...

MDove
08/13
0
0
SAS创建宏变量的七种方法

学会创建宏变量,特别是全局宏变量是应用宏的一个基础,下面我们介绍一下,创建宏变量的七种方法,并通过例子来演示。 1.通过宏函数创建宏变量。 %let dsid=%sysfunc(open(sashelp.class));...

开拓者-2017
2016/03/01
161
0
第三章 spring-bean之AbstractBeanFactory(5)

前言 AbstractBeanFactor实现了ConfigurableBeanFactory接口。一棵树有不仅有主干,树干,还有花花叶叶。其他接口与实现是BeanFactory的主干与树干的话,那ConfigurableBeanFactory负责管理B...

鸟菜啊
08/04
0
0
android应用程序的混淆打包

1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示: target=android-8 proguard.config=proguard.cfg Eclipse会通过此配置在工程目录生成proguard.cfg文件......

AlexZhuang
2012/04/11
0
0
Runtime之消息发送和消息转发

简介: 如果消息含有参数,则为: 1、消息发送机制 检查selector 是否需要忽略 检查target是否为nil,如果为nil,直接cleanup,然后return(这就是为什么可以向nil发送消息的原因) 然后在t...

Tonyliu_
04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mariadb二进制包安装,Apache安装

安装mariadb 下载二进制包并解压 [root@test-a src]# wget https://downloads.mariadb.com/MariaDB/mariadb-10.2.6/bintar-linux-glibc_214-x86_64/mariadb-10.2.6-linux-glibc_214-x86_64.t......

野雪球
今天
3
0
ConcurrentHashMap 高并发性的实现机制

ConcurrentHashMap 的结构分析 为了更好的理解 ConcurrentHashMap 高并发的具体实现,让我们先探索它的结构模型。 ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。HashEnt...

TonyStarkSir
今天
3
0
大数据教程(7.4)HDFS的java客户端API(流处理方式)

博主上一篇博客分享了namenode和datanode的工作原理,本章节将继前面的HDFS的java客户端简单API后深度讲述HDFS流处理API。 场景:博主前面的文章介绍过HDFS上存的大文件会成不同的块存储在不...

em_aaron
昨天
3
0
聊聊storm的window trigger

序 本文主要研究一下storm的window trigger WindowTridentProcessor.prepare storm-core-1.2.2-sources.jar!/org/apache/storm/trident/windowing/WindowTridentProcessor.java public v......

go4it
昨天
7
0
CentOS 生产环境配置

初始配置 对于一般配置来说,不需要安装 epel-release 仓库,本文主要在于希望跟随 RHEL 的配置流程,紧跟红帽公司对于服务器的配置说明。 # yum update 安装 centos-release-scl # yum ins...

clin003
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部