微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java反射之Call stack introspection详解

这篇文章主要介绍了Java反射之Call stack introspection详解,具有一定参考价值,需要的朋友可以了解下。

java是基于栈设计的语言,其实与C、C++语言相同。整个程序的运行表现在方法的执行是一系列入栈出栈的行为,栈是线程私有的。

在java语言中,我们可以跟踪方法调用关系,即当前栈帧(栈顶)和已经入栈的栈帧的层次关系。

从java1.4以后,java语言的Throwable类提供了以下方法

OpenDeclarationStackTraceElement[]java.lang.Throwable.getStackTrace() Providesprogrammaticaccesstothestacktraceinformationprintedbyprintstacktrace().Returnsanarrayofstacktraceelements,eachrepresentingonestackframe.Thezerothelementofthearray(assumingthearray'slengthisnon-zero)representsthetopofthestack,whichisthelastmethodinvocationinthesequence.Typically,thisisthepointatwhichthisthrowablewascreatedandthrown.Thelastelementofthearray(assumingthearray'slengthisnon-zero)representsthebottomofthestack,whichisthefirstmethodinvocationinthesequence. Somevirtualmachinesmay,undersomecircumstances,omitoneormorestackframesfromthestacktrace.Intheextremecase,avirtualmachinethathasnostacktraceinformationconcerningthisthrowableispermittedtoreturnazero-lengtharrayfromthismethod.Generallyspeaking,thearrayreturnedbythismethodwillcontainoneelementforeveryframethatwouldbeprintedbyprintstacktrace.Writestothereturnedarraydonotaffectfuturecallstothismethod. Returns: anarrayofstacktraceelementsrepresentingthestacktracepertainingtothisthrowable. Since: 1.4

方法返回的StackTraceElement[] 就是栈帧数组。数组下标0的元素代表当前栈顶栈帧,数组的最大下标代表调用栈序列中第一个栈帧,也就是第一个方法调用。我们可以从StackTraceElement得到栈调用层级的关系、调用方法名及调用入口位置,代码示例:

执行结果:

调用结果显示方法调用层级关系。

那我们得到这些信息有什么用呢。

1.日志:这些信息可以让应用的日志系统得到信息更详细。

2.安全:API可以决定调用者当前包或者类是否有权限进入。

3.流程控制:可以避免一些流程错误,比如无限递归调用

实现一个简单的日志系统:

package com.doctor.reflect; import java.io.PrintWriter; import java.io.StringWriter; /** * Call stack introspection * * @author sdcuike * * Created At 2016年8月29日 下午9:40:35 */ public class CallStackIntrospectionDemo { private static final MyLogger logger = new LoggerImpl(); public static void main(String[] args) { logger.logRecord("hello"); IllegalArgumentException exception = new IllegalArgumentException("IllegalArgumentException"); logger.logProblem("throwable", exception); } public interface MyLogger { // Types for log records int ERROR = 0; int WARNING = 100; int STATUS = 200; int DEBUG = 300; int TRACE = 400; void logRecord(String message); void logProblem(String message, Throwable throwable); } public static class LoggerImpl implements MyLogger { @Override public void logRecord(String message) { Throwable throwable = new Throwable(); log(message, throwable.getStackTrace()[1]); } @Override public void logProblem(String message, Throwable throwable) { StringWriter out = new StringWriter(); PrintWriter writer = new PrintWriter(out); throwable.printstacktrace(writer); writer.flush(); log(message + out.toString(), throwable.getStackTrace()[0]); } private void log(String message, StackTraceElement stackTraceElement) { String className = stackTraceElement.getClassName(); String methodName = stackTraceElement.getmethodName(); int lineNumber = stackTraceElement.getLineNumber(); System.out.println(String.join(" ", "模拟打印日志:", methodName, className, "" + lineNumber, message)); } } }

执行结果:

模拟打印日志: main com.doctor.reflect.CallStackIntrospectionDemo 36 hello 模拟打印日志: main com.doctor.reflect.CallStackIntrospectionDemo 38 throwablejava.lang.IllegalArgumentException: IllegalArgumentException at com.doctor.reflect.CallStackIntrospectionDemo.main(CallStackIntrospectionDemo.java:38)

上述日志,只是简单的在控制台打印一些信息。

总结

以上就是本文关于Java反射之Call stack introspection详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

Java反射简易教程

关于Java反射机制 你需要知道的事情

Java的RTTI和反射机制代码分析

如有不足之处,欢迎留言指出。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐