提交 8d8ad98a 编写于 作者: W wizardforcel

2021-05-02 16:35:23

上级 3307b0d4
......@@ -2296,7 +2296,7 @@ NumberFormatters.parseLocaleStyleRound(
Locale.US, Style.LONG, true, "5,50 thousand");
```
通过`setCurrency​()``setParseIntegerOnly()``setMaximumIntegerDigits()``setMinimumIntegerDigits()``setMinimumFractionDigits()``setMaximumFractionDigits()`方法可以获得更多的调
通过`setCurrency​()``setParseIntegerOnly()``setMaximumIntegerDigits()``setMinimumIntegerDigits()``setMinimumFractionDigits()``setMaximumFractionDigits()`方法可以获得更多的调
# 摘要
......
......@@ -76,7 +76,7 @@ module com.three19.irisScan { }
# 模块化 JDK
JEP-200 的核心目标是使用**Java 平台模块系统****JPMS**)对 JDK 进行模块化。在 Java 9 之前,我们对 JDK 的熟悉包括对其主要组件的了解:
JEP-200 的核心目标是使用 **Java 平台模块系统****JPMS**)对 JDK 进行模块化。在 Java 9 之前,我们对 JDK 的熟悉包括对其主要组件的了解:
* JRE
* 解释器(Java)
......
......@@ -2,7 +2,7 @@
在上一章中,我们探讨了如何将 Java9 之前的应用程序迁移到新的 Java 平台。我们研究了在 Java9 上运行时可能导致当前应用程序出现问题的几个问题。我们首先回顾了 Jigsaw 项目,然后研究了模块如何适应新的 Java 平台。我们为您提供了一些见解和过程,使您的 Java8 代码能够与 Java9、10 或 11 一起工作。具体来说,我们提供了迁移规划的技巧、Oracle 关于迁移的共享建议,以及可以用来帮助您开始使用 Java18.x 的共享工具。
在本章中,我们将首先介绍新的命令行,**Read Eval Print Loop**(也称为**REPL**工具,以及**Java Shell****JShell**)。我们将首先回顾一些关于这个工具的介绍性信息,REPL 概念,然后讨论可以与 JShell 一起使用的命令和命令行选项。我们将采用实践者的方法来回顾 JShell,并包括您可以自己尝试的示例。
在本章中,我们将首先介绍新的命令行,**读取求值打印循环**(也称为**REPL**工具,以及 **Java Shell****JShell**)。我们将首先回顾一些关于这个工具的介绍性信息,REPL 概念,然后讨论可以与 JShell 一起使用的命令和命令行选项。我们将采用实践者的方法来回顾 JShell,并包括您可以自己尝试的示例。
本章将讨论以下主题:
......@@ -23,9 +23,9 @@ IDE 软件包就足够了。来自 JetBrains 的 IntelliJ IDEA 用于与本章
**JShell**是 Java 平台上比较新的一个重要工具。它是在 jdk9 中引入的。它是一个交互式 REPL 工具,用于评估以下 Java 编程语言组件声明、语句和表达式。它有自己的 API,因此可以被外部应用程序使用。
**Read-Eval-Print Loop** is often referred to as **REPL**, taking the first letter from each word in the phrase. It is also known as a language shell or interactive top level.
**读取求值打印循环** 通常称为 **REPL**,取自词组中每个单词的第一个字母。 它也被称为语言外壳或交互式顶层。
JShell 的引入是**JDK 增强建议****JEP**)222 的结果。以下是本 JEP 关于 Java Shell 命令行工具的既定目标:
JShell 的引入是 **JDK 增强建议****JEP**)222 的结果。以下是本 JEP 关于 Java Shell 命令行工具的既定目标:
* 促进快速调查
* 便于快速编码
......@@ -42,7 +42,7 @@ JShell 的引入是**JDK 增强建议**(**JEP**)222 的结果。以下是本
# JShell 入门
**JShell**是位于`/bin`文件夹中的命令行工具。此工具的语法如下:
**JShell** 是位于`/bin`文件夹中的命令行工具。此工具的语法如下:
```java
jshell <options> <load files>
......@@ -66,7 +66,7 @@ jshell <options> <load files>
| `/env` | 这个强大的命令允许您查看或更改评估上下文语法如下:`/env [-class-path <path>]  [-module-path <path>]  [-add-modules <modules>]` |
| `/exit` | 此命令用于退出 JShell。语法是简单的`/exit`,没有任何可用的选项或参数。 |
| `/history` | history 命令提供您所键入内容的历史记录。语法是简单的`/history`,没有任何可用的选项或参数。 |
| `/<id>` | 此命令用于通过引用`id`重新运行以前的代码段。语法如下:`/<id>`您也可以使用`/-<n>`引用*n<sup>th</sup>*前面的代码段来运行特定的代码段。 |
| `/<id>` | 此命令用于通过引用`id`重新运行以前的代码段。语法如下:`/<id>`您也可以使用`/-<n>`引用`n`代码段来运行特定的代码段。 |
| `/imports` | 可以使用此命令列出导入的项目。语法为`/imports`,不接受任何选项或参数。 |
| `/list` | 此命令将列出您键入的源代码。语法如下:`/list [<name or id> &#124; -all &#124; -start]` |
| `/methods` | 此命令列出所有声明的方法及其签名。语法如下:`/methods [<name or id> &#124; -all &#124; -start]` |
......@@ -209,13 +209,13 @@ JShell 不是一个全功能的文本编辑器,但是您可以在 shell 中做
默认的文本编辑/输入模式使您键入的文本显示在当前光标位置。当您想删除文本时,有几个选项可供选择。以下是完整的列表:
| **删除动作** | **PC 键盘组合** | **Mac 键盘组合** |
| 删除当前光标位置的字符 | *删除* | *删除* |
| 删除光标左侧的字符 | *退格* | *删除* |
| 删除从光标位置到行尾的文本 | *Ctrl*+`K` | *命令*+`K` |
| 删除从光标位置到当前单词末尾的文本 | *Alt*+`D` | *alt*+`D` |
| 从光标位置删除到上一个空白处 | *Ctrl*+`W` | *命令*+`W` |
| 在光标位置粘贴最近删除的文本 | *Ctrl*+`Y` | *命令*+`Y` |
| 当使用*Ctrl*+`Y`(或 Macintosh 上的 c*md+Y*时,您将能够使用*Alt+Y*键盘组合循环浏览先前删除的文本 | *Alt*+`Y` | *alt*+`Y` |
| 删除当前光标位置的字符 | `del` | `del` |
| 删除光标左侧的字符 | `backspace` | `del` |
| 删除从光标位置到行尾的文本 | `Ctrl + K` | `Cmd + K` |
| 删除从光标位置到当前单词末尾的文本 | `Alt + D` | `Alt + D` |
| 从光标位置删除到上一个空白处 | `Ctrl + W` | `Cmd + W` |
| 在光标位置粘贴最近删除的文本 | `Ctrl + Y` | `Cmd + Y` |
| 当使用`Ctrl + Y`(或 Macintosh 上的`Cmd + Y`)时,您将能够使用`Alt + Y`键盘组合循环浏览先前删除的文本 | `Alt + Y` | `Alt + Y` |
# 基本导航
......@@ -227,14 +227,14 @@ JShell 不是一个全功能的文本编辑器,但是您可以在 shell 中做
| 向上箭头 | 在历史中向上移动一行 |
| 向下箭头 | 沿着历史向前移动一行 |
| 返回 | 输入(提交)当前行 |
| *Ctrl*+`A`*cmd*+`A`在 Macintosh 上) | 跳到当前行的开头 |
| *Ctrl*+`E`*cmd*+`E`在 Macintosh 上) | 跳到当前行的末尾 |
| *Alt*+`B` | 退一步说 |
| *Alt*+`F` | 向前跳一个字 |
| `Ctrl + A``Cmd + A`在 Macintosh 上) | 跳到当前行的开头 |
| `Ctrl + E``Cmd + E`在 Macintosh 上) | 跳到当前行的末尾 |
| `Alt + B` | 退一步说 |
| `Alt + F` | 向前跳一个字 |
# 历史导航
JShell 会记住您输入的代码段和命令。它维护此历史记录,以便您可以重用已输入的代码段和命令。要循环浏览代码段和命令,可以按住*Ctrl*键(Macintosh 上的 c*md*,然后使用上下箭头键,直到看到所需的代码段或命令。
JShell 会记住您输入的代码段和命令。它维护此历史记录,以便您可以重用已输入的代码段和命令。要循环浏览代码段和命令,可以按住`Ctrl`键(Macintosh 上的`cmd`,然后使用上下箭头键,直到看到所需的代码段或命令。
# 高级编辑命令
......
# 利用默认的 G1 垃圾收集器
在上一章中,我们研究了**Java Shell****JShell**)、Java 的**Read Eval Print Loop****REPL**)命令行工具。我们从介绍该工具的信息开始,仔细研究了 REPL 概念。我们花了大量时间来检查 JShell 命令和命令行选项。我们的报道包括反馈模式的实用指南、资产列表和 shell 中的编辑。我们还获得了使用脚本的经验。
在上一章中,我们研究了 **Java Shell****JShell**)、Java 的 **读取求值打印循环****REPL**)命令行工具。我们从介绍该工具的信息开始,仔细研究了 REPL 概念。我们花了大量时间来检查 JShell 命令和命令行选项。我们的报道包括反馈模式的实用指南、资产列表和 shell 中的编辑。我们还获得了使用脚本的经验。
在本章中,我们将深入了解垃圾收集以及如何在 Java 中处理它。我们将从垃圾收集的概述开始,然后看看 Java9 之前的领域中的细节。有了这些基本信息,我们将研究 Java9 平台中特定的垃圾收集更改。最后,我们将研究一些即使在 Java11 之后仍然存在的垃圾收集问题。
......@@ -81,7 +81,7 @@ Java 让垃圾收集器在代码的暗处运行(通常是一个低优先级线
JVM 可以使用几种垃圾收集算法或类型。在本节中,我们将介绍以下垃圾收集算法:
* 标记和扫描
* **并发标记扫描****CMS**垃圾回收
* **并发标记扫描****CMS**垃圾回收
* 串行垃圾回收
* 并行垃圾回收
* G1 垃圾回收
......@@ -134,7 +134,7 @@ G1 算法的另一部分是当内存被释放时,堆空间被压缩。不幸
G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域的优先级。
**G1**名称首先指**垃圾**
**G1** 名称指**垃圾优先**
要为应用程序手动调用 G1 垃圾回收算法,请使用以下命令行选项:
......@@ -146,7 +146,7 @@ G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域
以下是 JVM 大小调整选项的列表:
| **尺寸说明** | **JVM 选项标志** |
| **大小说明** | **JVM 选项标志** |
| 此标志建立初始堆大小(年轻空间和长期空间的组合)。 | `XX:InitialHeapSize=3g` |
| 此标志建立最大堆大小(年轻空间和长期空间的组合)。 | `-XX:MaxHeapSize=3g` |
| 此标志建立初始和最大堆大小(年轻空间和长期空间的组合)。 | `-Xms2048m -Xmx3g` |
......@@ -160,22 +160,22 @@ G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域
| 此标志确定每个线程专用的栈区域的大小(以 KB 为单位)。 | `-XX:ThreadStackSize=512` |
| 此标志确定 JVM 可用的堆外内存的最大大小。 | `-XX:MaxDirectMemorySize=3g` |
以下是年轻一代垃圾收集选项的列表:
以下是新生代垃圾收集选项的列表:
| **年轻一代垃圾回收调优选项** | **旗** |
| **新生代垃圾回收调优选项** | **标志** |
| 设置保留阈值(从年轻空间升级到保留空间之前集合的阈值) | `-XX:Initial\TenuringThreshold=16` |
| 设置上限寿命阈值。 | `-XX:Max\TenuringThreshold=30` |
| 设置空间中允许的最大对象大小。如果一个对象大于最大大小,它将被分配到终身空间和绕过年轻空间。 | `-XX:Pretenure\SizeThreshold=3m` |
| 用于将年轻集合中幸存的所有年轻对象提升到终身空间。 | `-XX:+AlwaysTenure` |
| 使用此标记,只要幸存者空间有足够的空间,年轻空间中的对象就永远不会升级到终身空间。 | `-XX:+NeverTenure` |
| 我们可以指出我们想要在年轻空间中使用线程本地分配块。这在默认情况下是启用的。 | `-XX:+UseTLAB` |
| 切换此选项以允许 JVM 自适应地调整线程的**TLAB**(简称**线程本地分配块**)。 | `-XX:+ResizeTLAB` |
| 切换此选项以允许 JVM 自适应地调整线程的 **TLAB**(简称**线程本地分配块**)。 | `-XX:+ResizeTLAB` |
| 设置线程的 TLAB 的初始大小。 | `-XX:TLABSize=2m` |
| 设置 TLAB 的最小允许大小。 | `-XX:MinTLABSize=128k` |
以下是 CMS 调整选项列表:
| **CMS 调谐选项** | **旗** |
| **CMS 调优选项** | **标志** |
| 指示您希望仅使用占用率作为启动 CMS 收集操作的标准。 | `-XX:+UseCMSInitiating\OccupancyOnly` |
| 设置 CMS 生成占用率百分比以开始 CMS 收集周期。如果您指示一个负数,那么您就告诉 JVM 您要使用`CMSTriggerRatio`。 | `-XX:CMSInitiating\OccupancyFraction=70` |
| 设置要启动 CMS 集合以进行引导集合统计的 CMS 生成占用百分比。 | `-XX:CMSBootstrap\Occupancy=10` |
......@@ -187,22 +187,22 @@ G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域
| 您可以使用此命令在备注阶段之前强制年轻的集合。 | `-XX:+CMSScavengeBeforeRemark` |
| 如果使用的 Eden 低于阈值,则使用此选项可防止出现计划注释。 | `-XX:+CMSScheduleRemark\EdenSizeThreshold` |
| 设置您希望 CMS 尝试和安排备注暂停的 Eden 占用百分比。 | `-XX:CMSScheduleRemark\EdenPenetration=20` |
| 至少在年轻一代的入住率达到您想要安排备注的 1/4(在我们右边的示例中)之前,您就要在这里开始对 Eden top 进行采样。 | `-XX:CMSScheduleRemark\SamplingRatio=4` |
| 至少在新生代的入住率达到您想要安排备注的 1/4(在我们右边的示例中)之前,您就要在这里开始对 Eden top 进行采样。 | `-XX:CMSScheduleRemark\SamplingRatio=4` |
| 备注后可选择`variant=1``variant=2`验证。 | `-XX:CMSRemarkVerifyVariant=1` |
| 选择使用并行算法进行年轻空间的收集。 | `-XX:+UseParNewGC` |
| 允许对并发阶段使用多个线程。 | `-XX:+CMSConcurrentMTEnabled` |
| 设置用于并发阶段的并行线程数。 | `-XX:ConcGCThreads=2` |
| 设置要用于停止世界阶段的并行线程数。 | `-XX:ParallelGCThreads=2` |
| 您可以启用**增量 CMS****iCMS**模式。 | `-XX:+CMSIncrementalMode` |
| 您可以启用**增量 CMS****iCMS**模式。 | `-XX:+CMSIncrementalMode` |
| 如果未启用,CMS 将不会清理永久空间。 | `-XX:+CMSClassUnloadingEnabled` |
| 这允许`System.gc()`触发并发收集,而不是整个垃圾收集周期。 | `-XX:+ExplicitGCInvokes\Concurrent` |
| 这允许`System.gc()`触发永久空间的并发收集。 | `‑XX:+ExplicitGCInvokes\ConcurrentAndUnloadsClasses` |
**iCMS** mode is intended for servers with a small number of CPUs. It should not be employed on modern hardware.
**iCMS** 模式适用于CPU数量少的服务器。 不应在现代硬件上使用它。
以下是一些杂项垃圾收集选项:
| **其他垃圾收集选项** | **** |
| **其他垃圾收集选项** | **标志** |
| 这将导致 JVM 忽略应用程序的任何`System.gc()`方法调用。 | `-XX:+DisableExplicitGC` |
| 这是堆中每 MB 可用空间的生存时间(软引用),以毫秒为单位。 | `-XX:SoftRefLRU\PolicyMSPerMB=2000` |
| 这是用于在抛出`OutOfMemory`错误之前限制垃圾收集所用时间的使用策略。 | `-XX:+UseGCOverheadLimit` |
......@@ -211,14 +211,14 @@ G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域
最后,这里有一些特定于 G1 的选项。请注意,从 jvm6u26 开始,所有这些都受支持:
| **G1 垃圾回收选项** | **** |
| **G1 垃圾回收选项** | **标志** |
| 堆区域的大小。默认值是 2048,可接受的范围是 1 MiB 到 32 MiB。 | `-XX:G1HeapRegionSize=16m` |
| 这是置信系数暂停预测启发式算法。 | `-XX:G1ConfidencePercent=75` |
| 这决定了堆中的最小保留空间。 | `-XX:G1ReservePercent=5` |
| 这是每个 MMU 的垃圾收集时间——时间片(毫秒)。 | `-XX:MaxGCPauseMillis=100` |
| 这是每个 MMU 的暂停间隔时间片(毫秒)。 | `-XX:GCPauseIntervalMillis=200` |
**MiB** stands for **Mebibyte**, which is a multiple of bytes for digital information.
**MiB** 代表 **Mebibyte**,它是数字信息的字节倍数。
# 与垃圾收集相关的 Java 方法
......@@ -454,10 +454,10 @@ Java 以自动垃圾收集的方式脱颖而出,成为许多程序员的首选
让我们简要回顾一下这些方法:
* **CMS 垃圾回收:**CMS 垃圾回收算法使用多线程扫描堆内存。使用这种方法,JVM 标记要删除的对象,然后进行扫描以实际删除它们。
* **串行垃圾回收:**这种方法在单个线程上使用线程冻结模式。当垃圾收集正在进行时,它会冻结所有其他线程,直到垃圾收集操作结束。由于串行垃圾回收的线程冻结特性,它只适用于非常小的程序。
* **并行垃圾收集:**这种方法使用多个线程,但冻结应用程序中所有非垃圾收集线程,直到垃圾收集函数完成,就像串行垃圾收集算法一样
* **G1 垃圾回收:**这是垃圾回收算法,具有以下特点:
* **CMS 垃圾回收**CMS 垃圾回收算法使用多线程扫描堆内存。使用这种方法,JVM 标记要删除的对象,然后进行扫描以实际删除它们。
* **串行垃圾回收**这种方法在单个线程上使用线程冻结模式。当垃圾收集正在进行时,它会冻结所有其他线程,直到垃圾收集操作结束。由于串行垃圾回收的线程冻结特性,它只适用于非常小的程序。
* **并行垃圾收集**这种方法使用多个线程,但冻结应用程序中所有非垃圾收集线程,直到垃圾收集函数完成,就像串行垃圾收集算法一样
* **G1 垃圾回收**这是垃圾回收算法,具有以下特点:
* 与大内存堆一起使用
* 包括将内存堆分割为多个区域
* 与每个堆区域并行进行
......@@ -496,7 +496,7 @@ Oracle 在将特性、api 和库从 Java 平台的新版本中删除之前,一
以下列出的垃圾收集配置受 Java 8 平台中上述折旧的影响:
| **垃圾回收配置** | **** |
| **垃圾回收配置** | **标志** |
| 新建+CMS | `-XX:+UseParNewGC`
`-XX:UseConcMarkSweepGC` |
| 新+旧 | `-XX:+UseParNewGC` |
......@@ -509,7 +509,7 @@ Oracle 在将特性、api 和库从 Java 平台的新版本中删除之前,一
随着 Java9 的发布,JDK8 中的垃圾收集组合被删除,这些组合与控制这些组合的标志一起列出。此外,启用 CMS 前台集合的标志已被删除,并且在 JDK9 中不存在。这些标志如下所示:
| **垃圾收集组合** | **** |
| **垃圾收集组合** | **标志** |
| CMS 前景 | `-XX:+UseCMSCompactAtFullCollection` |
| CMS 前景 | `-XX+CMSFullGCsBeforeCompaction` |
| CMS 前景 | `-XX+UseCMSCollectionPassing` |
......@@ -534,7 +534,7 @@ Oracle 在将特性、api 和库从 Java 平台的新版本中删除之前,一
* 痕迹
* 发展
这不是一个详尽的目标清单。我们将在*第 14 章*“命令行标志”中更详细地讨论 Java 的统一日志模式。
这不是一个详尽的目标清单。我们将在第 14 章“命令行标志”中更详细地讨论 Java 的统一日志模式。
在日志记录上下文中,对 JVM 的更改可以分为:
......@@ -573,7 +573,7 @@ Oracle 在将特性、api 和库从 Java 平台的新版本中删除之前,一
* `uptimemillis`
* `uptimenanos`
有关这些装饰的说明,请参阅*第 14 章*、“命令行标志”。
有关这些装饰的说明,请参阅第 14 章、“命令行标志”。
# 输出
......@@ -830,7 +830,7 @@ public class GarbageCollectionExperimentThree
然后,我们将重点转向新的 Java9 平台对垃圾收集的更改。我们在 Java 中对垃圾收集的探索包括默认垃圾收集、折旧的垃圾收集组合和统一的垃圾收集日志记录。我们通过查看一些即使在最新版本的 Java 中仍然存在的垃圾收集问题来结束对垃圾收集的探索。
在下一章中,我们将研究如何使用*“Java 微基准线束”***JMH**)编写性能测试,这是一个用于编写 JVM 基准测试的 Java 线束库。
在下一章中,我们将研究如何使用 **Java 微基准线束****JMH**)编写性能测试,这是一个用于编写 JVM 基准测试的 Java 线束库。
# 问题
......
......@@ -2,7 +2,7 @@
在上一章中,我们深入回顾了垃圾收集,包括对象生命周期、垃圾收集算法、垃圾收集选项以及与垃圾收集相关的方法。我们简要介绍了 Java8 中垃圾收集的升级,重点介绍了新 Java 平台的变化。我们对 Java11 中的垃圾收集的探索包括:默认垃圾收集、折旧的垃圾收集组合、统一的垃圾收集日志记录以及持久存在的垃圾收集问题。
在本章中,我们将研究如何使用*“Java 微基准线束”***JMH**)编写性能测试,这是一个用于编写 JVM 基准测试的 Java 线束库。我们将使用 Maven 和 JMH 来帮助说明使用新 Java 平台进行微标记的威力。
在本章中,我们将研究如何使用 **Java 微基准线束****JMH**)编写性能测试,这是一个用于编写 JVM 基准测试的 Java 线束库。我们将使用 Maven 和 JMH 来帮助说明使用新 Java 平台进行微标记的威力。
具体来说,我们将讨论以下主题:
......@@ -368,7 +368,7 @@ int newValue = 3190;
# 缓存容量
**动态随机存取存储器****DRAM**非常慢。在基准测试期间,这可能会导致非常不同的性能结果。
**动态随机存取存储器****DRAM**非常慢。在基准测试期间,这可能会导致非常不同的性能结果。
有两种策略可以解决这个陷阱:
......
# 利用过程 API
在上一章中,我们了解到,*“Java 微基准线束”***JMH**是一个 Java 线束库,用于为 JVM 编写基准测试。我们尝试使用 Maven 和 JMH 编写性能测试,以帮助说明使用新 Java 平台进行微基准标记的过程。我们从微基准概述开始,然后与 Maven 深入到微基准,回顾了基准选项,最后介绍了一些避免微基准陷阱的技术。
在上一章中,我们了解到,**Java 微基准线束****JMH**是一个 Java 线束库,用于为 JVM 编写基准测试。我们尝试使用 Maven 和 JMH 编写性能测试,以帮助说明使用新 Java 平台进行微基准标记的过程。我们从微基准概述开始,然后与 Maven 深入到微基准,回顾了基准选项,最后介绍了一些避免微基准陷阱的技术。
在本章中,我们将重点介绍对`Process`类和`java.lang.ProcessHandle`API 的更新。在 Java 的早期版本中,在 Java9 之前,用 Java 管理进程是很困难的。API 不够,有些功能不够,有些任务需要以特定于系统的方式来解决。例如,在 Java8 中,让进程访问自己的**进程标识符****PID**)是一项不必要的困难任务。
......@@ -320,7 +320,7 @@ public static void main(String[] args) throws IOException,
}
```
虽然这是一个守护进程,但我们将它作为普通线程而不是守护进程线程启动。当一个线程被设置为守护进程线程时,它不会使 JVM 保持活动状态。当所有其他非守护进程线程停止时,JVM 将退出,守护进程线程将停止。在我们的例子中,我们执行的守护进程线程是保持代码运行的唯一线程。在启动之后,主线程就没有什么事情可做了,但是 JVM 应该保持活动状态,直到运算符发出 Unix`kill`命令或在命令行上按*Ctrl*+`C`将其杀死。
虽然这是一个守护进程,但我们将它作为普通线程而不是守护进程线程启动。当一个线程被设置为守护进程线程时,它不会使 JVM 保持活动状态。当所有其他非守护进程线程停止时,JVM 将退出,守护进程线程将停止。在我们的例子中,我们执行的守护进程线程是保持代码运行的唯一线程。在启动之后,主线程就没有什么事情可做了,但是 JVM 应该保持活动状态,直到运算符发出 Unix`kill`命令或在命令行上按`Ctrl + C`将其杀死。
使用 JDK 中新的`Files``Paths`类,获取指定目录中的文件列表并从文件中获取参数非常简单:
......
......@@ -22,9 +22,9 @@
在深入研究`StackWalker`之前,让我们先介绍一下 Java 栈。我们将查看基本栈信息,而不是针对`StackWalker`
Java 运行时有一个名为`Stack`的类,可以使用**后进先出****后进先出**策略来存储对象。算术表达式是使用栈计算的。如果我们在代码中加上`A``B`,首先将`A`推送到**操作数栈**上,然后将`B`推送到操作数栈上,最后执行加法运算,取操作数栈最上面的两个元素并推送结果,`A`+`B`那里。
Java 运行时有一个名为`Stack`的类,可以使用**后进先出****LIFO**策略来存储对象。算术表达式是使用栈计算的。如果我们在代码中加上`A``B`,首先将`A`推送到**操作数栈**上,然后将`B`推送到操作数栈上,最后执行加法运算,取操作数栈最上面的两个元素并推送结果,`A`+`B`那里。
JVM 是用 C 编写的,并执行调用 C 函数并从那里返回。此调用返回序列使用**本机方法栈****、**与其他 C 程序一样进行维护。
JVM 是用 C 编写的,并执行调用 C 函数并从那里返回。此调用返回序列使用**本机方法栈**与其他 C 程序一样进行维护。
最后,当 JVM 创建一个新线程时,它还会分配一个调用栈,其中包含一个帧,该帧依次包含本地变量、对上一个帧的引用以及对包含执行方法的类的引用。当调用一个方法时,会创建一个新的框架。当一个方法完成它的执行时,框架就被破坏了;换句话说,它返回或抛出一个异常。这个栈,**Java 虚拟机栈**,是`StackWalker`API 管理的栈。
......
......@@ -400,7 +400,7 @@ Doclet API 包含以下列出的接口。接口名称是不言自明的。有关
# 编译器树 API
编译树 API 在`com.sun.source.doctree`包中。它提供了几个接口来记录源代码级别的注释。这些 API 表示为**抽象语法树****AST**
编译树 API 在`com.sun.source.doctree`包中。它提供了几个接口来记录源代码级别的注释。这些 API 表示为**抽象语法树****AST**
有两个枚举,如下所示:
......@@ -446,16 +446,16 @@ Doclet API 包含以下列出的接口。接口名称是不言自明的。有关
`com.sun.source.doctree`包包含几个接口。具体见下表:
| **接口名称** | **延伸** | **用于**的树节点 | **非继承方法** |
| `AttributeTree` | `DocTree` | HTML 元素 | `getName()``getValue()``getValueKind()` |
| **接口名称** | **扩展** | **所用于的树节点** | **非继承方法** |
| `AttributeTree` | `DocTree` | HTML 元素 | `getName(), getValue(), getValueKind()` |
| `AuthorTree` | `BlockTagTree, DocTree` | `@author`块标签 | `getName()` |
| `BlockTagTree` | `DocTree` | 不同类型的块标记的基类 | `getTagName()` |
| `CommentTree` | `DocTree` | 带有以下 HTML 标记的嵌入式 HTML 注释-`<!--text-->` | `getBody()` |
| `DeprecatedTree` | `BlockTagTree` | `@deprecated`块标签 | `getBody()` |
| `DocCommentTree` | `DocTree` | 正文块标记 | `getBlockTags()``getBody()``getFirstSentence()` |
| `DocCommentTree` | `DocTree` | 正文块标记 | `getBlockTags(), getBody(), getFirstSentence()` |
| `DocRootTree` | `InlineTagTree` | `@docroot`内联标签 | 不适用 |
| `DocTree` | 不适用 | 所有用户的通用接口 | `accept(DocTreeVisitor<R,D>visitor,Ddata)``getKind()` |
| `DocTreeVisitor<R,P>` | 药方: | `R`=访问者方法的返回类型;`P`=附加参数的类型 | `visitAttribute(AttributeTree node, P p)``visitAuthor(AuthorTree node, P p)``visitComment(CommentTree node, P p)``visitDeprecated(DeprecatedTree node, P p)``visitDocComment(DocCommentTree node, P p)``visitDocRoot(DocRootTree node, P p)``visitEndElement(EndElementTree node, P p)``visitEntity(EntityTree node, P p)``visitErroneous(ErroneousTree node, P p)``visitIdentifier(IdentifierTree node, P p)``visitInheritDoc(InheritDocTree node, P p)``visitLink(LinkTree node, P p)``visitLiteral(LiteralTree node, P p)``visitOther(DocTree node, P p)``visitParam(ParamTree node, P p)``visitReference(ReferenceTree node, P p)``visitReturn(ReturnTree node, P p)``visitSee(SeeTree node, P p)``visitSerial(SerialTree node, P p)``visitSerialData(SerialDataTree node, P p)``visitSerialField(SerialFieldTree node, P p)``visitSince(SinceTree node, P p)``visitStartElement(StartElementTree node, P p)``visitText(TextTree node, P p)``visitThrows(ThrowsTree node, P p)``visitUnknownBlockTag(UnknownBlockTagTree node, P p)``visitUnknownInlineTag(UnknownInlineTagTree node, P p)``visitValue(ValueTree node, P p)``visitVersion(VersionTree node, P p) ` |
| `DocTree` | 不适用 | 所有用户的通用接口 | `accept(DocTreeVisitor<R,D>visitor,Ddata), getKind()` |
| `DocTreeVisitor<R,P>` | 药方: | `R`=访问者方法的返回类型;`P`=附加参数的类型 | `visitAttribute(AttributeTree node, P p)``visitAuthor(AuthorTree node, P p)``visitComment(CommentTree node, P p)``visitDeprecated(DeprecatedTree node, P p)``visitDocComment(DocCommentTree node, P p)``visitDocRoot(DocRootTree node, P p)``visitEndElement(EndElementTree node, P p)``visitEntity(EntityTree node, P p)``visitErroneous(ErroneousTree node, P p)``visitIdentifier(IdentifierTree node, P p)``visitInheritDoc(InheritDocTree node, P p)``visitLink(LinkTree node, P p)``visitLiteral(LiteralTree node, P p)``visitOther(DocTree node, P p)``visitParam(ParamTree node, P p)``visitReference(ReferenceTree node, P p)``visitReturn(ReturnTree node, P p)``visitSee(SeeTree node, P p)``visitSerial(SerialTree node, P p)``visitSerialData(SerialDataTree node, P p)``visitSerialField(SerialFieldTree node, P p)``visitSince(SinceTree node, P p)``visitStartElement(StartElementTree node, P p)``visitText(TextTree node, P p)``visitThrows(ThrowsTree node, P p)``visitUnknownBlockTag(UnknownBlockTagTree node, P p)``visitUnknownInlineTag(UnknownInlineTagTree node, P p), visitValue(ValueTree node, P p), visitVersion(VersionTree node, P p) ` |
| `EndElementTree` | `DocTree` | HTML 元素`</name>`的结尾 | `getName()` |
| `EntityTree` | `DocTree` | HTML 实体 | `getName()` |
| `ErroneousTree` | `TextTree` | 这是用于格式错误的文本 | `getDiagnostic()` |
......@@ -464,15 +464,15 @@ Doclet API 包含以下列出的接口。接口名称是不言自明的。有关
| `InlineTagTree` | `DocTree` | 内联标记的公共接口 | `getTagName()` |
| `LinkTree` | `InlineTagTree` | `@link``@linkplan`内联标签 | `getLabel(), getReference()` |
| `LiteralTree` | `InlineTagTree` | `@literal``@code`内联标签 | `getBody()` |
| `ParamTree` | `BlockTagTree` | `@param`块标签 | `getDescription()``getName()``isTypeParameter()` |
| `ParamTree` | `BlockTagTree` | `@param`块标签 | `getDescription(), getName(), isTypeParameter()` |
| `ReferenceTree` | `DocTree` | 用于引用 Java 语言元素 | `getSignature()` |
| `ReturnTree` | `BlockTagTree` | `@return`块标签 | `getDescription()` |
| `SeeTree` | `BlockTagTree` | `@see`块标签 | `getReference()` |
| `SerialDataTree` | `BlockTagTree` | `@serialData`块标签 | `getDescription()` |
| `SerialFieldTree` | `BlockTagTree` | `@serialData`块标签和`@serialField`字段名称和说明 | `getDescription()``getName()``getType()` |
| `SerialFieldTree` | `BlockTagTree` | `@serialData`块标签和`@serialField`字段名称和说明 | `getDescription(), getName(), getType()` |
| `SerialTree` | `BlockTagTree` | `@serial`块标签 | `getDescription()` |
| `SinceTree` | `BlockTagTree` | `@since`块标签 | `getBody()` |
| `StartElementTree` | `DocTree` | HTML 元素`< name [attributes] [/] >`的开头 | `getAttributes()``getName()``isSelfClosing()` |
| `StartElementTree` | `DocTree` | HTML 元素`< name [attributes] [/] >`的开头 | `getAttributes(), getName(), isSelfClosing()` |
| `TextTree` | `DocTree` | 纯文本 | `getBody()` |
| `ThrowsTree` | `BlockTagTree` | `@exception``@throws`块标签 | `getDescription(), getExceptionname()` |
| `UnknownBlockTagTree` | `BlockTagTree` | 无法识别的内联标记 | `getContent()` |
......@@ -737,7 +737,7 @@ Javadoc 搜索功能通过使用 Camel Case search 提供了一个很好的快
# 对多 JRE 功能的更改
**mJRE**(简称**Multiple JRE**)特性以前用于指定启动应用程序的特定 JRE 版本或版本范围。我们可以通过命令行选项`-version`或者通过 JAR 文件清单中的一个条目来实现这一点。以下流程图说明了根据我们的选择所发生的情况:
**mJRE**(简称 **Multiple JRE**)特性以前用于指定启动应用程序的特定 JRE 版本或版本范围。我们可以通过命令行选项`-version`或者通过 JAR 文件清单中的一个条目来实现这一点。以下流程图说明了根据我们的选择所发生的情况:
![](img/e96e35e9-c105-4eaf-b741-0e69b856ac91.png)
......@@ -951,7 +951,7 @@ JAR 文件结构
# Java 级 JVM 编译器接口
基于 Java 的**JVM 编译器接口****JVMCI**)允许 Java 编译器(必须是用 Java 编写的)被 JVM 用作动态编译器。
基于 Java 的 **JVM 编译器接口****JVMCI**)允许 Java 编译器(必须是用 Java 编写的)被 JVM 用作动态编译器。
JVMCI 需求背后的原因是,它将是一个高度优化的编译器,不需要低级语言特性。一些 JVM 子系统需要低级功能,比如垃圾收集和字节码解释。所以,JVMCI 是用 java 编写的,而不是用 C 或 C++编写的。这提供了 Java 一些最强大功能的附带好处,例如:
......@@ -1165,7 +1165,7 @@ public @interface SwingContainer {
下表提供了`java.util.logging`包类,并简要说明了每个类在日志功能和管理方面提供的内容:
| **** | **定义** | **说明** |
| **** | **定义** | **说明** |
| `ConsoleHandler` | `public class ConsoleHandler extends StreamHandler` | 将日志记录发布到`System.err` |
| `ErrorManager` | `public class ErrorManager extends Object` | 用于在日志记录期间处理错误 |
| `FileHandler` | `public class FileHandler extends StreamHandler` | 文件记录 |
......@@ -1251,11 +1251,11 @@ Java9 提供的新的 XML 目录 API 遵循 OASISXML 目录标准 v1.1。以下
因为新的 XML 目录 API 是公共的,所以 Java 9 之前的内部目录解析器已经被删除,因为它不再是必需的。
# 收藏
# 集合
Java 编程语言不支持集合文本。将此功能添加到 Java 平台是在 2013 年提出的,并在 2016 年重新进行了讨论,但它只是作为一个研究建议而被公开,并不是为了将来的实现。
Oracle 对 collection literal 的定义是[**一种语法表达式形式,其计算结果是聚合类型,例如数组、列表或映射**](http://openjdk.java.net/jeps/186)
Oracle 对集合字面值的定义是[**一种语法表达式形式,其计算结果是聚合类型,例如数组、列表或映射**](http://openjdk.java.net/jeps/186)
当然,直到 Java9 发布。据报道,在 Java 编程语言中实现集合文字具有以下好处:
......
......@@ -22,7 +22,7 @@ IDE 软件包就足够了。来自 JetBrains 的 IntelliJ IDEA 用于与本章
# 数据报传输层安全
**数据报传输层安全****DTLS**)是一种通信协议。该协议为基于数据报的应用程序提供了一个安全层。DTLS 允许安全通信,基于**传输层安全****TLS**协议。嵌入式安全性有助于确保消息不被伪造、篡改或窃听。
**数据报传输层安全****DTLS**)是一种通信协议。该协议为基于数据报的应用程序提供了一个安全层。DTLS 允许安全通信,基于**传输层安全****TLS**协议。嵌入式安全性有助于确保消息不被伪造、篡改或窃听。
让我们回顾一下相关术语:
......@@ -51,7 +51,7 @@ DTLS 协议 1.0 版于 2006 年建立,为数据报协议提供通信安全。
* 提供安全保障
* 保留了 DLS 协议的数据报语义
下图说明了**传输层****SSL/TLS**协议层的总体架构中的位置以及每层的协议:
下图说明了**传输层** **SSL/TLS** 协议层的总体架构中的位置以及每层的协议:
![](img/b8bdfd37-c99d-4798-b658-a7f8093e5d10.png)
......@@ -77,7 +77,7 @@ DTLS 协议版本 1.0 提供了主要覆盖区域的详细规范,如下所示
* 超时和重传
* 数据包丢失
* **路径最大转换单元(PMTU)**发现
* **路径最大转换单元**(PMTU)发现
* 记录层
* 记录有效负载保护
* 重新排序
......@@ -86,7 +86,7 @@ DTLS 协议版本 1.0 提供了主要覆盖区域的详细规范,如下所示
# DTLS 协议版本 1.2
DTLS 协议 1.2 版于 2012 年 1 月发布,版权归**互联网工程任务组****IETF**所有。本节共享说明在版本 1.2 中所做更改的代码示例。
DTLS 协议 1.2 版于 2012 年 1 月发布,版权归**互联网工程任务组****IETF**所有。本节共享说明在版本 1.2 中所做更改的代码示例。
下面的代码演示了 TLS1.2 握手消息头。此格式支持:
......@@ -122,7 +122,7 @@ struct
} Handshake;
```
本节中的代码来自 DTLS 协议文件,并根据 IETF*有关 IETF 文件*的法律规定重新发布。
本节中的代码来自 DTLS 协议文件,并根据 IETF *有关文件*的法律规定重新发布。
记录层包含我们打算发送到记录中的信息。信息开始于`DTLSPlaintext`结构中,然后在握手发生之后,记录被加密,并且可以通过通信流发送。记录层格式遵循 1.2 版中的新字段,并在代码注释中用`// New field`注释,如下所示:
......@@ -226,11 +226,11 @@ dtlsapi 的 Java 实现是独立于传输的,而且是轻量级的。API 的
DTLS 是一种协议,用于在将数据传递到传输层协议之前保护来自应用层的数据。DTLS 是加密和传输实时数据的一个很好的解决方案。应谨慎行事,以免在应用程序实现中引入漏洞。以下是在 Java 应用程序中实现 DTL 的一些安全注意事项:
* 实现 dtlsv1.2,因为它是 Java 支持的最新版本。
* 避免**Rivest Shamir Adleman****RSA**)加密。如果必须使用 RSA,请为私钥添加额外的安全性,因为这是 RSA 的一个弱点。
* 当使用**椭圆曲线 Diffie-Hellman****ECDH**匿名密钥协商协议时,使用 192 位或更多。192 位的值基于**美国国家标准与技术研究所****美国国家标准与技术研究所**)的建议。
* 强烈建议使用带有相关数据(**AEAD**)的**认证加密,这是一种加密形式。AEAD 为加密和解密的数据提供真实性、机密性和完整性保证。**
* 避免 **Rivest Shamir Adleman****RSA**)加密。如果必须使用 RSA,请为私钥添加额外的安全性,因为这是 RSA 的一个弱点。
* 当使用**椭圆曲线 Diffie-Hellman****ECDH**)匿名密钥协商协议时,使用 192 位或更多。192 位的值基于**美国国家标准与技术研究所****NIST**)的建议。
* 强烈建议使用**带有相关数据的认证加密****AEAD**),这是一种加密形式。AEAD 为加密和解密的数据提供真实性、机密性和完整性保证。
* 在实现握手重新协商时,始终实现`renegotiation_info`扩展。
* 在使用通信协议的所有 Java 应用程序中建立**前向保密****FS**功能。实现 FS 可以确保过去的会话加密密钥不会在长期加密密钥受损时受损。理想情况下,**完美前向保密****PFS**),其中每个密钥仅对单个会话有效,将用于要求传输数据最大安全性的 Java 应用程序中。
* 在使用通信协议的所有 Java 应用程序中建立**前向保密****FS**功能。实现 FS 可以确保过去的会话加密密钥不会在长期加密密钥受损时受损。理想情况下,**完美前向保密****PFS**),其中每个密钥仅对单个会话有效,将用于要求传输数据最大安全性的 Java 应用程序中。
# 创建 PKCS12 密钥库
......@@ -403,9 +403,9 @@ try {
# Java 9、10 和 11 中的 PKCS12 默认值
在 Java9 之前,默认的`KeyStore`类型是**Java 密钥库****JKS**)。当前的 Java 平台使用 PKCS 作为默认的`KeyStore`类型,更确切地说,PKCS12。
在 Java9 之前,默认的`KeyStore`类型是 **Java 密钥库****JKS**)。当前的 Java 平台使用 PKCS 作为默认的`KeyStore`类型,更确切地说,PKCS12。
**PKCS** is an acronym for **Public Key Cryptography Standards**.
**PKCS** **公钥密码标准**的首字母缩写。
与 JKS 相比,PKCS 的这种变化提供了更强的加密算法。正如您所料,jdk9、10 和 11 仍然与 JKS 兼容,以支持以前开发的系统。
......@@ -496,7 +496,7 @@ checkPackageAccess 方法的异常
# TLS 应用层协议协商扩展
`javax.net.ssl`包最近进行了增强,支持**传输层安全****TLS****ALPN**(简称**应用层协议协商**)扩展。此扩展允许 TLS 连接的应用程序协议协商。
`javax.net.ssl`包最近进行了增强,支持**传输层安全扩展****TLS ALPN**)(简称**应用层协议协商**。此扩展允许 TLS 连接的应用程序协议协商。
# TLS ALPN 扩展
......@@ -596,7 +596,7 @@ struct {
# 散列
**Galois HASH****GHASH**)和**RSA**是密码系统哈希算法。哈希是由文本字符串生成的固定长度的字符串或数字。算法,更具体地说是散列算法,被设计成这样的结果散列不能被反向工程。我们使用散列存储用 salt 生成的密码。
**Galois HASH****GHASH**)和 **RSA** 是密码系统哈希算法。哈希是由文本字符串生成的固定长度的字符串或数字。算法,更具体地说是散列算法,被设计成这样的结果散列不能被反向工程。我们使用散列存储用 salt 生成的密码。
在密码学中,salt 是一种随机数据,用作哈希函数生成密码的输入。盐有助于防止彩虹表攻击和字典攻击。
......@@ -606,7 +606,7 @@ struct {
哈希概述
如您所见,**散列算法**被输入明文和**Salt**,从而产生一个新的散列密码并存储**Salt**。以下是带有示例输入/输出的相同图形,以演示功能:
如您所见,**散列算法**被输入明文和**盐**,从而产生一个新的散列密码并存储**盐**。以下是带有示例输入/输出的相同图形,以演示功能:
![](img/ce245ee5-0a14-442b-9903-34da1912a923.png)
......@@ -638,14 +638,14 @@ OCSP 装订过程涉及多个组件和有效性检查。下图说明了 OCSP 装
**TLS 的 OCSP 装订**通过 TLS 证书状态请求扩展实现 OCSP 装订。OSCP 装订检查 X.509 证书的有效性。
X.509 证书是使用 X509**公钥基础设施****PKI**的数字证书。
X.509 证书是使用 X509 **公钥基础设施****PKI**的数字证书。
在 Java 9 之前,可以在客户端启用证书有效性检查(实际上,检查证书是否已被吊销),但效率低下:
* OCSP 响应程序性能瓶颈
* 基于多通道的性能下降
* 如果在客户端执行 OCSP 检查,则性能会进一步降低
* False**在浏览器未连接到 OCSP 响应程序时**失败
* **在浏览器未连接到 OCSP 响应程序时**失败
* OCSP 响应程序易受拒绝服务攻击
用于 TLS 的新 OCSP 装订包括 Java 9、10 和 11 的以下系统属性更改:
......@@ -671,7 +671,7 @@ X.509 证书是使用 X509**公钥基础设施**(**PKI**的数字证书。
* 可以将该值设置为零以禁用缓存的生存期
* `jdk.tls.stapling.responderURI`
* 默认设置:无
* 可以为没有**权限信息访问****AIA**扩展的证书设置默认 URI
* 可以为没有**权限信息访问****AIA**扩展的证书设置默认 URI
* 除非设置了`jdk.tls.stapling.Override`属性,否则不重写 AIA 扩展
* `jdk.tls.stapling.respoderOverride`
* 默认设置:false
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册