
开发过程中一直需要获得当前正在执行的方式名,以前搜过,只是简单的明白可以调用Thread.currentThread().getStackTrace()来获得。就点到为止了。这次应该获得调用当前方法的方式的技巧名(有点绕,我信你可看明白),所以具体跟了下。
Thread.currentThread().getStackTrace()返回的是一个StackTraceElement数组,内容为调用函数堆栈java stack trace,并且以读取层级关系保存。由于不记得当时用的之后使用的字段下标,想当然的觉得Android和纯Java的层级应该是一样的。所以直接取下标为2(StackTraceElement[2])当成是调用当前方法的方式。后来调试了下才发觉问题。调用当前方法的方式在Android上函数下标为3,纯Java的变量下标为2。

出现这个问题是因为Android的java.lang.Thread.getStackTrace方法实际上是调用了Android的VMStack.getThreadStackTrace(this):
/**
* Returns an array of {@link StackTraceElement} representing the current thread's stack.
*/
public StackTraceElement[] getStackTrace() {
StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT;
}

这里不再往深入里跟进去了(好吧,其实是我和不下来了),贴出调试过程中打印的变量调用堆栈信息,可以扫眼函数的调用层级关系:
JAVA版本:

[0]java.lang.Thread.getStackTrace(Thread.java:1518)
[1]com.test.TestDemo.testMethod(TestDemo.java:34)
[2]com.test.TestDemo.testMethod1(TestDemo.java:29)
[3]sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[4]sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[5]sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[6]java.lang.reflect.Method.invoke(Method.java:597)
[7]org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
[8]org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
[9]org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
[10]org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
[11]org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
[12]org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
[13]org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
[14]org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
[15]org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
[16]org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
[17]org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
[18]org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
[19]org.junit.runners.ParentRunner.run(ParentRunner.java:309)
[20]org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
[21]org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
[22]org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
[23]org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
[24]org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
[25]org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Android版本:

[0]dalvik.system.VMStack.getThreadStackTrace(Native Method)
[1]java.lang.Thread.getStackTrace(Thread.java:579)
[2]com.demo.android.annotation.view.EventListener.invokeMethod(EventListener.java:60)
[3]com.demo.android.annotation.view.EventListener.onClick(EventListener.java:52)
[4]android.view.View.performClick(View.java:4475)
[5]android.view.View$PerformClick.run(View.java:18786)
[6]android.os.Handler.handleCallback(Handler.java:730)
[7]android.os.Handler.dispatchMessage(Handler.java:92)
[8]android.os.Looper.loop(Looper.java:137)
[9]android.app.ActivityThread.main(ActivityThread.java:5493)
[10]java.lang.reflect.Method.invokeNative(Native Method)
[11]java.lang.reflect.Method.invoke(Method.java:525)
[12]com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
[13]com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
[14]dalvik.system.NativeStart.main(Native Method)
[0]dalvik.system.VMStack.getThreadStackTrace(Native Method)
[1]java.lang.Thread.getStackTrace(Thread.java:579)
[2]com.demo.android.annotation.view.EventListener.invokeMethod(EventListener.java:60)
[3]com.demo.android.annotation.view.EventListener.onClick(EventListener.java:52)
[4]java.lang.reflect.Method.invokeNative(Native Method)
[5]java.lang.reflect.Method.invoke(Method.java:525)
[6]com.demo.android.annotation.view.EventListener.invokeMethod(EventListener.java:71)
[7]com.demo.android.annotation.view.EventListener.onClick(EventListener.java:52)
[8]android.view.View.performClick(View.java:4475)
[9]android.view.View$PerformClick.run(View.java:18786)
[10]android.os.Handler.handleCallback(Handler.java:730)
[11]android.os.Handler.dispatchMessage(Handler.java:92)
[12]android.os.Looper.loop(Looper.java:137)
[13]android.app.ActivityThread.main(ActivityThread.java:5493)
[14]java.lang.reflect.Method.invokeNative(Native Method)
[15]java.lang.reflect.Method.invoke(Method.java:525)
[16]com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
[17]com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
[18]dalvik.system.NativeStart.main(Native Method)
从打印Android版本的信息发现,所有调用都源自dalvik.system.NativeStart.main(Native Method),有兴趣可以深和下。
写着写着想起当时看一个开源项目的例程打印log的个别时遭遇过这个难题(早干嘛去了java stack trace,再次指责自己的狗屎的脾气!),还提了个issue,只是没人理。。详见和
其实,日志打印工具类的实现都依赖于Thread.currentThread().getStackTrace()来获得相关信息,所以想自己写一个LogUtils,可以参考下。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/shouji/article-141180-1.html
如果缩头缩脑
猛禽配凡凡