前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从OpenJDK8到OpenJDK11 - StackWalker类

从OpenJDK8到OpenJDK11 - StackWalker类

作者头像
干货满满张哈希
发布2021-04-12 14:16:56
8520
发布2021-04-12 14:16:56
举报
文章被收录于专栏:干货满满张哈希

本文基于OpenJDK 11

之前升级了JDK到OpenJDK11,把遇到的问题以及解决方案列一下。 每篇文章会以提出问题,思路说明,解决问题的思路去行文。 这篇文章是关于堆栈信息获取的。

遇到的问题 - 调用堆栈获取

之前有做调用堆栈监控上报,某些仅采集调用类,某些需要采集调用方法,总体来说:在Java8中,我们可以这样去获取调用堆栈:

  1. 通过Reflection类:
代码语言:javascript
复制
private static void getCallStackClassNames() {
    StringBuffer sbStack = new StringBuffer();
    int i = 0;
    Class caller = Reflection.getCallerClass(i++);
    do {
        sbStack.append(i + ".").append(caller.getName())
            .append("\n");
        caller = Reflection.getCallerClass(i++);
    } while (caller != null);
    LOGGER.info("{}", sbStack);
}

这种方式可以灵活地获取调用类,不用一下子读取整个堆栈。但是缺点是:无法查看调用方法,信息不够详细 2. 通过Thread.currentThread().getStackTrace():

代码语言:javascript
复制
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

这种方法获取的信息很详细,但是一下子返回整个堆栈的调用,不够方便。

升级到OpenJDK11之后,sun.reflect.Reflection类没有了。

思路说明

通过在Java 9之后JDK自带的工具jdeps来寻找可替代的类:

代码语言:javascript
复制
jdeps  --jdk-internals ./target/AppName.jar

显示:

代码语言:javascript
复制
...
JDK Internal API                         Suggested Replacement
----------------                         ---------------------
sun.reflect.Reflection                   Use java.lang.StackWalker @since 9

看到建议使用java.lang.StackWalker 我们考虑用这个类替换sun.reflect.Reflection

解决问题

StackWalker可以灵活地查看每一帧调用。 初始化可以指定选项:

代码语言:javascript
复制
//一般这样就足够用了,可以把每个调用栈输出
StackWalker walker = StackWalker.getInstance();

也可以指定初始化参数:

代码语言:javascript
复制
//这样对于调用:StackWalker#getCallerClass()和StackFrame#getDeclaringClass()不会报异常,默认初始化是不支持这两个方法的
StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);

如果你想看反射的调用栈,例如Spring动态代理反射,可以这么初始化:

代码语言:javascript
复制
StackWalker walker = StackWalker.getInstance(StackWalker.Option.SHOW_REFLECT_FRAMES);

如果你想看完整的调用栈没有隐藏任何的调用栈,可以这么初始化:

代码语言:javascript
复制
StackWalker walker = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES);

之后应用,例如取第一个调用栈:

代码语言:javascript
复制
walker.walk(s -> s.limit(1).collect(Collectors.toList()));

将每一个输出:

代码语言:javascript
复制
walker.forEach(System.out::println);
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 遇到的问题 - 调用堆栈获取
  • 思路说明
  • 解决问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档