Logger synchronization encapsulation in slf4j is implemented today to facilitate the replacement of logs in the future.
Problem encountered: Use thread. currentthread (). getstacktrace () [1]. getclassname () to get the current class instead of the call 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());}
Therefore, when printing logs, you do not get the class information that the logs actually belong.
Then I conducted a set of tests:
Test:
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 this 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 class is the same as above. The result is:
Java. Lang. thread; getstacktrace; thread. Java (thread Information)
Test. threadtest; teststring; threadtest. Java (current method and class)
Test. app; main; app. Java (methods and classes that call this method)
What is the meter situation ??? Is it because the getstacktrace of thread has more information than the getstacktrace of throwable (Exception's parent class) of Thread class ???
I'm not sure if this is the case, so I checked the JDK source code (it is purely an X installation, not an illusion ).
The first is the getstacktrace method of throwable. The Code is as follows:
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 it.
int depth = getStackTraceDepth();
stackTrace[i] = getStackTraceElement(i);
Both methods are native and will not be further explored. If no problem is found, go to the getstacktrace method of thread. The Code is as follows:
public StackTraceElement[] getStackTrace() { if (this != Thread.currentThread()) { // check for getStackTrace permission SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission( SecurityConstants.GET_STACK_TRACE_PERMISSION); } // optimization so we do not call into the vm for threads that // have not yet started or have terminated if (!isAlive()) { return EMPTY_STACK_TRACE; } StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this}); StackTraceElement[] stackTrace = stackTraceArray[0]; // a thread that was alive during the previous isAlive call may have // since terminated, therefore not having 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 with it ~~~ No, I suddenly followed the logic. In the if statement, because
This! = Thread. currentthread () is true, so the method will execute the statements in else. What is in it !!!!
return (new Exception()).getStackTrace();
All right! Here, the JVM executes new exception (). getstacktrace (); this statement makes it possible to print a Java statement using the getstacktrace method of thread. lang. thread; getstacktrace; thread. java! That's why
logger = LoggerFactory.getLogger(Thread.currentThread().getStackTrace()[1].getClassName());
The reason why the correct log information is not available!
This should be the case. In order to verify what I think is right, I wrote an example of test verification. The Code is as follows:
public class TestException {public static StackTraceElement[] getStackTrace() {return new Exception().getStackTrace();}}
public class ThreadTest {public static void TestString(){StackTraceElement[] arr = TestException.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 execution result is:
Test. testexception; getstacktrace; testexception. Java
Test. threadtest; teststring; threadtest. Java
Test. app; main; app. Java
The red line proves that my thoughts are correct!
All the verifications have ended. The final solution to this problem is very simple, or new exception () is used (). getstacktrace () [1]; either use thread. currentthread (). getstacktrace () [2].
Although this problem is very small and basic, I am still very excited. After all, I am stuck with the source code and suddenly forced a lot of upgrades ~~~
A newbie is on the road ~!