深入理解JVM(③)Java模块化系统
前言
JDK9引入的Java模块化系统(Java Platform Module System ,JPMS)是 对Java技术的一次重要升级,除了像之前JAR包哪有充当代码的容器之外,还包括:
- 依赖其他模块的列表。
- 导出的包列表,即其他模块可以使用的列表。
- 开放的包列表,即其他模块可反射访问模块的列表。
- 使用的服务列表。
- 提供服务的实现列表。
模块化系统
可配置的封装隔离机制解决了原来类路径上跨文件的public类的可访问性的问题。public类型不再意味着所有地方代码都可以访问它们,未导出和未开放的类是不能够被外部使用。
举例说明:
新创建一个maven工程,并创建两个module。

将每个module的Language level 和 SDK 设置成JDK9


然后在每个module的顶层目录中创建module-info.java

在ExampleOne中创建两个不同package下的类,ExampleFirst和ExampleOne。
package com.jimoer.jdkmoduleOne.test;
public class ExampleFirst {
private int id;
private String name;
private String sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "ExampleFirst{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
package com.jimoer.jdkmoduleOne;
public class ExampleOne {
private int id;
private String name;
private String arg;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArg() {
return arg;
}
public void setArg(String arg) {
this.arg = arg;
}
@Override
public String toString() {
return "ExampleOne{" +
"id=" + id +
", name='" + name + '\'' +
", arg='" + arg + '\'' +
'}';
}
}
然后在ExampleOne的module-info.java中声明导出包的路径。
module exampleOne {
// 导出包路径
exports com.jimoer.jdkmoduleOne.test;
}
在ExampleTwo中声明requires为引入包
module exampleTwo {
requires exampleOne;
}
然后在ExampleTwo中使用ExampleOne中的类
ublic class ExampleTwo {
public static void main(String[] args) {
ExampleFirst first = new ExampleFirst();
first.setId(1);
first.setName("余欢水");
first.setSex("男");
System.out.println(first);
}
}
运行结果:
ExampleFirst{id=1, name='余欢水', sex='男'}
但是当在ExampleTwo中引用ExampleOne中非导出包下的类时就会编译出错。

如上图提示,所有不被导出的包默认都被封装在模块里面。
模块的兼容性
为了使可配置的封装隔离机制能够兼容传统的类路径查找机制,JDK9提出了与“类路径”(ClassPath)相对应的“模块路径”(ModulePath)的概念。只要放在类路径上的JAR文件,都会被当作传统的JAR包来对待;相应地,只要放在模块路径上的JAR文件,即使没有使用JMOD后缀,甚至不包含module-info.class文件,也仍然会被当作一个模块来对待。
为了保证Java应用升级到JDK9之后依然使用传统的类路径,不会受到影响,制定了三条规则来保证兼容性。
- JAR文件在类路径的访问规则:所有类路径下的JAR文件及其他资源文件,都被视为自动打包在一个匿名模块(Unnamed Module)里,这个匿名模块几乎是没有任何隔离的,它可以看到和使用类路径上所有的包、JDK模块中所有的导出包,以及模块路径是哪个所有模块中导出的包。
- 模块在模块路径的访问规则:模块路径下的具名模块(Named Module)只能访问到她依赖定义中列明依赖的模块和包,匿名模块里所有的内容对具名模块来说都是不可见的,即具名模块看不见传统JAR包的内容。
- JAR文件在模块路径的访问规则:如果把一个传统的、不包含模块定义的JAR文件放置到模块路径中,它就会变成一个自动模块(Automatic Module)。
模块化下的类加载器
JDK9为了保证兼容性,依然保持了三层类加载器架构以及双亲委派模型。但是为了模块化系统的顺利实施,还是对类加载器做了一些改动。
- 首先,扩展类加载器(Extension Class Loader)被平台类加载器(Platform Class Loader)取代。因为模块化天然的支持扩展,自然不需要在存在扩展类加载器了。
- 其次,平台类加载器和应用类加载器都不再派生自java.net.URLClassLoader,如果有程序直接依赖了这种继承关系,或者依赖了URLClassLoader类特定方法,那代码很可能会在JDK9及更高版本的JDK中崩溃。
- 最后,JDK9中虽然仍然维持着三层类加载器和双亲委派架构,但类加载的委派关系也发生了变动。当平台及应用程序类加载器收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块中,如果可以找到这样的归属关系,就要优先委派给负责哪个模块的加载器完成加载,这可以算是对双亲委派的第四次破坏。
JDK9前后三层类加载器的架构图对比如下:

深入理解JVM(③)Java模块化系统的更多相关文章
- 深入学习重点分析java基础---第一章:深入理解jvm(java虚拟机) 第一节 java内存模型及gc策略
身为一个java程序员如果只会使用而不知原理称其为初级java程序员,知晓原理而升中级.融会贯通则为高级 作为有一个有技术追求的人,应当利用业余时间及零碎时间了解原理 近期在看深入理解java虚拟机 ...
- 深入理解JVM—Java 6 JVM参数配置说明
原文地址:http://yhjhappy234.blog.163.com/blog/static/316328322011119111014657/ 使用说明< xmlnamespace pre ...
- 深入理解JVM : Java垃圾收集器
如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现. Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商.不同版本的虚拟机所提供的垃圾收集器都可能会有很大差 ...
- 深入理解JVM - Java内存模型与线程 - 第十二章
Java内存模型 主内存与工作内存 Java内存模型主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.此处的变量(Variable)与Java编程中 ...
- 深入理解JVM - Java内存区域与内存溢出异常 - 第二章
一 运行时数据区域 JVM在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间. 程序计数器 程序计数器(Program Counter ...
- 深入理解JVM(③)Java的模块化
前言 JDK9引入的Java模块化系统(Java Platform Module System ,JPMS)是 对Java技术的一次重要升级,除了像之前JAR包那样充当代码的容器之外,还包括: 依赖其 ...
- 深入理解OSGI:Java模块化之路
简介 Java可能是近20年来最成功的开发技术,因其具备通用性.高效性.平台移植性和安全性而成为不同硬件平台理想的开发工具.从笔记本电脑到数据中心,从游戏控制台到科学超级计算机,从手机到互联网,Jav ...
- Java模块化规范之争(转载)
经过近20年的发展,Java语言已成为今日世界上最成功.使用的开发者人数最多的语言之一,Java世界中无数商业的或开源的组织.技术和产品共同构成了一个无比庞大的生态系统. 与大多数开发人员的普遍认知不 ...
- 深入理解JVM内幕:从基本结构到Java 7新特性
转自:http://www.importnew.com/1486.html 每个Java开发者都知道Java字节码是执行在JRE((Java Runtime Environment Java运行时环境 ...
随机推荐
- Java实现蓝桥杯十六进制转八进制
基础练习 十六进制转八进制 时间限制:1.0s 内存限制:512.0MB 提交此题 锦囊1 锦囊2 问题描述 给定n个十六进制正整数,输出它们对应的八进制数. 输入格式 输入的第一行为一个正整数n ( ...
- Java实现 蓝桥杯 算法训练 1的个数
试题 算法训练 1的个数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输入正整数n,判断从1到n之中,数字1一共要出现几次.例如1123这个数,则出现了两次1.例如15,那么从1 ...
- java中装箱和拆箱的详细使用(详解)
一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Jav ...
- 阿里云杨敬宇:边缘计算行业通识与阿里云ENS的技术演进之路
近日,阿里云杨敬宇在CSDN阿里云核心技术竞争力在线峰会上进行了<5G基础设施-阿里云边缘计算的技术演进之路>主题演讲,针对5G时代下,行业和技术的趋势.边缘计算产业通识以及阿里云边缘计算 ...
- (前言一)HTTP报文
01 概述 客户端与服务器端之间的通信,通过HTTP协议,以HTTP报文的形式来实现数据的交互. HTTP报文是HTTP通信时发送的数据块,本文主要从以下几个方面介绍HTTP报文:HTTP报文结构.方 ...
- 除了FastJson,你也应该了解一下Jackson(二)
概览 上一篇文章介绍了Jackson中的映射器ObjectMapper,以及如何使用它来实现Json与Java对象之间的序列化和反序列化,最后介绍了Jackson中一些序列化/反序列化的高级特性.而本 ...
- 数据误操作,删库跑路?教你使用ApexSQLLog工具从 SQLServer日志恢复数据!
前几天同事不小心误操作,将SQLServer库的一张表的一个状态字段给刷成了一个统一状态,由于是update执行所以原来的相关状态无法确定.发生这种事情的时候我的小伙伴背后 一凉,估计心里里面想这怕是 ...
- Python大神编程常用4大工具,你用过几个?
摘要:Python是一种跨平台的编程语言,能够在所有主要的操作系统上,运行你编写的任何Python程序.今天介绍几款常见的工具:Python自带的解释器.文本编辑器(Geany.Sublime Tex ...
- ubuntu12.04可用源
最近试了不少源,都无法用.这一份是目前可以正常使用的 #deb cdrom:[Ubuntu 12.04.5 LTS _Precise Pangolin_ - Release amd64 (201408 ...
- Javascript模块化编程(转自阮一峰的网络日志)(备忘)
http://www.ruanyifeng.com/blog/2012/10/javascript_module.html