class变化java没变化,Java9之class文件格式变动

Java9之class文件格式变动

Java9已经于2017年09月27日发布。Java9引入了很多新特性,其中最重要的特性,或者说最大的变化,无疑就是模块化了。为了支持模块化,Java从方方面面都进行了改进,包括class文件格式。已经有很多文章介绍Java9模块化,因此本文并不打算成为另一篇模块化入门文章。本文主要介绍Java9相较Java8在class文件格式方面的变动。

测试代码

本文将基于模块mymod进行讨论,目录结构如下所示:

j9cf

└── src

└── mymod

├── a

│ └── b

│ ├── MyImpl.java

│ ├── MyService.java

│ └── c

│ └── HelloWorld.java

└── module-info.java

其中a.b包里定义了MyService和MyImpl两个类,代码如下所示:

package a.b;

public class MyService {}

package a.b;

public class MyImpl extends MyService {}

a.b.c包里定义了HelloWorld主类,代码如下所示:

package a.b.c;

public class HelloWorld {

public static void main(String[] args) {

System.out.println("Hello, World!");

}

}

module-info.java文件则对mymod模块进行定义,代码如下所示:

module mymod {

requires java.base;

requires static java.sql;

requires transitive java.xml;

exports a.b.c;

exports a.b to java.sql, java.xml;

opens a.b to java.sql, java.xml;

uses a.b.MyService;

provides a.b.MyService with a.b.MyImpl;

}

使用下面的命令对模块进行编译:

cd j9cf

path/to/java9/bin/javac \

-d mods --module-source-path src \

src/mymod/module-info.java \

src/mymod/a/b/c/HelloWorld.java

使用下面的命令将模块打包成jar格式:

cd j9cf

path/to/bin/jar --create \

--file mymod-1.0.jar \ --main-class a.b.c.HelloWorld \ --module-version 1.0 \ -C mods/mymod .

上面两个命令执行完之后,j9cf目录结构如下所示:

j9cf

├── mymod-1.0.jar

├── mods

│ └── mymod

│ ├── a

│ │ └── b

│ │ ├── MyImpl.class

│ │ ├── MyService.class

│ │ └── c

│ │ └── HelloWorld.class

│ └── module-info.class

└── src

└── mymod

├── a

│ └── b

│ ├── MyImpl.java

│ ├── MyService.java

│ └── c

│ └── HelloWorld.java

└── module-info.java

class文件查看工具

Java自带了命令行工具javap,可以反编译并分析class文件格式。不过为了更直观的观察class文件,本文使用图形化工具classpy。

class文件格式变动

class文件格式主要在四个方面有变动:版本号、类存取标志、常量池、类属性,下面分别进行介绍。

版本号

class文件大版本号由Java8的52(0x34)增加到了53(0x35),如下图所示:

1b4f27f458a375b71a9c414852959fff.png

类存取标志

类的存取标志(access_flags)新增加了ACC_MODULE(0x8000)标志位,表示class文件描述的是一个模块,如下所示:

86c156450d6259bb4128487d1dfb8c0f.png

常量池

常量池增加了CONSTANT_Module_info和CONSTANT_Package_info两种常量。

CONSTANT_Module_info

CONSTANT_Module_info的tag值是19,表示一个模块,其结构如下所示:

CONSTANT_Module_info { u1 tag; u2 name_index; }

比如mymod模块module-info.class文件常量池的第15个常量就是一个CONSTANT_Module_info常量,表示mymod模块自己,如下图所示:

36de778b5cf25f323bb64ad200914ab8.png

CONSTANT_Package_info

CONSTANT_Package_info的tag值是20,表示模块输出(Export)或者打开(Open)的包,其结构和CONSTANT_Module_info一样,如下所示:

CONSTANT_Package_info { u1 tag; u2 name_index; }

比如mymod模块module-info.class文件常量池的第7个常量就是一个CONSTANT_Package_info常量,表示a.b包,如下图所示:

0a2aa64a982438f01f788fda4ba5200a.png

类属性

增加了三个预定义属性:Module_attribute、ModulePackages_attribute和ModuleMainClass_attribute。

ModulePackages_attribute

ModulePackages_attribute属性记录和模块相关(比如输出或使用等)的包,结构如下所示:

ModulePackages_attribute { u2 attribute_name_index; u4 attribute_length; u2 package_count; u2 package_index[package_count]; }

其中package_index是个u2表,表里的每个u2值都是常量池索引,并且索引指向的一定是CONSTANT_Package_info常量。mymod模块module-info.class文件的ModulePackages_attribute属性如下图所示:

5f11bdc991f8800d11663f098a5f3038.png

ModuleMainClass_attribute

ModuleMainClass_attribute属性记录模块主类,结构如下所示:

ModuleMainClass_attribute { u2 attribute_name_index; u4 attribute_length; u2 main_class_index; }

其中main_class_index是指向CONSTANT_Class_info常量的索引。mymod模块module-info.class文件的ModuleMainClass_attribute属性如下图所示:

8c1b95afd56f46272e3956fa7efd5b4a.png

Module_attribute

Module_attribute属性比较复杂,结构如下所示:

Module_attribute {

u2 attribute_name_index;

u4 attribute_length;

u2 module_name_index;

u2 module_flags;

u2 module_version_index;

u2 requires_count;

{ u2 requires_index;

u2 requires_flags;

u2 requires_version_index;

} requires[requires_count];

u2 exports_count;

{ u2 exports_index;

u2 exports_flags;

u2 exports_to_count;

u2 exports_to_index[exports_to_count];

} exports[exports_count];

u2 opens_count;

{ u2 opens_index;

u2 opens_flags;

u2 opens_to_count;

u2 opens_to_index[opens_to_count];

} opens[opens_count];

u2 uses_count;

u2 uses_index[uses_count];

u2 provides_count;

{ u2 provides_index;

u2 provides_with_count;

u2 provides_with_index[provides_with_count];

} provides[provides_count];

}

Module_attribute属性虽然结构复杂,但其实就是module-info.java文件中模块定义里requires、exports、opens、uses和provides语句的直接映射。mymod模块module-info.class文件的Module_attribute属性总体如下图所示:

eee024b35f7b8cfb68bc94185f38a86a.png

requires语句对应的部分如下图所示:

ee626c5949589025687fcfe895023831.png

exports语句对应的部分如下图所示:

c1c96b3d7718ae4119bcdd31a76df561.png

opens语句对应的部分如下图所示:

8a7c983a300bedd14794b4547d3af0ca.png

uses语句对应的部分如下图所示:

50bbd695cd12eba48d6283c759e1c0c4.png

provides语句对应的部分如下图所示:

395e98a70b3c5a1e78d8ec19bb969d6d.png

广告

以上Java9在class文件方面的变动就介绍完了,如果想深入了解Java8的class文件格式,请关注自己动手写Java虚拟机 这本书 :)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值