博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java9系列(五)Stack-Walking API
阅读量:6229 次
发布时间:2019-06-21

本文共 10551 字,大约阅读时间需要 35 分钟。

本文主要研究下

StackWalker

java9新增这个类的目的是提供一个标准API用于访问当前线程栈,之前只有Throwable::getStackTrace、Thread::getStackTrace以及SecurityManager::getClassContext提供了方法可以获取线程栈。

StackWalker.Option

/Library/Java/JavaVirtualMachines/jdk-9.0.4.jdk/Contents/Home/lib/src.zip!/java.base/java/lang/StackWalker.java

/**     * Stack walker option to configure the {@linkplain StackFrame stack frame}     * information obtained by a {@code StackWalker}.     *     * @since 9     */    public enum Option {        /**         * Retains {@code Class} object in {@code StackFrame}s         * walked by this {@code StackWalker}.         *         * 

A {@code StackWalker} configured with this option will support * {@link StackWalker#getCallerClass()} and * {@link StackFrame#getDeclaringClass() StackFrame.getDeclaringClass()}. */ RETAIN_CLASS_REFERENCE, /** * Shows all reflection frames. * *

By default, reflection frames are hidden. A {@code StackWalker} * configured with this {@code SHOW_REFLECT_FRAMES} option * will show all reflection frames that * include {@link java.lang.reflect.Method#invoke} and * {@link java.lang.reflect.Constructor#newInstance(Object...)} * and their reflection implementation classes. * *

The {@link #SHOW_HIDDEN_FRAMES} option can also be used to show all * reflection frames and it will also show other hidden frames that * are implementation-specific. * * @apiNote * This option includes the stack frames representing the invocation of * {@code Method} and {@code Constructor}. Any utility methods that * are equivalent to calling {@code Method.invoke} or * {@code Constructor.newInstance} such as {@code Class.newInstance} * are not filtered or controlled by any stack walking option. */ SHOW_REFLECT_FRAMES, /** * Shows all hidden frames. * *

A Java Virtual Machine implementation may hide implementation * specific frames in addition to {@linkplain #SHOW_REFLECT_FRAMES * reflection frames}. A {@code StackWalker} with this {@code SHOW_HIDDEN_FRAMES} * option will show all hidden frames (including reflection frames). */ SHOW_HIDDEN_FRAMES; }复制代码

创建StackWalker的选项,可组合使用

  • RETAIN_CLASS_REFERENCE,可以使用StackWalker#getCallerClass(),StackFrame#getDeclaringClass(),StackFrame.getDeclaringClass()方法
  • SHOW_REFLECT_FRAMES,默认反射相关的frames是被隐藏的,使用这个选项可以开启
  • SHOW_HIDDEN_FRAMES,除了反射相关的frames外jvm还会隐藏其他一些实现相关的frame,使用这个选项可以将所有都输出

实例

使用Thread的getStackTrace

@Test    public void testPrintCurrnentStackTrace(){        StackTraceElement[] stack = Thread.currentThread().getStackTrace();        for (StackTraceElement element : stack){            System.out.println(element);        }    }复制代码

输出

java.base/java.lang.Thread.getStackTrace(Thread.java:1654)test.com.packt.lang.StackWalkingTest.testPrintCurrnentStackTrace(StackWalkingTest.java:20)java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)java.base/java.lang.reflect.Method.invoke(Method.java:564)org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)org.junit.runners.ParentRunner.run(ParentRunner.java:363)org.junit.runner.JUnitCore.run(JUnitCore.java:137)com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)复制代码

SHOW_REFLECT_FRAMES

private void print(StackWalker stackWalker){        stackWalker.forEach(stackFrame -> System.out.printf("%6d| %s -> %s %n",                stackFrame.getLineNumber(),                stackFrame.getClassName(),                stackFrame.getMethodName()));    }    @Test    public void testShowReflectFrames(){        final StackWalker stackWalker =                StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES);        print(stackWalker);    }复制代码

输出

19| test.com.packt.lang.StackWalkingTest -> print     43| test.com.packt.lang.StackWalkingTest -> testShowReflectFrames     -2| jdk.internal.reflect.NativeMethodAccessorImpl -> invoke0     62| jdk.internal.reflect.NativeMethodAccessorImpl -> invoke     43| jdk.internal.reflect.DelegatingMethodAccessorImpl -> invoke    564| java.lang.reflect.Method -> invoke     50| org.junit.runners.model.FrameworkMethod$1 -> runReflectiveCall     12| org.junit.internal.runners.model.ReflectiveCallable -> run     47| org.junit.runners.model.FrameworkMethod -> invokeExplosively     17| org.junit.internal.runners.statements.InvokeMethod -> evaluate    325| org.junit.runners.ParentRunner -> runLeaf     78| org.junit.runners.BlockJUnit4ClassRunner -> runChild     57| org.junit.runners.BlockJUnit4ClassRunner -> runChild    290| org.junit.runners.ParentRunner$3 -> run     71| org.junit.runners.ParentRunner$1 -> schedule    288| org.junit.runners.ParentRunner -> runChildren     58| org.junit.runners.ParentRunner -> access$000    268| org.junit.runners.ParentRunner$2 -> evaluate    363| org.junit.runners.ParentRunner -> run    137| org.junit.runner.JUnitCore -> run     68| com.intellij.junit4.JUnit4IdeaTestRunner -> startRunnerWithArgs     47| com.intellij.rt.execution.junit.IdeaTestRunner$Repeater -> startRunnerWithArgs    242| com.intellij.rt.execution.junit.JUnitStarter -> prepareStreamsAndStart     70| com.intellij.rt.execution.junit.JUnitStarter -> main复制代码

比默认的多输出了jdk.internal.reflect相关frames

输出所有frames

@Test    public void testGetAllFrames(){        List
stack = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((s) -> s.collect(Collectors.toList())); System.out.println("All frames : \n" + stack.toString()); }复制代码

输出

All frames : [test.com.packt.lang.StackWalkingTest.testGetAll(StackWalkingTest.java:54), org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50), org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12), org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47), org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17), org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325), org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78), org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57), org.junit.runners.ParentRunner$3.run(ParentRunner.java:290), org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71), org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288), org.junit.runners.ParentRunner.access$000(ParentRunner.java:58), org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268), org.junit.runners.ParentRunner.run(ParentRunner.java:363), org.junit.runner.JUnitCore.run(JUnitCore.java:137), com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68), com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47), com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242), com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)]复制代码

过滤指定class

@Test    public void testFilterByClass(){        Optional
filteredResult = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((s) -> s.filter(f -> StackWalkingTest.class.equals(f.getDeclaringClass())).findFirst() ); System.out.println("filter by class : \n"+filteredResult.toString()); }复制代码

输出

filter by class : Optional[test.com.packt.lang.StackWalkingTest.testFilterByClass(StackWalkingTest.java:62)]复制代码

skip

@Test    public void testSkip(){        List
framesAfterSkip = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((s) -> s.skip(2).collect(Collectors.toList())); System.out.println("frames after skip : \n"+framesAfterSkip.toString()); }复制代码

输出

frames after skip : [org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12), org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47), org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17), org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325), org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78), org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57), org.junit.runners.ParentRunner$3.run(ParentRunner.java:290), org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71), org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288), org.junit.runners.ParentRunner.access$000(ParentRunner.java:58), org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268), org.junit.runners.ParentRunner.run(ParentRunner.java:363), org.junit.runner.JUnitCore.run(JUnitCore.java:137), com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68), com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47), com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242), com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)]复制代码

这里skip了前两行

小结

java9引进的StackWalker可以更方便地打印当前线程堆栈,并提供了相关filter,skip等方法。

doc

转载地址:http://acxna.baihongyu.com/

你可能感兴趣的文章
java c 转换_由javac完成的任何类型的转换?
查看>>
java properties类_Java Properties 类
查看>>
java 账号密码登陆验证码_介绍javaweb登录验证码的实现方法步骤
查看>>
java 上传 分片技术_java 大文件分片上传处理
查看>>
java 平滑 停止_设计Java应用程序的平滑停止
查看>>
java生成8位数随机码_JAVA 生成无重复8位随机码
查看>>
java范围查询treemap_java集合-TreeMap
查看>>
Java解决主从数据库延迟问题_MySQL主从数据库同步延迟问题解决
查看>>
java将jfif格式转换成ipg_jfif是什么格式?Win10将图片JFIF格式转成JPG格式的方法
查看>>
socket.io java 点对点_netty-socket.io点对点通讯和聊天室通讯
查看>>
python java thrift_Apache Thrift PythonJava“连接被拒绝”
查看>>
java测试邮箱是否_javaWEB邮件测试
查看>>
java里booelan_Java Web应用开发技术与案例教程 教学课件 张继军 第4章_JDBC数据库访问技术.ppt...
查看>>
php mysql记录用户行为_用户参与记录存储的演变_PHP教程
查看>>
python中使用缩进来体现代码之间的逻辑关系_Python使用缩进来体现代码之间的逻辑关系。...
查看>>
python图像对比度拉伸_python库skimage 图像直方图均衡化、自适应均衡化、对比度拉伸实现...
查看>>
java判断是不是disable_Java Compiler disable()方法与示例
查看>>
php 发送 二进制,PHP处理二进制数据的实现方法
查看>>
用php写上传文件的代码,php多文件上传实现代码
查看>>
php发送邮件怎么配置,php 配置smtp发送邮件
查看>>