A tangle of two ways to get current stack information (thread and Throwable)

Source: Internet
Author: User
Tags stack trace

Today, the SLF4J is logger in a synchronous package. The main purpose is to facilitate the replacement of the log implementation system later.

Problem encountered: Use Thread.CurrentThread (). Getstacktrace () [1].getclassname () gets the current class instead of the calling class. See the following code:

Private Org.slf4j.Logger Logger = null;/** * Construction method */public Logger () {//Get the current class Loggerlogger = Loggerfactory.getlogger (Thread.CurrentThread (). Getstacktrace () [1].getclassname ());

So when you print the log, you don't get the information about the class that the log really belongs to.


Then I carried out a set of tests:

Test A:

public class ThreadTest {public static void TestString () {stacktraceelement[] arr = new Exception (). Getstacktrace (); for ( int i=0;i<=arr.length-1;i++) {System.out.println (Arr[i].getclassname () + ";" +arr[i].getmethodname () + ";" +arr[i].getfilename ());}}}

public class App {public    static void Main (string[] args)    {        threadtest.teststring ();}    }

The result is:

Test. ThreadTest; teststring; Threadtest.java (current method and Class)
Test. App;main; App.java (Methods and classes that call the method)

Test B:

public class ThreadTest {public static void TestString () {stacktraceelement[] arr = Thread.CurrentThread (). Getstacktrace (); for (int i=0;i<=arr.length-1;i++) {System.out.println (Arr[i].getclassname () + ";" +arr[i].getmethodname () + ";" +arr[i].getfilename ());}}}

The app is similar. The resulting results are:

Java.lang.thread;getstacktrace; Thread.java (thread's information)
Test. ThreadTest; teststring; Threadtest.java (current method and Class)
Test. App;main; App.java (Methods and classes that call the method)

What rice situation??? Is it because the thread of the Getstacktrace than Throwable (exception of the parent class) of the Getstacktrace more hit a section of the thread class information???


Because I'm not sure if this is really the case, the deceased looked at the source code for the next JDK (it's a purely X-ray, no fantasy).

The first is the Getstacktrace method of the Throwable, the code such as the following:

Public stacktraceelement[] Getstacktrace () {        return Getourstacktrace (). Clone ();    Private synchronized stacktraceelement[] Getourstacktrace () {        //Initialize stack trace field with information from
   //BackTrace If this is the first call to this method        if (stackTrace = = Unassigned_stack | |            (StackTrace = = NULL && backtrace! = null)/* Out of protocol state */) {            int depth = getstacktracedepth (); 
   
    stacktrace = new Stacktraceelement[depth];            for (int i=0; i < depth; i++)                stacktrace[i] = getstacktraceelement (i);        } else if (stackTrace = = null) {            return unassigned_stack;        }        return stackTrace;    }
   

There seems to be nothing wrong with the place Ha, among

int depth = getstacktracedepth ();
Stacktrace[i] = getstacktraceelement (i);
Two methods are native, not to delve into. No problem is found here. Went to see the next thread of the Getstacktrace method, code such as the following:

Public stacktraceelement[] Getstacktrace () {if (This! = Thread.CurrentThread ()) {//Check for Getstack            Trace permission SecurityManager security = System.getsecuritymanager (); if (Security! = null) {security.checkpermission (securityconstants.get_stack_trace_perm            Ission); }//Optimization so we don't call to the the VM for threads that//has not yet started or has ter            minated if (!isalive ()) {return empty_stack_trace;            } stacktraceelement[][] Stacktracearray = dumpthreads (new thread[] {this});            stacktraceelement[] StackTrace = stacktracearray[0]; A thread that is alive during the previous isAlive call May has//since terminated, therefore not had            A stacktrace.            if (StackTrace = = null) {stackTrace = Empty_stack_trace;      } return stackTrace;  } else {//Don ' t need JVM help for current thread return (new Exception ()). Getstacktrace (); }    }

At first glance there is nothing wrong AH ~ ~ ~ Not right, suddenly follow the logic to walk. Inside the IF statement because

This! = Thread.CurrentThread () is true. So the method runs the statement inside the else, what's inside.!!


Return (new Exception ()). Getstacktrace ();
All right!

This is the place where the JVM goes to run the new Exception (). Getstacktrace (); It is this sentence that makes use of Thread Getstacktrace method is possible to print a sentence java.lang.Thread; Getstacktrace; Thread.java out. That's why you use

Logger = Loggerfactory.getlogger (Thread.CurrentThread (). Getstacktrace () [1].getclassname ()];
Can not get the correct log information for the reason.

That's the way it should be. In order to verify that I was wrong, I wrote an example of a test pass, such as the following code:

public class TestException {public static stacktraceelement[] Getstacktrace () {return new Exception (). Getstacktrace ();}}

public class ThreadTest {public static void TestString () {stacktraceelement[] arr = Testexception.getstacktrace (); int i=0;i<=arr.length-1;i++) {System.out.println (Arr[i].getclassname () + ";" +arr[i].getmethodname () + ";" +arr[i].getfilename ());}}}

public class App {public    static void Main (string[] args)    {        threadtest.teststring ();}    }

The result after the run is:

Test. Testexception;getstacktrace; Testexception.java
Test. ThreadTest; teststring; Threadtest.java
Test. App;main; App.java

The red line proves that my idea is correct!


All the validations are over. The final solution to this problem is very easy, either using the new Exception (). Getstacktrace () [1]; either use Thread.CurrentThread (). Getstacktrace () [2].

Although this problem is very small, it is very basic. But I'm still very excited. After all, glue on the source code, immediately forcing lattice rise a lot ~ ~ ~

Novice on the road. Master Mercy ~!




A tangle of two ways to get current stack information (thread and Throwable)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.