[Class文件结构]1——概述

前言

众所周知,计算机只识别0和1,程序员写的c或c++程序最终都要经过编译、链接等步骤,将代码转换成0或1的二进制格式才能被计算机执行。由于依赖平台,导致c语音中基础数据类型在各平台上所占的字节数都不相同,其它细节也有不同。

Java不一样,Java在诞生之初就宣称“write once,run anywhere”,它选择了与操作系统和机器指令集无关的、平台中立的格式作为程序编译后的存储格式。

实现语言无关性的基础就是虚拟机和字节码存储格式,使用Java编译器可以把Java代码编译为存储字节码的Class文件,使用JRuby等的编译器一样可以把代码文件编译成Class文件,虚拟机并不关心Class文件的来源,只要它符合Class文件就有的结构就可以在Java虚拟机中运行。

Class类文件的结构

解析学习Class类文件的结构,是了解虚拟机的重要基础之一,有助于学习虚拟机如何加载并执行class文件。

Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件之中,中间没有添加任何分隔符。

Class文件采用一种类似C语言结构体的伪结构来存储,这种伪结构中只有两种数据类型:无符号数和表。

无符号数基于基本的数据类型,以u1,u2,u4,u8来分别代表1个字节、2个字节、4个字节、8个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或按照UTF-8编码构成的字符串值。

无论是无符号数还是表,当需要描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时候称这一系列连续的某一类型的数据为某一类型的集合。

注意:Class文件不像xml,它没有分隔符,而且它的顺序都是严格定义的。

Java代码中包含成员变量,方法,变量还定义了访问权限,方法还有参数、返回值,方法中的逻辑(比如说int型数据相加)是否会被存储成一个个指令,Class文件会如何描述这些东西呢?

示例代码

以如下代码为示例,查看编译后的Class文件。

package org.fenixsoft.clazz;

public class TestClass {

    private int m;

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

Class文件是字节码文件,需要使用16进制编辑器查看,本文中选用 WinHex,打开Class文件后整体如下:

另外Class文件可以使用javap工具查看,指令如下:javap -verbose class文件路径

魔数与Class文件版本

每个Class文件的头4个字节称为魔数,它的唯一作用是用于确定这个文件是否为Class文件。查看上单节的Class文件格式图,魔数正好也是由一个u4类型表示。

Class文件的魔数为 cafebabe(咖啡宝贝?)。

魔数之后即是次版本号和主版本号,二者均由一个u2表示。

本例中次版本号为0,主版本号为51(33是16进制数,换成10进制就是51),即为Java 1.7。注意高版本的JDK能向下兼容,但无法运行以后版本的Class文件,那么本例中的Class文件只能被JDK 1.7及以上运行。

常量池

主版本号后边就是常量池了,常量池中的所有项目类型为:

使用javap -verbose 查看Class文件,查看常量池部分

常量池中存放两大类常量:字面量和符号引用。字面量,如字符串、被声明为final的常量值等。而符号引用(符号引用属于编译原理方面的概念)包括了下面三类常量:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

和Java代码中的常量不一致,常量池中并不是只会存储final类型的数据,不是常量也会被存储,比如示例代码中的m,另外符号引用也并不是代码中所说的引用类型,除了类和接口,它还包含字段和方法。

虚拟机在加载Class文件时进行动态连接,也就是说Class文件并不会保存各个方法和字段的最终内存布局信息,当虚拟机运行时,需要从常量池中获取对应的符号引用,在运行时解析并翻译到具体的内存地址当中。

常量池是最繁琐的数据了,因为常量池中所包含的11种类型都有自己的结构。一般是由一位u1指定类型,再加上数据长度(一般是u2),再加上数据具体值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 字节码查看工具:WinHex 前言 Java虚拟机实现语言无关性的基石就是Class文件Java虚拟机提供的语言无...
    zlcook阅读 7,152评论 4 18
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,740评论 18 399
  • ---剽悍新江湖100天成长目标 四期五连三排52号郭艳 行动营22天的经历让我开拓了视野,明白了什么是真正的学习...
    燕灵湾阅读 411评论 1 1
  • 初春,凉意依旧直袭人心。弯月寒光微微,草坪上似乎有潮意慢慢升腾,我打开随身带来的老白干,任由六十七度的烈酒热辣辣地...
    骑鲸_阅读 2,861评论 31 39
  • 此时此刻,我已经心情平复了许多,而就在刚才,我还连饭都吃不下!我的感受是压抑愤怒,和强大的委屈。到马上进入到幼儿园...
    崔峰媳妇孙小莹阅读 225评论 2 1