Java反射之Call stack introspection详解

 更新时间:2017年11月15日 16:15:34   作者:Beaver  
这篇文章主要介绍了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和反射机制代码分析

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

相关文章

  • Spring boot调用Oracle存储过程的两种方式及完整代码

    Spring boot调用Oracle存储过程的两种方式及完整代码

    这篇文章主要给大家介绍了关于Spring boot调用Oracle存储过程的两种方式及完整代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-08-08
  • 一文详解MVCC的执行原理

    一文详解MVCC的执行原理

    MVCC是一种并发控制机制,用于解决数据库并发访问中,数据一致性问题,它通过在读写操作期间保存多个数据版本,以提供并发事务间的隔离性,本文将和大家简单聊聊MVCC的执行原理,需要的朋友可以参考下
    2023-12-12
  • Java中@Pattern注解常用的校验正则表达式学习笔记

    Java中@Pattern注解常用的校验正则表达式学习笔记

    对于正则这个东西,对我来说一直是很懵逼的,每次用每次查,然后还是记不住,下面这篇文章主要给大家介绍了关于Java中@Pattern注解常用的校验正则表达式学习笔记的相关资料,需要的朋友可以参考下
    2022-07-07
  • Spring整合redis的操作代码

    Spring整合redis的操作代码

    这篇文章主要介绍了Spring整合redis的操作代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • 如何通过Java生成一个随机数

    如何通过Java生成一个随机数

    当我们需要在Java中生成随机数时,可以借助JDK中提供的Random类来实现,通过使用Random类,我们可以轻松地生成各种类型的随机数,下面我们就来看看如何利用Random类生成随机数吧
    2023-09-09
  • SpringBoot快速搭建web项目详细步骤总结

    SpringBoot快速搭建web项目详细步骤总结

    这篇文章主要介绍了SpringBoot快速搭建web项目详细步骤总结 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • Java通过PropertyDescriptor反射调用set和get方法

    Java通过PropertyDescriptor反射调用set和get方法

    这篇文章主要为大家详细介绍了Java通过PropertyDescriptor反射调用set和get方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • java多线程编程之Synchronized块同步方法

    java多线程编程之Synchronized块同步方法

    这篇文章主要介绍了java多线程编程之Synchronized块同步方法,synchronized关键字又称同步锁,当方法执行完后,会自动释放锁锁,只有一个线程能进入此方法,看看下文中各种例子对synchronized的详细解释
    2015-12-12
  • java 获取用户的MAC地址多种方法实例详解

    java 获取用户的MAC地址多种方法实例详解

    这篇文章主要介绍了JAVA实现获取用户的MAC地址的多种方法实例,需要的朋友可以参考下
    2017-04-04
  • java利用Tabula实现对PDF内表格数据提取

    java利用Tabula实现对PDF内表格数据提取

    Tabula是一个开源工具,用于从PDF文档中提取表格数据,下面小编就来和大家详细介绍一下java如何通过Tabula对PDF文件内表格进行数据提取吧
    2023-09-09

最新评论