Java反射之Call stack introspection詳解
java是基于棧設(shè)計(jì)的語(yǔ)言,其實(shí)與C、C++語(yǔ)言相同。整個(gè)程序的運(yùn)行表現(xiàn)在方法的執(zhí)行是一系列入棧出棧的行為,棧是線程私有的。
在java語(yǔ)言中,我們可以跟蹤方法的調(diào)用關(guān)系,即當(dāng)前棧幀(棧頂)和已經(jīng)入棧的棧幀的層次關(guān)系。
從java1.4以后,java語(yǔ)言的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[] 就是棧幀數(shù)組。數(shù)組下標(biāo)0的元素代表當(dāng)前棧頂棧幀,數(shù)組的最大下標(biāo)代表調(diào)用棧序列中第一個(gè)棧幀,也就是第一個(gè)方法的調(diào)用。我們可以從StackTraceElement得到棧調(diào)用層級(jí)的關(guān)系、調(diào)用方法名及調(diào)用入口位置,代碼示例:
執(zhí)行結(jié)果:
調(diào)用結(jié)果顯示的方法調(diào)用層級(jí)關(guān)系。
那我們得到這些信息有什么用呢。
1.日志:這些信息可以讓?xiě)?yīng)用的日志系統(tǒng)得到信息更詳細(xì)。
2.安全:API可以決定調(diào)用者當(dāng)前包或者類是否有權(quán)限進(jìn)入。
3.流程控制:可以避免一些流程錯(cuò)誤,比如無(wú)限遞歸調(diào)用。
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志系統(tǒng):
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)); } } }
執(zhí)行結(jié)果:
模擬打印日志: 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)
上述日志,只是簡(jiǎn)單的在控制臺(tái)打印一些信息。
總結(jié)
以上就是本文關(guān)于Java反射之Call stack introspection詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:
如有不足之處,歡迎留言指出。
- JAVA中StackOverflowError錯(cuò)誤的解決
- JVM---jstack分析Java線程CPU占用,線程死鎖的解決
- Java中使用StackWalker和Stream API進(jìn)行堆棧遍歷
- Java StackTraceElement實(shí)例代碼
- Java線程Dump分析工具jstack解析及使用場(chǎng)景
- 深入分析JAVA Vector和Stack的具體用法
- java中stack(棧)的使用代碼實(shí)例
- Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(Stack)實(shí)現(xiàn)詳解
- OneinStack一鍵安裝PHP/JAVA/HHVM和超詳細(xì)的VPS手動(dòng)安裝LNMP的方法
- Java 異常的棧軌跡(Stack Trace)詳解及實(shí)例代碼
- java自帶的工具Jstack截取進(jìn)程中的堆棧信息
- Java 并發(fā)編程ArrayBlockingQueue的實(shí)現(xiàn)
- 詳解JAVA中priorityqueue的具體使用
- 詳解Java中的延時(shí)隊(duì)列 DelayQueue
- 詳解java中DelayQueue的使用
- java隊(duì)列之queue用法實(shí)例分析
- Java多線程工具篇BlockingQueue的詳解
- Java Stack與Queue詳解
相關(guān)文章
java容器類知識(shí)點(diǎn)詳細(xì)總結(jié)
這篇文章主要介紹了java容器類知識(shí)點(diǎn)詳細(xì)總結(jié),2019-06-06Java 1.8使用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列
這篇文章主要為大家詳細(xì)介紹了Java 1.8使用數(shù)組實(shí)現(xiàn)循環(huán)隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10Spring Boot攔截器和過(guò)濾器實(shí)例解析
這篇文章主要介紹了Spring Boot攔截器和過(guò)濾器實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01Java實(shí)現(xiàn)分頁(yè)的前臺(tái)頁(yè)面和后臺(tái)代碼
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)分頁(yè)的前臺(tái)頁(yè)面和后臺(tái)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03java?freemarker實(shí)現(xiàn)動(dòng)態(tài)生成excel文件
這篇文章主要為大家詳細(xì)介紹了java如何通過(guò)freemarker實(shí)現(xiàn)動(dòng)態(tài)生成excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12