JDK 9模块化介绍
- 介绍
- Java SE 9:拼图项目
- 1.拼图项目将引入Java SE 9的全新概念:Java模块系统。
- 2.Java模块解决了什么问题
- 3.细节描述
- Java SE 9模块系统的优点
- 1.由于Java SE 9将把JDK,JRE,JAR等分成较小的模块,因此我们可以使用所需的任何模块。因此将Java应用程序缩减到小型设备非常容易。
- API层面介绍
- Java 9 改进的 @Deprecated 注解
- 全新的http客户端API
- Java 9模块系统之母
- G1垃圾收集器
- 查看JDK垃圾回收机制的命令
- Java 9对类加载器的改动
- 类加载过程
- 类加载器对比
- Java 9之前的类加载器层次
- Java 9之后的类加载器层次
介绍
甲骨文公司已将Java 9版本从2017年3月推迟到2017年9月。导致推迟的原因是它提供了150多种新功能,其中包括新的模块系统和相当多的改进,这些改进有望带来更高的安全性,更多的可伸缩性和更好的性能管理。
JDK 9提供了超过150项新功能特性,包括备受期待的模块化系统、可交互的REPL工具: jshell, JDK编译工具,语法层面的改变:Java公共API和私有代码,以及安全增强、扩展提升、性能管理改善等。
Java SE 9:拼图项目
1.拼图项目将引入Java SE 9的全新概念:Java模块系统。
这是Oracle Corp在Java SE 9版本中非常重要的项目。最初,他们作为Java SE 7 Release的一部分启动了该项目。但是,由于进行了很大的更改,它被推迟到Java SE 8,然后又被推迟了。现在它将与Java SE 9一起在2017年9月发布问世。
2.Java模块解决了什么问题
JDK类库目前太臃肿了,在一些微型设备上可能用不到全部的功能,在目前的情况下却不得不引用全部的类库。Java 9引入模块功能后,JDK、JRE、甚至是JAR都可以把用不到的类库排除掉,大大降低了依赖库的规模。
3.细节描述
1.由于当前的JDK源代码jar文件太大,尤其是rt.jar,因此每次在运行时,我们不需要的也会给我们加载进去,就会导致资源浪费(运行内存),因此他们把rt.jar进行了拆分为大约71个jmod文件模块左右,每个模块下都会有一个module-info.java文件,它声明了模块的访问方式以及依赖关系。
Java SE 9模块系统的优点
1.由于Java SE 9将把JDK,JRE,JAR等分成较小的模块,因此我们可以使用所需的任何模块。因此将Java应用程序缩减到小型设备非常容易。
3.易于测试和可维护性。4.支持更好的性能。5.由于public不仅是public,它还支持非常强的封装。6.我们不能再访问内部非关键API。7.模块可以非常安全地隐藏不必要的内部细节,我们可以获得更好的安全性。8.应用程序太小,因为我们只能使用所需的模块。9.它易于支持组件之间的较少耦合。10.它易于支持单一职责原则(SRP)。
API层面介绍
String的底层优化: byte 是字节数据类型 ,是有符号型的,占1 个字节;大小范围为-128—127 。char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 );大小范围 是0—65535
[Java中String类型在JDK 8与JDK 11,JDK 17的底层实现变迁 http://t.csdnimg.cn/RfheY]
编辑
编辑
// Java 9 改进的 Stream API 添加了一些便利的方法,使流处理更容易,并使用收集器编写复杂的查询。
// Java 9 为 Stream 新增了几个方法:dropWhile、takeWhile、ofNullable,为 iterate 方法新增了一个重载方法。
// takeWhile 方法
default Stream<T> takeWhile(Predicate<? super T> predicate)
// takeWhile() 方法使用一个断言作为参数,返回给定 Stream 的子集直到断言语句第一次返回 false。如果第一个值不满足断言条件,将返回一个空的 Stream。
// takeWhile() 方法在有序的 Stream 中,takeWhile 返回从开头开始的尽量多的元素;在无序的 Stream 中,takeWhile 返回从开头开始的符合 Predicate 要求的元素的子集
Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
.forEach(System.out::print);
// dropWhile 方法和 takeWhile 作用相反的,使用一个断言作为参数,直到断言语句第一次返回 true 才返回给定 Stream 的子集。
default Stream<T> dropWhile(Predicate<? super T> predicate)
Stream.of("a","b","c","","e","f").dropWhile(s-> !s.isEmpty())
.forEach(System.out::print);
// 方法允许使用初始种子值创建顺序(可能是无限)流,并迭代应用指定的下一个方法。 当指定的 hasNext 的 predicate 返回 false 时,迭代停止。
static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
IntStream.iterate(3, x -> x < 10, x -> x+ 3).forEach(System.out::println);
// ofNullable 方法可以预防 NullPointerExceptions 异常, 可以通过检查流来避免 null 值。
// 如果指定元素为非 null,则获取一个元素并生成单个元素流,元素为 null 则返回一个空流。
static <T> Stream<T> ofNullable(T t)
long count = Stream.ofNullable(100).count();
System.out.println(count);
count = Stream.ofNullable(null).count();
System.out.println(count);
Java 9 改进的 @Deprecated 注解
Deprecated 注解意思是若某类或某方法加上该注解之后,表示此方法或类不再建议使用,调用时也会出现删除线,但并不代表不能用,只是说,不推荐使用,因为还有更好的方法可以调用
注解 @Deprecated 可以标记 Java API 状态,可以是以下几种:
- 使用它存在风险,可能导致错误
- 可能在未来版本中不兼容
- 可能在未来版本中删除
- 一个更好和更高效的方案已经取代它。
语法层面改变
// JDK 7 try
try (FileInputStream inputStream = new FileInputStream("d:\\a.txt");
FileOutputStream outputStream = new FileOutputStream("d:\\c.txt")){
}
// JDK 9 try优化
FileInputStream inputStream = new FileInputStream("d:\\a.txt");
FileOutputStream outputStream = new FileOutputStream("d:\\c.txt")
try (inputStream;outputStream){
}
// JDK9 新增接口方法
public interface MyInterface {
//定义私有方法
private void test1() {
System.out.println("123");
}
void test2() {
test1();
}
}
全新的http客户端API
http1.1 采用长连接tcp,好处是不需要每次请求都需要创建一次tcp连接,坏处是请求需等待,而http2.0采用的是多路复用,在一个tcp连接可以处理多个请求,无需等待上一个请求处理完成,提高响应速度。 [HTTP1.1升级HTTP2.0 http://t.csdnimg.cn/v0HMZ]
Java 9模块系统之母
Java 9模块系统具有一个“ java.base”模块。它被称为基本模块。它是一个独立模块,不依赖于任何其他模块。默认情况下,所有其他模块都依赖于此模块。
这就是“ java.base”模块也被称为Java 9模块之母的原因。
它是所有JDK模块和用户定义模块的默认模块。
G1垃圾收集器
G1(Garbage First Collector)是一款面向服务端应用的垃圾收集器,设计用于多核CPU和大容量内存的机器。它的主要特性包括:
- 目标:在可预测的暂停时间内执行垃圾收集,同时保持高吞吐量。G1通过并行和并发的方式工作,以减少应用程序暂停的时间。
- 适用场景:G1在JDK 9及更高版本中成为默认的垃圾收集器,取代了CMS收集器。它特别适合现代服务器硬件,如多核处理器和大内存容量。
- 操作模式:G1将堆空间划分为多个区域(region),每个区域可以独立地进行垃圾回收,而不是整个堆空间一次性进行回收。这样可以更好地控制垃圾回收的暂停时间。
查看JDK垃圾回收机制的命令
虽然 java -XX:+PrintCommandLineFlags -version
可以显示JVM启动时使用的命令行参数,但要查看具体的垃圾收集器配置,更合适的命令是:
- 使用
-XX:+PrintGCDetails
或-XX:+PrintGC
,并运行一些内存密集型操作,以观察和分析垃圾收集器的行为。
Java 9对类加载器的改动
Java 9引入了模块系统(Jigsaw项目),这改变了类加载器的运作方式。模块系统允许代码和资源被组织成模块,每个模块可以声明对外部模块的依赖关系,以及它公开给外部模块的包。这种变化不仅影响了类路径的结构,也改变了类的查找和加载过程,使得类和资源的管理更加严格和清晰。
类加载过程
类加载过程通常被分为以下几个阶段:
- 加载(Loading):读取类的二进制字节流,将其转换为方法区的数据结构,并创建
java.lang.Class
对象。 - 验证(Verification):确保字节流符合JVM规范,防止恶意代码。
- 准备(Preparation):为类变量分配内存并设置默认值。
- 解析(Resolution):将符号引用转换为直接引用。
- 初始化(Initialization):执行类构造器
<clinit>()
方法,设置类变量的初始值。
初始化阶段就是执行类构造器方法的过程
类加载器对比
Java 9之前的类加载器层次
-
引导类加载器(Bootstrap Class Loader):这是JVM内部的类加载器,它加载Java的核心类库(如
java.lang
、java.util
等),这些类位于$JAVA_HOME/jre/lib/rt.jar
或$JAVA_HOME/jre/classes
目录下。引导类加载器没有父类加载器,通常表示为null
。 -
扩展类加载器(Extension Class Loader):这个类加载器加载位于
$JAVA_HOME/jre/lib/ext
目录下的jar文件,也就是扩展库。它的父类加载器是引导类加载器。 -
应用类加载器(Application Class Loader):也被称为系统类加载器,负责加载用户应用程序的类,它会从环境变量
CLASSPATH
指定的位置加载类库。它的父类加载器是扩展类加载器。
Java 9之后的类加载器层次
Java 9引入了模块系统(Jigsaw项目),这改变了类加载器的层次和作用:
-
引导类加载器:在Java 9中,核心类库依然由引导类加载器加载,但现在它们被组织成模块。核心模块如
java.base
由引导类加载器加载。 -
平台类加载器:这是Java 9中新增的类加载器,用于加载
$JAVA_HOME/jre/lib
目录下的非核心模块。这些模块构成了平台模块集,可以由平台类加载器加载。可以通过ClassLoader.getPlatformClassLoader()
获取平台类加载器的引用。 -
应用或系统类加载器:这个类加载器的作用没有改变,仍然是加载应用程序类路径(
CLASSPATH
)上的类。然而,现在它也可以加载模块路径(--module-path
或-p
)上的模块。