Java反射之Call stack introspection詳解
java是基于棧設(shè)計的語言,其實與C、C++語言相同。整個程序的運行表現(xiàn)在方法的執(zhí)行是一系列入棧出棧的行為,棧是線程私有的。
在java語言中,我們可以跟蹤方法的調(diào)用關(guān)系,即當(dāng)前棧幀(棧頂)和已經(jīng)入棧的棧幀的層次關(guān)系。
從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[] 就是棧幀數(shù)組。數(shù)組下標(biāo)0的元素代表當(dāng)前棧頂棧幀,數(shù)組的最大下標(biāo)代表調(diào)用棧序列中第一個棧幀,也就是第一個方法的調(diào)用。我們可以從StackTraceElement得到棧調(diào)用層級的關(guān)系、調(diào)用方法名及調(diào)用入口位置,代碼示例:

執(zhí)行結(jié)果:

調(diào)用結(jié)果顯示的方法調(diào)用層級關(guān)系。
那我們得到這些信息有什么用呢。
1.日志:這些信息可以讓應(yīng)用的日志系統(tǒng)得到信息更詳細。
2.安全:API可以決定調(diào)用者當(dāng)前包或者類是否有權(quán)限進入。
3.流程控制:可以避免一些流程錯誤,比如無限遞歸調(diào)用。
實現(xià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é)
以上就是本文關(guān)于Java反射之Call stack introspection詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:
如有不足之處,歡迎留言指出。
- JAVA中StackOverflowError錯誤的解決
- JVM---jstack分析Java線程CPU占用,線程死鎖的解決
- Java中使用StackWalker和Stream API進行堆棧遍歷
- Java StackTraceElement實例代碼
- Java線程Dump分析工具jstack解析及使用場景
- 深入分析JAVA Vector和Stack的具體用法
- java中stack(棧)的使用代碼實例
- Java數(shù)據(jù)結(jié)構(gòu)與算法之棧(Stack)實現(xiàn)詳解
- OneinStack一鍵安裝PHP/JAVA/HHVM和超詳細的VPS手動安裝LNMP的方法
- Java 異常的棧軌跡(Stack Trace)詳解及實例代碼
- java自帶的工具Jstack截取進程中的堆棧信息
- Java 并發(fā)編程ArrayBlockingQueue的實現(xiàn)
- 詳解JAVA中priorityqueue的具體使用
- 詳解Java中的延時隊列 DelayQueue
- 詳解java中DelayQueue的使用
- java隊列之queue用法實例分析
- Java多線程工具篇BlockingQueue的詳解
- Java Stack與Queue詳解
相關(guān)文章
base64_encode和base64_decode的JAVA實現(xiàn)
Base64 編碼其實是將3個8位字節(jié)轉(zhuǎn)換為4個6位這4個六位字節(jié) 其實仍然是8位,只不過高兩位被設(shè)置為0. 當(dāng)一個字節(jié)只有6位有效時,它的取值空間為0 到 2的6次方減1 即63,也就是說被轉(zhuǎn)換的Base64編碼的每一個編碼的取值空間為(0~63).需要的朋友可以參考下2016-04-04
Springboot工具類ReflectionUtils使用教程
這篇文章主要介紹了Springboot內(nèi)置的工具類之ReflectionUtils的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12
SpringBoot查詢數(shù)據(jù)庫導(dǎo)出報表文件方式
這篇文章主要介紹了SpringBoot查詢數(shù)據(jù)庫導(dǎo)出報表文件方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
詳解Spark?Sql在UDF中如何引用外部數(shù)據(jù)
這篇文章主要為大家介紹了詳解Spark?Sql在UDF中如何引用外部數(shù)據(jù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02
Java統(tǒng)計50個10到50之間整數(shù)的隨機出現(xiàn)次數(shù)
這篇文章主要為大家詳細介紹了Java統(tǒng)計50個10到50之間整數(shù)的隨機出現(xiàn)次數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07

