Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenDocCN
apachecn-java-zh
提交
bbec2994
A
apachecn-java-zh
项目概览
OpenDocCN
/
apachecn-java-zh
11 个月 前同步成功
通知
5
Star
53
Fork
13
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
apachecn-java-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
bbec2994
编写于
5月 12, 2021
作者:
W
wizardforcel
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
2021-05-12 21:41:16
上级
c6093bbf
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
41 addition
and
41 deletion
+41
-41
new/master-java11/05.md
new/master-java11/05.md
+7
-7
new/master-java11/06.md
new/master-java11/06.md
+2
-2
new/master-java11/07.md
new/master-java11/07.md
+9
-9
new/master-java11/08.md
new/master-java11/08.md
+5
-5
new/master-java11/09.md
new/master-java11/09.md
+5
-5
new/master-java11/10.md
new/master-java11/10.md
+13
-13
未找到文件。
new/master-java11/05.md
浏览文件 @
bbec2994
...
...
@@ -571,7 +571,7 @@ public class DependencyTest {
正如您在本章前面所读到的,大多数内部 API 都是强封装的。如前所述,在更新源代码时,您可能会寻找替换 API。当然,这并不总是可行的。您可以在运行时使用
`--add-opens`
选项、使用
`--add-exports`
选项和
`--permit-illegal-access`
命令行选项来采取另外三种方法。让我们看看每一个选项。
#
--add 打开
选项
#
`--add-opens`
选项
您可以使用
`--add-opens`
运行时选项来允许您的代码访问非公共成员。这可以称为
**深反射**
。进行这种深度反思的图书馆能够访问所有成员,包括私人和公共。要授予这种类型的代码访问权限,可以使用
`--add-opens`
选项。语法如下:
...
...
@@ -581,7 +581,7 @@ public class DependencyTest {
这允许给定的模块打开指定的包。使用此选项时,编译器不会产生任何错误或警告。
#
--add exports
选项
#
`--add-exports`
选项
您可以使用
`--add-exports`
来破坏封装,这样您就可以使用默认为不可访问的内部 API。语法如下:
...
...
@@ -599,7 +599,7 @@ public class DependencyTest {
只有在认为绝对必要的情况下才应使用
`--add-exports`
命令行选项。除短期解决方案外,不建议使用此选项。常规使用它的危险在于,对引用的内部 API 的任何更新都可能导致代码无法正常工作。
#
--permit 非法访问
选项
#
`--permit-illegal-access`
选项
打破封装的第三个选择是使用
`--permit-illegal-access`
选项。当然,谨慎的做法是与第三方库创建者核实是否有更新的版本。如果这不是一个选项,那么您可以使用
`--permit-illegal-access`
非法访问要在类路径上实现的操作。由于这里的操作非常非法,每次发生这些操作时,您都会收到警告。
...
...
@@ -707,7 +707,7 @@ Java 中删除的另外两个内容如下:
# 序列化小程序
Java 不再支持将 Applet 作为序列化对象进行部署。过去,
a
pplet 被部署为序列化对象,以补偿压缩速度慢和 JVM 性能问题。在当前的 Java 平台上,压缩技术是先进的,JVM 具有良好的性能。
Java 不再支持将 Applet 作为序列化对象进行部署。过去,
A
pplet 被部署为序列化对象,以补偿压缩速度慢和 JVM 性能问题。在当前的 Java 平台上,压缩技术是先进的,JVM 具有良好的性能。
如果尝试将小程序部署为序列化对象,则在启动小程序时,对象属性和参数标记将被忽略。从 Java9 开始,您可以使用标准部署策略部署小程序。
...
...
@@ -721,7 +721,7 @@ JNLP 规范在 Java9 中进行了更新。以下章节详细介绍了四个具
# 嵌套资源
以前支持将组件扩展与 Java 或
j2se
元素中的嵌套资源一起使用,但规范中没有对此进行说明。规范现在已经更新以反映这种支持。先前的规范如下:
以前支持将组件扩展与 Java 或
J2SE
元素中的嵌套资源一起使用,但规范中没有对此进行说明。规范现在已经更新以反映这种支持。先前的规范如下:
*不能将 Java 元素指定为资源的一部分。*
...
...
@@ -729,7 +729,7 @@ JNLP 规范在 Java9 中进行了更新。以下章节详细介绍了四个具
组件扩展中的 Java 元素不会控制所使用的 Java 版本,但可以使用包含嵌套资源元素的 Java 版本,并且只有在使用与第 4.6 节中指定的给定版本匹配的 Java 版本时,才可以使用这些资源。
这个特定的更改确保扩展 JLP 文件必须具有 Java 或
j2se
资源,并且这些资源不会指定使用什么 JRE。使用指定版本时允许嵌套资源。
这个特定的更改确保扩展 JLP 文件必须具有 Java 或
J2SE
资源,并且这些资源不会指定使用什么 JRE。使用指定版本时允许嵌套资源。
# FX XML 扩展
...
...
@@ -904,7 +904,7 @@ Maven 可以与 Eclipse(M2Eclipse)、JetBrains IntelliJ IDEA 和 netbeansIDE
*
您可以很容易地解析 Maven 依赖关系(您可以直接从 Eclipse 执行此操作,而不必安装本地 Maven 存储库)
*
您可以自动下载所需的依赖项(从远程 Maven 存储库)
*
您可以使用软件向导创建新的 Maven 项目,创建
`pom.xml`
文件,并为普通 Java 项目启用 Maven 支持
*
Use
可以对 Maven 的远程存储库执行快速的依赖性搜索
*
您
可以对 Maven 的远程存储库执行快速的依赖性搜索
# 获取 Eclipse IDE
...
...
new/master-java11/06.md
浏览文件 @
bbec2994
...
...
@@ -65,7 +65,7 @@ jshell <options> <load files>
|
`/edit`
| 使用此命令,您可以使用
`name`
或
`id`
引用编辑源条目语法如下:
`/edit <name or id>`
|
|
`/env`
| 这个强大的命令允许您查看或更改评估上下文语法如下:
`/env [-class-path <path>] [-module-path <path>] [-add-modules <modules>]`
|
|
`/exit`
| 此命令用于退出 JShell。语法是简单的
`/exit`
,没有任何可用的选项或参数。 |
|
`/history`
|
history
命令提供您所键入内容的历史记录。语法是简单的
`/history`
,没有任何可用的选项或参数。 |
|
`/history`
|
`history`
命令提供您所键入内容的历史记录。语法是简单的
`/history`
,没有任何可用的选项或参数。 |
|
`/<id>`
| 此命令用于通过引用
`id`
重新运行以前的代码段。语法如下:
`/<id>`
您也可以使用
`/-<n>`
引用前
`n`
个代码段来运行特定的代码段。 |
|
`/imports`
| 可以使用此命令列出导入的项目。语法为
`/imports`
,不接受任何选项或参数。 |
|
`/list`
| 此命令将列出您键入的源代码。语法如下:
`/list [<name or id> | -all | -start]`
|
...
...
@@ -176,7 +176,7 @@ jshell <options> <load files>
![](
img/7e1da0de-02ab-4b9c-8a69-8452b355def4.png
)
作为一个例子,让我们浏览一下
truncation
设置,该设置要求在每个输出行上显示多少个字符。使用
`/set truncation`
命令,如下面的屏幕截图所示,显示当前的截断设置:
作为一个例子,让我们浏览一下
`truncation`
设置,该设置要求在每个输出行上显示多少个字符。使用
`/set truncation`
命令,如下面的屏幕截图所示,显示当前的截断设置:
![](
img/d6c42080-2734-48f5-a805-d520602e9154.png
)
...
...
new/master-java11/07.md
浏览文件 @
bbec2994
...
...
@@ -88,7 +88,7 @@ JVM 可以使用几种垃圾收集算法或类型。在本节中,我们将介
# 标记和扫描
Java 的初始垃圾收集算法
mark and sweep
使用了一个简单的两步过程:
Java 的初始垃圾收集算法
标记清除
使用了一个简单的两步过程:
1.
第一步,标记,是遍历所有具有可访问引用的对象,将这些对象标记为活动对象
...
...
@@ -187,7 +187,7 @@ G1 垃圾收集算法还根据要收集的垃圾最多的区域来确定区域
| 您可以使用此命令在备注阶段之前强制年轻的集合。 |
`-XX:+CMSScavengeBeforeRemark`
|
| 如果使用的 Eden 低于阈值,则使用此选项可防止出现计划注释。 |
`-XX:+CMSScheduleRemark\EdenSizeThreshold`
|
| 设置您希望 CMS 尝试和安排备注暂停的 Eden 占用百分比。 |
`-XX:CMSScheduleRemark\EdenPenetration=20`
|
| 至少在新生代的入住率达到您想要安排备注的 1/4(在我们右边的示例中)之前,您就要在这里开始对 Eden
top
进行采样。 |
`-XX:CMSScheduleRemark\SamplingRatio=4`
|
| 至少在新生代的入住率达到您想要安排备注的 1/4(在我们右边的示例中)之前,您就要在这里开始对 Eden
顶部
进行采样。 |
`-XX:CMSScheduleRemark\SamplingRatio=4`
|
| 备注后可选择
`variant=1`
或
`variant=2`
验证。 |
`-XX:CMSRemarkVerifyVariant=1`
|
| 选择使用并行算法进行年轻空间的收集。 |
`-XX:+UseParNewGC`
|
| 允许对并发阶段使用多个线程。 |
`-XX:+CMSConcurrentMTEnabled`
|
...
...
@@ -283,7 +283,7 @@ public class GCVerificationTest {
除了使用
`System.gc()`
方法调用垃圾收集器之外,还有一种替代方法。在我们的例子中,我们可以使用
`myRuntime.gc()`
,我们早期的单例例子。
#
finalize()
方法
#
`finalize()`
方法
你可以把 Java 的垃圾收集器想象成死亡贩子。当它从记忆中删除某些东西时,它就消失了。这个所谓的死亡贩子并非没有同情心,因为它为每个方法提供了他们最后的遗言。对象通过
`finalize()`
方法给出他们的最后一句话。如果一个对象有一个
`finalize()`
方法,垃圾收集器会在移除该对象和释放相关内存之前调用它。该方法不带参数,返回类型为
`void`
。
...
...
@@ -640,7 +640,7 @@ Java9 日志框架支持三种类型的输出:
# gc 标签
我们可以使用带有
`-Xlog`
选项的
`gc`
标记来通知 JVM 在
info
级别只记录
`gc`
标记的项。您还记得,这类似于使用
`-XX:+PrintGC`
。使用这两个选项,JVM 将为每个垃圾收集操作记录一行。
我们可以使用带有
`-Xlog`
选项的
`gc`
标记来通知 JVM 在
`info`
级别只记录
`gc`
标记的项。您还记得,这类似于使用
`-XX:+PrintGC`
。使用这两个选项,JVM 将为每个垃圾收集操作记录一行。
值得注意的是,
`gc`
标签并非单独使用,而是建议与其他标签一起使用。
...
...
@@ -658,7 +658,7 @@ log_<level>(Tag1[,...])(fmtstr, ...)
log_debug
(
gc
,
classloading
)(
"Number of objects loaded: %d."
,
object_count
)
```
下面的示例
skeleton
`log`
宏显示了如何使用新的 Java 日志框架来创建脚本,以提高日志记录的逼真度:
下面的示例
框架
`log`
宏显示了如何使用新的 Java 日志框架来创建脚本,以提高日志记录的逼真度:
```
java
LogHandle
(
gc
,
rt
,
classunloading
)
log
;
...
...
@@ -705,18 +705,18 @@ if (log.is_trace()) {
正如本章前面提到的,G1 垃圾收集器自 Java9 以来一直是默认的垃圾收集器。G1 垃圾收集器的效率之一是它使用并发垃圾收集而不是完全收集。有时会实现完全垃圾收集,通常是并发垃圾收集速度不够快。注意,在 Java9 之前,并行收集器是默认的垃圾收集器,是一个并行的完全垃圾收集器。
对于 Java10,
g1full 垃圾回收器被转换为 parallel,以减轻对使用 full
垃圾回收的开发人员的任何负面影响。将用于 G1 完全垃圾回收的 mark-week 压缩算法并行化。
对于 Java10,
G1Full 垃圾回收器被转换为并行,以减轻对使用完全
垃圾回收的开发人员的任何负面影响。将用于 G1 完全垃圾回收的 mark-week 压缩算法并行化。
# Epsilon–任意低开销 GC
Java 的最新版本
version11 附带了一个负责内存分配的被动 GC。这个 GC 的被动性质(称为 epsilongc
)表明它不执行垃圾收集;相反,它继续分配内存,直到堆上没有剩余空间为止。这时,JVM 关闭。
Java 的最新版本
11 附带了一个负责内存分配的被动 GC。这个 GC 的被动性质(称为 EpsilonGC
)表明它不执行垃圾收集;相反,它继续分配内存,直到堆上没有剩余空间为止。这时,JVM 关闭。
为了启用 Epsilon GC,我们使用以下任一方法:
*
`-XX:+UseEpsilonGC`
*
`-XX:+UseNoGC`
epsilongc
的使用主要出现在测试中,由于缺乏垃圾收集,它的开销很低,提高了测试效率
EpsilonGC
的使用主要出现在测试中,由于缺乏垃圾收集,它的开销很低,提高了测试效率
# 长期存在的问题
...
...
@@ -750,7 +750,7 @@ public class GarbageCollectionExperimentOne {
}
```
如在代码注释中所示,一旦
string object
引用变量设置为
`null`
,在本例中使用
`junk = null;`
语句,对象就可以进行垃圾收集。
如在代码注释中所示,一旦
字符串对象
引用变量设置为
`null`
,在本例中使用
`junk = null;`
语句,对象就可以进行垃圾收集。
在我们的下一个示例中,我们将通过将对象的引用变量设置为指向另一个对象来放弃该对象。正如您在以下代码中看到的,这导致第一个对象可用于垃圾收集:
...
...
new/master-java11/08.md
浏览文件 @
bbec2994
...
...
@@ -37,7 +37,7 @@ IDE 软件包就足够了。来自 JetBrains 的 IntelliJ IDEA 用于与本章
Oracle 的文档表明,最理想的 JMH 用例是使用依赖于应用程序 JAR 文件的 Maven 项目。他们进一步建议微标记通过命令行进行,而不是从 IDE 中进行,因为这可能会影响结果。
Maven,也称为
apachem
aven,是一个项目管理和理解工具,我们可以使用它来管理我们的应用程序项目构建、报告和文档。
Maven,也称为
ApacheM
aven,是一个项目管理和理解工具,我们可以使用它来管理我们的应用程序项目构建、报告和文档。
为了使用 JMH,我们将使用字节码处理器(注释)来生成基准代码。
...
...
@@ -51,7 +51,7 @@ Maven,也称为 apachemaven,是一个项目管理和理解工具,我们可
# 动手实验
现在我们已经安装了
eclipseo
xygen,您可以运行一个快速测试来确定 JMH 是否在您的开发计算机上工作。首先创建一个新的 Maven 项目,如以下屏幕截图所示:
现在我们已经安装了
EclipseO
xygen,您可以运行一个快速测试来确定 JMH 是否在您的开发计算机上工作。首先创建一个新的 Maven 项目,如以下屏幕截图所示:
![](
img/4889a0b4-6ec1-4e9a-b8e8-d7b61065eaf9.png
)
...
...
@@ -97,7 +97,7 @@ JMH 测试结果
# Maven 微基准
开始使用 JMH 的一种方法是使用
jmhm
aven 原型。第一步是创建一个新的 JMH 项目。在我们系统的命令提示符下,我们将输入
`mvn`
命令,然后输入一组长参数,以创建一个新的 Java 项目和必要的 Maven
`pom.xml`
文件:
开始使用 JMH 的一种方法是使用
JMHM
aven 原型。第一步是创建一个新的 JMH 项目。在我们系统的命令提示符下,我们将输入
`mvn`
命令,然后输入一组长参数,以创建一个新的 Java 项目和必要的 Maven
`pom.xml`
文件:
```
java
mvn
archetype:
generate
-
DinteractiveMode
=
false
-
DarchetypeGroupId
=
org
.
openjdk
.
jmh
-
DarchetypeArtifactId
=
jmh
-
java
-
benchmark
-
archetype
-
DgroupId
=
com
.
packt
-
DartifactId
=
chapter8
-
benchmark
-
Dversion
=
1.0
...
...
@@ -334,7 +334,7 @@ if (value != null) {
.
.
.
```
在我们前面的示例中,由于变量值永远不会等于
null
,因此永远不会到达标识为死代码的行。在条件语句
`if`
计算变量之前,它被设置为
`10`
。
在我们前面的示例中,由于变量值永远不会等于
`null`
,因此永远不会到达标识为死代码的行。在条件语句
`if`
计算变量之前,它被设置为
`10`
。
问题是,为了消除死代码,有时可以删除基准测试代码。
...
...
@@ -355,7 +355,7 @@ int newValue = 3190;
对于这个陷阱,有一个建议的策略:
*
使用
jmh
API 支持来确保您的基准测试代码不会被消除
*
使用
JMH
API 支持来确保您的基准测试代码不会被消除
# 运行间差异
...
...
new/master-java11/09.md
浏览文件 @
bbec2994
...
...
@@ -8,7 +8,7 @@
*
引入流程
*
使用
`ProcessHandle`
接口
*
查看示例
process controller
应用程序
*
查看示例
进程控制器
应用程序
# 技术要求
...
...
@@ -34,7 +34,7 @@ IDE 软件包就足够了。来自 JetBrains 的 IntelliJ IDEA 用于与本章
程序可以准备在收到此类请求时停止。例如,Java 应用程序可以添加一个调用
`Runtime.getRuntime().addShutdownHook(Thread t)`
方法的
`Thread`
对象。传递的线程应该在进程被要求停止时启动,这样线程就可以执行程序退出前必须执行的所有任务。不幸的是,不能保证线程会真正启动,这取决于实际的实现。
# 使用
ProcessHandle
接口
# 使用
`ProcessHandle`
接口
Java9 中引入了两个支持处理操作系统进程的新接口-
`ProcessHandle`
和
`ProcessHandle.Info`
。
...
...
@@ -159,7 +159,7 @@ public class ChildLister {
列出子进程与列出子进程非常相似,但是如果我们调用
`processHandle.descendants()`
方法,那么
`Stream`
将包含所有子进程以及这些进程的子进程,依此类推。
以下程序以命令行参数启动命令提示,以便它们也生成另一个终止的
【T0”
:
以下程序以命令行参数启动命令提示,以便它们也生成另一个终止的
`cmd.exe`
:
```
java
import
java.io.IOException
;
...
...
@@ -286,7 +286,7 @@ public class TerminateAProcessAfterWaiting {
示例代码将睡眠时间设置为 10 秒。这是一个更明显的时间段。运行两次代码并删除破坏进程的行会导致打印速度慢得多。实际上,测量和打印的运行时间也会显示终止进程会产生影响。
# 查看示例
process controller
应用程序
# 查看示例
进程控制器
应用程序
最后一节提供了一个示例过程控制应用程序来演示本章的内容。应用程序的功能非常简单。它从一系列配置文件参数中读取如何启动某些进程,然后,如果其中任何进程停止,它将尝试重新启动进程。
...
...
@@ -390,7 +390,7 @@ public class ParamsAndHandle {
}
```
由于该类与使用它的
`ControlDaemon`
类紧密相连,因此没有与该字段相关联的
mutator 或 accessor
。我们把这两个类看作是在同一个封装边界内的东西。
`toHandle () `
方法就在那里,所以我们可以将它用作方法句柄,我们将在第 10 章、“细粒度栈跟踪”中看到。
由于该类与使用它的
`ControlDaemon`
类紧密相连,因此没有与该字段相关联的
更改器或访问器
。我们把这两个类看作是在同一个封装边界内的东西。
`toHandle () `
方法就在那里,所以我们可以将它用作方法句柄,我们将在第 10 章、“细粒度栈跟踪”中看到。
# 控制守护进程
...
...
new/master-java11/10.md
浏览文件 @
bbec2994
...
...
@@ -125,7 +125,7 @@ public class CheckEligibility {
![](
img/8da943bd-0406-4257-8bcb-2707259cb2a4.png
)
StackFrame
在库中找到的类
`StackFrame`
在库中找到的类
# 示例–为呼叫者获取记录器
...
...
@@ -154,7 +154,7 @@ public class Labrador {
接下来,我们来看看
`StackWalker`
的细节。
# 与
StackWalker
合作
# 与
`StackWalker`
合作
在本节中,您将熟悉如何使用
`StackWalker`
。本节将探讨以下主题:
...
...
@@ -163,7 +163,7 @@ public class Labrador {
*
访问类
*
步行法
# 正在获取
StackWalker
的实例
# 正在获取
`StackWalker`
的实例
要遍历栈元素,我们需要一个
`StackWalker`
的实例。为此,我们调用
`getInstance()`
方法。如图所示,此方法有四个重载版本:
...
...
@@ -172,7 +172,7 @@ public class Labrador {
*
`static StackWalker getInstance(Set<StackWalker.Option> options)`
*
`static StackWalker getInstance(Set<StackWalker.Option> options, int estimateDepth)`
第一个版本不接受任何参数,并返回一个
`StackWalker`
实例,让我们遍历正常的栈帧。这通常是我们感兴趣的。该方法的其他版本接受一个或多个
`StackWalker
.Option`
值。顾名思义,enum
`StackWalker.Option`
在
`StackWalker`
类中
,有三个值:
第一个版本不接受任何参数,并返回一个
`StackWalker`
实例,让我们遍历正常的栈帧。这通常是我们感兴趣的。该方法的其他版本接受一个或多个
`StackWalker
`
类中的
`StackWalker.Option`
枚举
,有三个值:
*
`RETAIN_CLASS_REFERENCE`
*
`SHOW_REFLECT_FRAMES`
...
...
@@ -180,19 +180,19 @@ public class Labrador {
# 枚举选项
`RETAIN_CLASS_REFERENCE`
、
`SHOW_REFLECT_FRAMES`
和
`SHOW_HIDDEN_FRAMES`
enum
选项具有自描述性名称,下面将对其进行说明。
`RETAIN_CLASS_REFERENCE`
、
`SHOW_REFLECT_FRAMES`
和
`SHOW_HIDDEN_FRAMES`
枚举
选项具有自描述性名称,下面将对其进行说明。
#
保留等级参考
#
`RETAIN_CLASS_REFERENCE`
如果我们指定第一个选项
enum constant
,
`RETAIN_CLASS_REFERENCE`
作为
`getInstance()`
方法的参数,那么返回的实例将授予我们访问各个栈在遍历期间引用的类的权限。
如果我们指定第一个选项
的枚举常量
,
`RETAIN_CLASS_REFERENCE`
作为
`getInstance()`
方法的参数,那么返回的实例将授予我们访问各个栈在遍历期间引用的类的权限。
#
显示\u 反射\u 帧
#
`SHOW_REFLECT_FRAMES`
`SHOW_REFLECT_FRAMES`
enum 常量将生成一个 walker
,其中包含来自某个反射调用的帧。
`SHOW_REFLECT_FRAMES`
枚举常量将生成一个遍历器
,其中包含来自某个反射调用的帧。
#
显示隐藏的帧
#
`SHOW_HIDDEN_FRAMES`
最后,
enum constant
选项
`SHOW_HIDDEN_FRAMES`
将包括所有隐藏帧,其中包含反射调用以及为 Lambda 函数调用生成的调用帧。
最后,
枚举常量
选项
`SHOW_HIDDEN_FRAMES`
将包括所有隐藏帧,其中包含反射调用以及为 Lambda 函数调用生成的调用帧。
下面是反射和隐藏框架的简单演示:
...
...
@@ -348,7 +348,7 @@ stackwalker/packt.Main.main(Main.java:8)
在大多数情况下,它的效率较低,因为它强制
`StackWalker`
实例获取栈跟踪的所有元素,这样
`forEach()`
方法就可以遍历每个元素到最后。如果我们知道我们不会遍历栈跟踪到最后,我们应该使用
`walk()`
方法,即以惰性的方式访问栈,从而为性能优化留下更多的空间。
`StackWalker`
类有
`walk()`
方法,这是使其成为
walker
的定义方法。该方法接受由
`StackWalker`
调用的函数。
`walk()`
方法的返回值将是函数返回的对象。函数的参数是传递栈帧的
`Stream<StackFrame>`
。第一帧是包含
`walk()`
方法调用的帧,下一帧是调用包含
`walk()`
方法调用的帧,依此类推。
`StackWalker`
类有
`walk()`
方法,这是使其成为
遍历器
的定义方法。该方法接受由
`StackWalker`
调用的函数。
`walk()`
方法的返回值将是函数返回的对象。函数的参数是传递栈帧的
`Stream<StackFrame>`
。第一帧是包含
`walk()`
方法调用的帧,下一帧是调用包含
`walk()`
方法调用的帧,依此类推。
该函数可用于根据来自流的
`StackFrame`
对象计算一些值,并决定调用方是否有资格调用我们的代码。
...
...
@@ -371,7 +371,7 @@ public static void itIsNotCallBack() {
}
```
我们所做的只是直接从
walker
调用返回流,然后遍历流,然后执行相同的计算。我们的结果是
`IllegalStateException`
例外,而不是资格检查。
我们所做的只是直接从
遍历器
调用返回流,然后遍历流,然后执行相同的计算。我们的结果是
`IllegalStateException`
例外,而不是资格检查。
原因是
`StackWalker`
的实现高度优化。它不会复制整个栈来为流提供源信息。它是从实际的,活生生的栈中工作的。为此,必须确保在使用流时不修改栈。这与迭代集合时更改集合可能得到的
`ConcurrentModificationException`
异常非常相似。如果我们在调用栈中向上传递流,然后想要从中获取
`StackFrame`
,那么流将尝试从早已消失的栈帧中获取信息,因为我们从它所属的方法返回。这样,
`StackWalker`
就不会生成整个栈的快照,而是从实际栈开始工作,并且必须确保所需的栈部分不会更改。我们可以从函数中调用方法,这样我们可以在调用链中更深入地挖掘,但是在流被使用时,我们不能得到更高的值。
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录