温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java反射之Call stack introspection的示例分析

发布时间:2021-08-23 15:20:30 来源:亿速云 阅读:229 作者:小新 栏目:编程语言

小编给大家分享一下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得到栈调用层级的关系、调用方法名及调用入口位置,代码示例:

Java反射之Call stack introspection的示例分析

执行结果:

Java反射之Call stack introspection的示例分析

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

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

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的示例分析”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI