Java高階--Java執行緒執行棧資訊的獲取
阿新 • • 發佈:2019-01-10
*/
public LocationInfo(Throwable t, String fqnOfCallingClass) {
String s;
…
t.printStackTrace(pw);
s = sw.toString();
sw.getBuffer().setLength(0);
…. // 這裡的程式碼省略
}
[/code]
這裡我們可以看到整體的實現思路。
首先,t.printStackTrace(pw); 獲得stack trace字串。這個t是 new Throwable()的結果。使用者程式呼叫Log4J方法之後,Log4J自己又進行了4次呼叫,然後才獲得了 t = new Throwable() :
at org.apache.log4j.PatternLayout.format(PatternLayout.java:413)
at org.apache.log4j.FileAppender.doAppend(FileAppender.java:183)
at org.apache.log4j.Category.callAppenders(Category.java:131)
at org.apache.log4j.Category.log(Category.java:512)
那麼,往下走4行,就可以回到使用者程式本身的呼叫資訊:
at callers.fully.qualified.className.methodName(FileName.java:74)
這一行裡面,類名、方法名、檔名、行號等資訊全有了。解析這一行,就可以獲得需要的所有資訊。
三、JDK1.4 Log的相關實現
Log4J大獲成功,Sun決定在JDK1.4中引入這個Log功能。
為了免去解析StackTrace字串的麻煩,JDK1.4引入了一個新的類,StackTraceElement。
public final class StackTraceElement implements java.io.Serializable {
// Normally initialized by VM (public constructor added in 1.5)
private String declaringClass;
private String methodName;
private String fileName;
private int lineNumber;
可以看到,恰好包括類名、方法名、檔名、行號等資訊。
我們來看JDK1.4 Log的相關實現。
LocationInfo.java 的infoCaller方法(推算呼叫者)
// Private method to infer the callers class and method names
private void inferCaller() {
…
// Get the stack trace.
StackTraceElement stack[] = (new Throwable()).getStackTrace();
// First, search back to a method in the Logger class.
…. // 這裡的程式碼省略
// Now search for the first frame before the "Logger" class.
while (ix < stack.length) {
StackTraceElement frame = stack[ix];
String cname = frame.getClassName();
if (!cname.equals("java.util.logging.Logger"))
// Weve found the relevant frame.
… // 這裡的程式碼省略
}
// We haven found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here.
}
從註釋中就可以看出實現思路。過程和Log4J異曲同工。只是免去了解析字串的麻煩。
四、Log4J 1.3 alpha的相關實現
既然JDK1.4中引入了StackTraceElement類,Log4J也要與時俱進。LocationInfo類也有了相應的變化。
/**
Instantiate location information based on a Throwable. We
expect the Throwable , to be in the format
public LocationInfo(Throwable t, String fqnOfCallingClass) {
String s;
…
t.printStackTrace(pw);
s = sw.toString();
sw.getBuffer().setLength(0);
…. // 這裡的程式碼省略
}
[/code]
這裡我們可以看到整體的實現思路。
首先,t.printStackTrace(pw); 獲得stack trace字串。這個t是 new Throwable()的結果。使用者程式呼叫Log4J方法之後,Log4J自己又進行了4次呼叫,然後才獲得了 t = new Throwable() :
at org.apache.log4j.PatternLayout.format(PatternLayout.java:413)
at org.apache.log4j.FileAppender.doAppend(FileAppender.java:183)
at org.apache.log4j.Category.callAppenders(Category.java:131)
at org.apache.log4j.Category.log(Category.java:512)
那麼,往下走4行,就可以回到使用者程式本身的呼叫資訊:
at callers.fully.qualified.className.methodName(FileName.java:74)
這一行裡面,類名、方法名、檔名、行號等資訊全有了。解析這一行,就可以獲得需要的所有資訊。
三、JDK1.4 Log的相關實現
Log4J大獲成功,Sun決定在JDK1.4中引入這個Log功能。
為了免去解析StackTrace字串的麻煩,JDK1.4引入了一個新的類,StackTraceElement。
public final class StackTraceElement implements java.io.Serializable {
// Normally initialized by VM (public constructor added in 1.5)
private String declaringClass;
private String methodName;
private String fileName;
private int lineNumber;
可以看到,恰好包括類名、方法名、檔名、行號等資訊。
我們來看JDK1.4 Log的相關實現。
LocationInfo.java 的infoCaller方法(推算呼叫者)
// Private method to infer the callers class and method names
private void inferCaller() {
…
// Get the stack trace.
StackTraceElement stack[] = (new Throwable()).getStackTrace();
// First, search back to a method in the Logger class.
…. // 這裡的程式碼省略
// Now search for the first frame before the "Logger" class.
while (ix < stack.length) {
StackTraceElement frame = stack[ix];
String cname = frame.getClassName();
if (!cname.equals("java.util.logging.Logger"))
// Weve found the relevant frame.
… // 這裡的程式碼省略
}
// We haven found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here.
}
從註釋中就可以看出實現思路。過程和Log4J異曲同工。只是免去了解析字串的麻煩。
四、Log4J 1.3 alpha的相關實現
既然JDK1.4中引入了StackTraceElement類,Log4J也要與時俱進。LocationInfo類也有了相應的變化。
/**
Instantiate location information based on a Throwable. We
expect the Throwable
t