拓展阅读

Java Functional java 函数式编程

Java Lambda

jdk10 有哪些新特性

Java 9 是一个里程碑式的版本,带来了许多重要的改进和新特性。以下是 JDK 9 中一些主要的新特性:

JDK 10 引入了一系列新特性和改进,以下是 JDK 10 的一些主要新特性:

  1. 局部变量类型推断(JEP 286): 使用 var 关键字,允许开发者在声明局部变量时不必显式指出类型,编译器会根据变量的初始化程序推断其类型。这减少了样板代码,使得代码更加简洁。var 仅用于局部变量,不适用于方法参数、返回类型等。

  2. 并行全垃圾回收器(G1): JDK 10 通过 JEP 307 改进了 G1 垃圾收集器,引入了并行 Full GC,以改善 G1 在最坏情况下的延迟。G1 旨在避免 Full GC,但在必要时,此改进有助于提高性能。

  3. 垃圾回收器接口(JEP 304): 提供了一个垃圾回收器接口,以便新的垃圾回收器可以更容易地集成到 HotSpot VM 中。

  4. 线程-局部管控: 允许在不执行全局 VM 安全点的情况下对线程执行回调,使得停止单个线程而不是全部线程成为可能。

  5. 合并 JDK 多个代码仓库到一个单独的储存库中: JDK 10 将 JDK 9 中的多个代码仓库合并为一个,简化了代码管理和维护。

  6. 新增 API
    • ByteArrayOutputStream 新增 toString(Charset) 方法,允许使用指定的字符集解码字节。
    • ListMapSet 接口增加了 copyOf 静态方法,返回一个不可修改的集合。
    • java.util.Properties 新增构造函数和 replace 方法的重载版本。
  7. Collectors 收集器新增方法: 新增 toUnmodifiableListtoUnmodifiableSettoUnmodifiableMap 等方法,方便创建不可修改的集合。

  8. 其他特性
    • 线程本地握手(JEP 312)
    • 其他 Unicode 语言标签扩展(JEP 314)
    • 实验性的 JIT 编译器(JEP 317)
    • 应用程序类数据共享(JEP 310)
    • 根证书颁发认证(CA)删除工具 javah(JEP 313)
  9. 版本号命名规则变更: JDK 10 采用了基于时间的版本控制命名方案,其中版本号的新模式是 $FEATURE.$INTERIM.$UPDATE.$PATCH,这更适合基于时间的发布模型。

  10. 安全性能改进: JDK 10.0.1 针对安全性能进行了一些改进,例如在 CipherOutputStream 中捕获 BadPaddingException 异常,并在解密时校验异常。

这些新特性和改进展示了 JDK 10 在性能、安全性、易用性等方面的持续进步。开发者可以利用这些特性来提升 Java 应用程序的质量和性能。

jdk10 局部变量类型推断(JEP 286)

JDK 10 引入的局部变量类型推断(Local Variable Type Inference),也称为 JEP 286,是一个旨在提高 Java 代码可读性和简洁性的语言特性。通过引入 var 关键字,开发者可以在声明局部变量时进行类型推断,而不必显式地指定变量的类型。

1. 使用 var 关键字

使用 var 关键字,开发者可以更简洁地声明局部变量,编译器会根据变量初始化的值进行类型推断。

var list = new ArrayList<String>();  // 类型推断为 ArrayList<String>
var map = new HashMap<Integer, String>();  // 类型推断为 HashMap<Integer, String>

2. 代码可读性和简洁性

局部变量类型推断可以使代码更加简洁和易读,特别是对于类型名称较长或复杂的情况。它允许开发者专注于代码的逻辑而不是类型声明。

// 没有使用 var
List<String> listOfStrings = new ArrayList<String>();

// 使用 var
var listOfStrings = new ArrayList<String>();

3. 类型安全性

尽管使用 var 关键字进行类型推断,Java 仍然是一个静态类型语言,编译器会在编译时进行类型检查,确保代码的类型安全性。

var list = new ArrayList<String>();
// list.add(123);  // 编译错误,因为 123 不是 String 类型

4. 局限性

  • var 只能用于局部变量,不能用于方法参数、构造函数、类成员或返回类型。
// 方法参数
void printSomething(var text) {}  // 编译错误

// 类成员
var instanceVariable = new ArrayList<String>();  // 编译错误

// 返回类型
var getValue() { return 123; }  // 编译错误
  • 由于类型推断,变量必须在声明时进行初始化。
var number;  // 编译错误,需要初始化

5. 使用场景

局部变量类型推断适用于大多数需要明确初始化的局部变量声明,特别是在 lambda 表达式和集合初始化等场景中,可以减少冗余和提高代码可读性。

// 使用 lambda 表达式
var runnable = (Runnable) () -> System.out.println("Hello, World!");

// 使用集合初始化
var numbers = List.of(1, 2, 3, 4, 5);

总结

JDK 10 中的局部变量类型推断(JEP 286)是一个重要的语言特性,它通过引入 var 关键字,提供了一种更简洁和可读的方式来声明局部变量。

这个特性不仅使 Java 代码更加简洁和易读,还可以提高开发效率,减少冗余代码,并提高代码可维护性。

尽管有一些使用限制,但局部变量类型推断仍然是一个有价值的增强,适用于许多常见的编程场景。

jdk10 并行全垃圾回收器(G1)

JDK 10 引入了对 G1(Garbage-First)垃圾收集器的改进,特别是并行全垃圾回收(Full GC)的能力,这是通过 JEP 307 实现的。

以下是 JDK 10 中 G1 垃圾收集器的详细介绍:

  1. 并行全垃圾回收: 在 JDK 10 之前,G1 垃圾收集器在执行 Full GC 时使用单线程进行标记-清除-压缩算法,这可能导致较长的停顿时间。JDK 10 改进了 G1,使用并行化标记-清除-压缩算法,以减少 Full GC 的停顿时间。

  2. 线程数量控制: 并行 Full GC 所使用的线程数量可以通过 -XX:ParallelGCThreads 参数控制,这个参数同时也影响 Young 和 Mixed 收集器的线程数量。

  3. 性能提升: 通过并行化 Full GC,G1 垃圾收集器在处理大型堆或者当垃圾回收不能及时回收足够内存时,可以显著减少停顿时间,从而提升性能。

  4. G1 垃圾收集器的工作过程: G1 垃圾收集器将堆划分为多个大小相等的区域(Region),并跟踪这些区域中的垃圾回收价值,优先回收价值最大的区域。G1 通过并发标记和并行清理的方式,尽量减少停顿时间。

  5. G1 垃圾收集器的优点
    • 并行与并发执行,有效利用多核处理器。
    • 分代收集,对新生代和老生代采用不同的策略。
    • 空间整合,使用标记-压缩算法减少内存碎片。
    • 可预测的停顿时间,允许用户指定在特定时间片段内,垃圾回收造成的停顿时间不超过某个值。
  6. G1 垃圾收集器的参数调优: G1 提供了多个参数供开发者进行调优,如控制区域大小的 -XX:G1HeapRegionSize,设置最大GC停顿时间的 -XX:MaxGCPauseMillis,以及触发并发GC周期的 Java 堆占用率阈值 -XX:InitiatingHeapOccupancyPercent 等。

  7. 适用场景: G1 垃圾收集器适用于大堆内存和对延迟敏感的应用,如服务端应用程序,它能够在保证高吞吐量的同时,尽可能减少垃圾收集的停顿时间。

  8. JDK 版本中的演进: G1 从 JDK 7u4 版本开始引入,JDK 9 中成为默认垃圾收集器,并在 JDK 10 中通过并行 Full GC 进一步增强。

  9. 注意事项: 尽管 G1 垃圾收集器在 JDK 10 中得到了改进,但在小内存环境中相比其他收集器如 CMS 可能没有优势。此外,G1 的内存占用和程序运行时的额外执行负载可能比 CMS 高。

通过这些改进,JDK 10 使得 G1 垃圾收集器成为一个更加强大和灵活的工具,适用于需要在大堆内存和低延迟之间找到平衡点的 Java 应用。开发者可以根据应用的具体需求,利用 G1 垃圾收集器提供的参数进行性能调优,以获得更好的垃圾收集性能。

jdk10 垃圾回收器接口(JEP 304)

JDK 10 引入了垃圾回收器接口(Garbage Collector Interface),这是通过 JEP 304 实现的。

这个改进旨在提高 HotSpot 虚拟机内部垃圾回收器(GC)代码的模块化,从而简化添加新 GC 或从 JDK 构建中排除现有 GC 的过程。

以下是 JEP 304 的一些关键点:

  1. 接口定义: JEP 304 通过定义一个清晰的接口 CollectedHeap,要求每个垃圾收集器实现都必须提供这个接口。这使得垃圾收集器与 HotSpot 虚拟机的其他部分之间的交互主要由 CollectedHeap 类来驱动。

  2. 代码隔离性: 引入垃圾回收器接口的目的是为了改善不同垃圾收集器实现之间的源码隔离性。这意味着对一个 GC 实现的更改不会影响到另一个 GC 实现,从而降低了维护和更新的复杂性。

  3. 简化 GC 添加或移除: 通过这个接口,添加一个新的 GC 或者从 JDK 构建中排除某个 GC 变得更加简单。开发者只需要实现一组文档化的接口,而不需要了解 HotSpot 中需要改变的所有地方。

  4. 非目标: JEP 304 并不旨在实际添加或移除 GC。它的主要目标是提高模块化,并为将来可能的 GC 添加或移除提供便利。

  5. 对其他 JEP 的帮助: JEP 304 有助于其他几个 JEP 的实现,包括 JEP 291(弃用 CMS 垃圾收集器)和 JEP 189(Shenandoah:一个超低暂停时间垃圾收集器)。通过提供隔离机制,这些 JEP 能够更少地干扰现有代码。

  6. 风险和假设: 此 JEP 主要涉及重构 HotSpot 内部代码,因此风险较低。不过,如果引入了额外的虚方法调用,可能会影响性能。这个风险可以通过持续的性能测试来缓解。

  7. 测试和验证: 由于 JEP 304 是纯粹的重构,因此在之前版本中工作的内容之后也应该工作,并且性能不应退步。运行标准回归测试套件应该足够,无需开发新的测试。

  8. 社区反馈: 在 Java 10 发布之前,社区对于引入垃圾回收器接口表示支持,因为它有助于简化 GC 的实现和维护。

JEP 304 的引入为 JDK 的垃圾回收器带来了更好的模块化和可维护性,为 Java 平台的长期发展和 GC 技术的进步奠定了基础。

JDK 10 引入了垃圾回收器接口(JEP 304),这是一个旨在提高 JVM 的可维护性和可扩展性的关键特性。

通过引入垃圾回收器接口,JDK 提供了一个标准化的方式,允许开发者更容易地为 JVM 实现新的垃圾回收器或修改现有的垃圾回收器。

1. 垃圾回收器接口(Garbage Collector Interface)

JEP 304 引入了一个新的垃圾回收器接口,这个接口定义了 JVM 垃圾回收器的核心行为和操作。它为开发者提供了一个清晰、一致的 API,用于开发、调试和优化垃圾回收器实现。

2. 标准化的垃圾回收器行为

通过定义垃圾回收器接口,JDK 标准化了垃圾回收器的行为和操作,包括垃圾收集周期、内存管理、对象分配等。这使得开发者可以更容易地理解和预测 JVM 的垃圾回收行为,从而更有效地调整和优化应用程序的内存使用。

3. 支持多种垃圾回收器实现

垃圾回收器接口为 JVM 提供了一个开放的框架,允许开发者为不同的应用场景和需求实现特定的垃圾回收器。这包括现有的垃圾回收器,如 G1、Parallel 和 CMS,以及未来可能的新垃圾回收器实现。

4. 增强的垃圾回收器开发和调试工具

JEP 304 提供了一个更容易的方式来开发和调试垃圾回收器实现。这包括新的 JVM 选项和诊断工具,用于监控和分析垃圾回收器的性能和行为,以及更容易地进行垃圾回收器性能调优。

5. 提高 JVM 的可维护性和可扩展性

通过引入垃圾回收器接口,JDK 提高了 JVM 的可维护性和可扩展性。这使得 JVM 更容易适应不同的硬件和操作系统环境,以及应用程序的特定需求和性能要求。

总结

JDK 10 的垃圾回收器接口(JEP 304)是一个重要的增强,它为 JVM 提供了一个标准化的、可扩展的框架,用于开发、调试和优化垃圾回收器实现。

这个接口不仅提高了 JVM 的可维护性和可扩展性,还支持多种垃圾回收器实现,提供了更强大和灵活的工具来管理和优化应用程序的内存使用。

开发者和系统管理员可以利用这些工具和特性来更有效地管理和调优垃圾回收,提高应用程序的性能和可用性。

jdk10 线程-局部管控

JDK 10 引入了线程局部管控的特性,这是通过 JEP 312 实现的。这项特性允许 JVM 在不执行全局安全点操作的情况下,对单个线程进行停止、挂起和恢复操作。全局安全点操作通常需要暂停所有的线程,以便进行一些全局性的检查或操作,如垃圾回收。

以下是线程局部管控的一些关键点:

  1. 减少全局停顿: 线程局部管控的主要目标是减少全局停顿时间,这对于响应时间敏感的应用程序尤其重要。通过仅停止单个线程,可以避免全局安全点带来的性能开销。

  2. 线程操作: JEP 312 允许 JVM 实现者对单个线程执行操作,如挂起(suspend)、恢复(resume)和停止(stop)。这些操作可以用于调试、线程转储或在不干扰其他线程的情况下对问题线程进行分析。

  3. 调试和分析: 线程局部管控对于线程转储的生成和线程行为的分析非常有用。开发者可以在不干扰其他线程的情况下,对单个线程的状态进行审查,这在调试复杂应用时非常有价值。

  4. 安全点的避免: 在传统的 JVM 实现中,要对单个线程进行操作,通常需要触发一个全局安全点。这意味着所有线程都会被暂停,直到需要操作的线程完成所需的操作。线程局部管控通过避免这种全局暂停,提高了应用的整体性能。

  5. 潜在用例: 除了调试,线程局部管控还可以用于其他场景,如在多线程应用中对特定线程进行性能分析,或者在不中断服务的情况下,对单个线程进行问题排查。

  6. 实现细节: 线程局部管控的实现涉及到 JVM 内部的线程管理机制。JVM 需要能够识别何时需要对单个线程进行操作,并能够在不触发全局安全点的情况下执行这些操作。

  7. 对开发者的影响: 对于 Java 开发者来说,线程局部管控的特性可能不会直接影响他们的日常工作。然而,这项特性对于 JVM 的维护者和性能调优者来说非常重要,因为它提供了更精细的线程控制手段。

  8. JDK 版本中的演进: 这项特性在 JDK 10 中引入,后续版本可能会根据反馈和实际使用情况进行进一步的优化和改进。

线程局部管控是 JDK 10 中一个重要的内部改进,它提高了 JVM 对线程的控制能力,尤其是在需要对单个线程进行操作而不影响整个应用性能的场景中。

这项特性对于 JVM 的调试和性能分析工具的开发具有重要意义。

jdk10 增强的 Optional 类

JDK 10 对 Optional 类进行了一些增强,主要集中在为 Optional 类添加了一些新的方法和改进现有方法的行为,以提供更好的使用体验和功能。

1. orElseThrow 方法的重载

在 JDK 10 中,Optional 类的 orElseThrow 方法得到了增强。除了原有的 orElseThrow 方法外,现在还提供了一个重载版本,允许开发者通过提供一个无参的 Supplier 来自定义抛出的异常。

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

这使得在某些场景下,开发者可以更容易地定义和抛出自定义异常。

2. Optional.stream 方法

JDK 10 引入了 Optional.stream 方法,该方法允许将 Optional 对象转换为一个包含零个或一个元素的流。这使得开发者可以更方便地在流操作中使用 Optional 对象。

public Stream<T> stream()

使用示例:

Optional<String> optional = Optional.of("value");
optional.stream().forEach(System.out::println); // 输出:value

3. orElseGet 方法的性能优化

JDK 10 对 Optional 类的 orElseGet 方法进行了性能优化,特别是当 Optional 对象包含一个非空值时。这些优化有助于提高 Optional 对象的创建和访问速度,特别是在高性能或大规模数据处理应用中。

4. 其他小改进

除了上述主要改进外,JDK 10 还对 Optional 类进行了一些其他小的改进和优化,以提高其整体性能和稳定性。

总结

JDK 10 对 Optional 类进行了一系列增强,主要包括增加 orElseThrow 方法的重载版本、引入 Optional.stream 方法以及优化 orElseGet 方法的性能等。这些改进不仅提供了更多的灵活性和功能,还增强了 Optional 类在 Java 应用程序中的使用体验。开发者可以利用这些增强功能来编写更加清晰、简洁和高效的代码,特别是在处理可能为空的值或对象时。

jdk10 Stream 接口的新方法

在 JDK 10 中,Stream 接口得到了一些新的方法和改进,这些改进主要目的是提供更多的灵活性和便利性,以支持更复杂和高效的流操作。以下是 JDK 10 中 Stream 接口的一些新方法:

1. Collector toUnmodifiableList 方法

在 JDK 10 中,Collectors 类增加了一个新的收集器 Collectors.toUnmodifiableList(),它返回一个不能修改的不可变列表。

public static <T> Collector<T, ?, List<T>> toUnmodifiableList()

这个方法返回一个收集器,用于将流中的元素收集到一个不可修改的列表中。

使用示例:

List<String> list = Stream.of("a", "b", "c")
                          .collect(Collectors.toUnmodifiableList());

2. Optional Stream 方法

如前面提到的,JDK 10 引入了 Optional.stream() 方法,该方法允许将 Optional 对象转换为一个流,包含零个或一个元素。

public Stream<T> stream()

使用示例:

Optional<String> optional = Optional.of("value");
optional.stream().forEach(System.out::println); // 输出:value

3. dropWhile 和 takeWhile 方法

JDK 9 引入了 dropWhiletakeWhile 方法,但它们在 JDK 9 中仅适用于 Stream,而在 JDK 10 中,它们也适用于 IntStreamLongStreamDoubleStream

  • dropWhile:从流的开头开始删除元素,直到找到第一个不满足给定谓词的元素。

      Stream.of("a", "b", "c", "", "e")
            .dropWhile(s -> !s.isEmpty())
            .forEach(System.out::println); // 输出:e
    
  • takeWhile:从流的开头开始获取元素,直到找到第一个不满足给定谓词的元素。

      Stream.of("a", "b", "c", "", "e")
            .takeWhile(s -> !s.isEmpty())
            .forEach(System.out::println); // 输出:a, b, c
    

4. 其他小改进

除了上述主要的新方法外,JDK 10 中 Stream 接口还进行了一些其他的小改进和优化,以提供更好的性能和使用体验。

总结

JDK 10 对 Stream 接口进行了一些增强,主要包括增加了新的收集器 Collectors.toUnmodifiableList()、引入了 Optional.stream() 方法,以及为 IntStreamLongStreamDoubleStream 添加了 dropWhiletakeWhile 方法。

这些改进增加了 Stream 接口的灵活性和功能,使开发者能够更容易地进行复杂和高效的流操作。

这些新方法和改进使得 Stream API 在处理集合和数据流时更加强大和灵活,为开发者提供了更多工具来编写清晰、简洁和高效的代码。

jdk10 更好的 StringBuilder 性能

在 JDK 10 中,StringBuilder 的性能得到了改进,尽管没有直接的 JEP 提案专门针对 StringBuilder 性能优化,但 OpenJDK 社区对 StringBuilder 进行了一些优化,使其在某些操作中更加高效。以下是 StringBuilder 在 JDK 10 中性能改进的一些方面:

  1. 代码优化: JDK 10 中对 StringBuilder 的底层实现进行了优化,提高了其在字符串拼接操作中的性能。这些优化可能包括减少不必要的内存分配、改进扩容机制等。

  2. 减少内存复制: 在之前的 JDK 版本中,当 StringBuilder 需要扩容时,会创建一个新的字符数组并复制现有内容。在 JDK 10 中,通过改进扩容机制,减少了内存复制的次数,从而提高了性能。

  3. 提高并发性能: 尽管 StringBuilder 是非线程安全的,但在多线程环境中,对 StringBuilder 的操作可能会导致性能瓶颈。JDK 10 中的优化可能有助于减少这种场景下的锁竞争,提高并发性能。

  4. 减少临时对象: JDK 10 改进了 StringBuilder 在某些操作中减少临时对象的创建,如在字符串拼接时,这有助于减少垃圾收集的开销,提高整体性能。

  5. API 的使用: JDK 10 中对 StringBuilder 的改进也可能鼓励开发者更多地使用这个类,而不是 String,因为 String 对象是不可变的,频繁的字符串操作会导致创建大量临时对象。

  6. 性能测试: 开发者可以通过性能测试来评估 JDK 10 中 StringBuilder 的性能提升。使用如 JMH(Java Microbenchmark Harness)这样的基准测试工具可以量化性能改进。

  7. 与其他 JDK 版本的比较: 在 JDK 10 中对 StringBuilder 的改进可能与其他 JDK 版本相比较,展现出更好的性能。开发者在升级 JDK 版本时,可以关注这些核心类库的性能变化。

  8. 社区贡献StringBuilder 的性能改进很可能是由 OpenJDK 社区的贡献者通过持续的性能分析和调优实现的。

  9. 文档和示例: JDK 10 的文档可能包含了有关如何高效使用 StringBuilder 的指导和示例,帮助开发者理解其性能优化和最佳实践。

请注意,具体的性能提升程度可能会根据应用程序的具体使用场景和工作负载而异。为了获得最佳性能,开发者应该对 StringBuilder 的使用进行适当的测试和调优。

jdk10 CopyOnWriteArrayList 的性能改进

在 JDK 10 中,并没有直接针对 CopyOnWriteArrayList 的性能改进作为一个独立的 JEP 或特性进行宣传。CopyOnWriteArrayList 是 Java 并发包 java.util.concurrent 中的一个线程安全列表,它通过写时复制(Copy-On-Write, COW)的策略来实现线程安全。这种策略在读取操作时无需加锁,从而提高了读取的并发性能,特别适合读多写少的场景。

然而,CopyOnWriteArrayList 在面对大量写入操作时性能可能不佳,因为它在每次写入操作时都需要复制整个底层数组。这种复制操作在高并发写入时会导致显著的性能开销和内存使用增加。

尽管 JDK 10 没有特定的更新日志提及对 CopyOnWriteArrayList 的性能改进,但以下几点可能会对性能有所影响:

  1. Java 平台的持续优化: 随着 Java 平台的持续优化,包括垃圾收集器和 JIT 编译器的改进,CopyOnWriteArrayList 在 JDK 10 中的性能可能间接受益。

  2. 并发编程的最佳实践: JDK 10 继续推广并发编程的最佳实践,通过文档和示例引导开发者更合理地使用 CopyOnWriteArrayList,比如在读多写少的场景下使用。

  3. 性能测试和调优: 开发者可以通过 JDK 10 提供的性能测试工具,如 JMH(Java Microbenchmark Harness),来测试 CopyOnWriteArrayList 的性能,并根据测试结果进行调优。

  4. 其他并发集合的替代使用: JDK 10 通过文档和社区的讨论,可能鼓励开发者在不适合使用 CopyOnWriteArrayList 的场景下考虑其他并发集合,如 ConcurrentHashMap

  5. 内存和 CPU 资源的动态调整: JDK 10 增强了 JVM 配置选项,允许开发者更灵活地根据系统资源调整线程池和 GC 机制,这可能间接影响到 CopyOnWriteArrayList 的性能表现。

  6. 社区和开发者的反馈: OpenJDK 社区的持续反馈和贡献可能对 CopyOnWriteArrayList 的性能有所优化,尽管这些优化可能不会在 JDK 10 的官方发布说明中明确列出。

请注意,虽然 CopyOnWriteArrayList 在 JDK 10 中可能没有直接的性能改进,但 Java 平台的整体性能提升和社区的最佳实践推荐,都可能间接地对其性能产生积极影响。开发者应当根据具体的应用场景和工作负载来评估 CopyOnWriteArrayList 的适用性。