java遍历栈_Java中使用StackWalker和Stream API进行堆栈遍历
1.Java 9以前堆栈遍历到目前为止,官方解决方案是获取当前线程并调用其getStackTrace()方法:
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
另一个智能解决方案涉及.抛出异常并从中提取堆栈跟踪信息。 但是,无法操纵结果,它会立即打印出来:
new Exception().printStackTrace();
两种解决方案都存在同样的问题——它们都急切地捕获整个堆栈的快照,可不方便使用。
2. JEP-259: Stack-Walking API
JEP-259应该解决这些问题,而且确实如此。 新的API提供了一种使用Stream API懒惰地遍历堆栈跟踪的便捷方法。
我们可以像这样轻松地创建StackWalker实例:
StackWalker stack = StackWalker.getInstance();
此外,我们可以提供一些初始选项:
StackWalker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
如果我们想要遍历整个堆栈,那只需要调用forEach()方法:
stack.forEach(System.out::println);
3. StackWalker.StackFrame
如果我们查看Java 1.4的StackTraceElement——它几乎是一个包含有关声明类、方法名、类加载器名等的详细字符串信息。
StackWalker.StackFrame是一个更加类型安全友好的升级,在其上面提到了丰富的方法:
public Class> getDeclaringClass();
public MethodType getMethodType();…甚至可这样:
public StackTraceElement toStackTraceElement();
4.示例
让我们将前面那些付诸实践,来创建一个简单的调用层次结构
(代码包和类名:com.nd.stackwalker. StackWalker):
public static void main(String[] args) {
foo();
}
private static void foo() {
bar();
}
private static void bar() {
java.lang.StackWalker
.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
.forEach(System.out::println);
}
如果我们在IDE中(jshell运行显示会不一样,这个它的处理模式有关)中运行它,结果将是(注意堆栈元素的顺序):
com.nd.stackwalker.StackWalker.bar(StackWalker.java:22)
com.nd.stackwalker.StackWalker.foo(StackWalker.java:17)
com.nd.stackwalker.StackWalker.main(StackWalker.java:14)
5.高级特性如果我们想利用惰性或帧过滤,我们可以使用另一个名为walk()的专用API方法,它允许我们使用Stream API来方便地遍历堆栈。 在阅读本文时,您可能想象walk()方法只是返回一个Stream实例。事实并非如此。
实际的签名是:
public T walk(Function super Stream, ? extends T> function)
还有一个很好的理由使它成为这种方式——堆栈需要被冻结以便遍历它,并且这发生在walk()方法调用的范围内 - 所以使用基于函数接口的模板方法实现这一目标是有意义的 。
即使你试图通过返回一个Stream实例来欺骗它,它也无法使用(自己试试看!)。
一旦我们知道了这个限制,我们只受我们的想象力和Stream API功能的约束。例如,我们可以优雅地跳过一些帧,然后挑选第一个遇到的帧:
java.lang.StackWalker
.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.skip(1).limit(1).collect(Collectors.toList()))
.forEach(System.out::println);
// 结果如下:
com.nd.stackwalker.StackWalker.main(StackWalker.java:17)
6.完整代码清单
/*
*测试堆栈遍历
*/
package com.nd.stackwalker;
import java.util.stream.Collectors;
/**
*
* @author Solo Cui
*/
public class StackWalker {
public static void main(String[] args) {
foo();
}
private static void foo() {
java.lang.StackWalker
.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.skip(1).limit(1).collect(Collectors.toList()))
.forEach(System.out::println);//第一次运行,注释掉
//bar();//第二次运行注释掉
}
private static void bar() {
java.lang.StackWalker
.getInstance(java.lang.StackWalker.Option.RETAIN_CLASS_REFERENCE)
.forEach(System.out::println);
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接
java遍历栈_Java中使用StackWalker和Stream API进行堆栈遍历相关推荐
- java steam 去重_Java中对List去重 Stream去重的解决方法
问题 当下互联网技术成熟,越来越多的趋向去中心化.分布式.流计算,使得很多以前在数据库侧做的事情放到了Java端.今天有人问道,如果数据库字段没有索引,那么应该如何根据该字段去重?大家都一致认为用Ja ...
- java入栈_java中代码块的执行,也会有入栈的步骤吗?
首先这个问题很有意思,不过题主没具体指明放在何处的代码块. 这里至少有三种情况,第一种就是在普通的方法里面,第二种是实例初始化代码块,第三种是静态初始化代码块. 第一种情况 使用javap反汇编了一下 ...
- java steam 去重_Java中对List去重, Stream去重
问题 当下互联网技术成熟,越来越多的趋向去中心化.分布式.流计算,使得很多以前在数据库侧做的事情放到了Java端.今天有人问道,如果数据库字段没有索引,那么应该如何根据该字段去重?大家都一致认为用Ja ...
- java静态方法 问题_Java中堆、栈,静态方法和非静态方法的速度问题
一.堆和栈的速度性能分析 堆和栈是JVM内存模型中的2个重要组成部分,自己很早以前也总结过堆和栈的区别,基本都是从存储内容,存储空间大小,存储速度这几个方面来理解的,但是关于堆和栈的存储速度,只知道堆 ...
- java如何遍历字典_Java中如何遍历Map对象的4种方法
在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...
- java内存堆和栈_java中堆,栈主要区别及内存存储
java堆.栈.堆栈的区别 1.栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. 2. 栈的优势是,存取速度 ...
- java filefilter递归_Java中的递归+文件过滤器
直接递归称为方法自身调用自己 间接递归可以A方法调用B方法,B方法调用方法,C方法调用A方法. 注意事项: 递归一定要有条件限定,保证递归能够停止下来,否则会发生栈内存溢出. 在递归中虽然有限定条件, ...
- java 注解开发_Java中的注解到底是如何工作的?
作者:人晓 www.importnew.com/10294.html 自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Over ...
- java 不知道类名_Java 中获取类名的三种方法,你知道几种?
之前我们分享过Java高级篇--深入浅出Java类加载机制这篇文章,今天来带你了解获取类名的三种方法. 获取类名的方法 Java 中获取类名的方式主要有以下三种. getName() 返回的是虚拟机里 ...
最新文章
- 安装hadoop下的sqoop1.99.3及配置问题全解决
- tensorflow量化感知训练_tensorflow模型量化实例
- 传闻或成真!这款新iPhone真就要停产了...
- 3d 自动生成物体_根据 2D 图片自动生成 3D 图书封面的牛逼工具
- word2016取消首字母大写 带图详细讲解
- Ubuntu10.0.4下CyanogenMod编译环境的搭建和可刷机文件的编译及打包
- centos安装libconfig
- java 运行 依赖_java – 运行时中的依赖项确定
- 最简单音乐播放器,还有歌词
- 利用intellij idea工具如何反编译.jar
- Linux 》编译器gcc/g++,调试器gdb
- phpstudy 运行PHP项目
- 大数据解决方案:Hadoop监控
- stm32L152 使用内部内部flash做EEPROM 出FLASH_ERROR_WRP问题及解决办法
- 【shell】Cshell
- 关于async await 等任务队列插话
- 520、Java Spring Cloud Alibaba -【Spring Cloud Alibaba Zuul】 2021.11.02
- linux ftp下载文件到本地,如何使用get指令利用FTP下载文件到本地
- odoo12 学习: 无效视图 xxxx xxxx xxxx 定义 False
- ADB命令大全--自学留存
热门文章
- void*与int互转
- boost库之tcp client 回调不正常
- jsp打印日志完整配置
- 爬虫架构师得逆袭之路
- android app电量分析,如何计算android app的耗电量?
- vc++获取的蓝牙设备信息中rssi的值_Android低功耗蓝牙总结
- idea设置类注释和方法注释
- redis 经纬度_原来用Redis实现查找附近的人这么容易
- 云南林业职业技术学院计算机考试试题,云南林业职业技术学院单招模拟题(含解析)9.docx...
- 第三讲,我们来谈谈:“二进制的负数”