Let’s start with the following code:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test1();
    }

    private void test1(a) {
        test2();
    }

    private void test2(a) {
        test3();
    }

    private void test3(a) {
        test4();
    }

    private void test4(a) {
        Log.d("wxl"."test".newException()); }}Copy the code

Guess what they print?

12-29 12:16:05.479 8140-8140/com.wuxiaolong.myapplication D/wxl: test
    java.lang.Exception
        at com.wuxiaolong.myapplication.MainActivity.test4(MainActivity.java:29)
        at com.wuxiaolong.myapplication.MainActivity.test3(MainActivity.java:25)
        at com.wuxiaolong.myapplication.MainActivity.test2(MainActivity.java:21)
        at com.wuxiaolong.myapplication.MainActivity.test1(MainActivity.java:17)
        at com.wuxiaolong.myapplication.MainActivity.onCreate(MainActivity.java:13)
        at android.app.Activity.performCreate(Activity.java:6975)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Copy the code

Test4 (); test4(); test4(); Is there a place to preserve this step by step relationship?

Log.d() :

public static int d(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr));
}

public static String getStackTraceString(Throwable tr) {
    if (tr == null) {
        return "";
    }
    // This is to reduce the amount of log spew that apps do in the non-error
    // condition of the network being unavailable.
    Throwable t = tr;
    while(t ! =null) {
        if (t instanceof UnknownHostException) {
            return "";
        }
        t = t.getCause();
    }
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    tr.printStackTrace(pw);
    pw.flush();
    return sw.toString();
}
Copy the code

The third parameter Exception is a subclass of Throwable, initialized by the Throwable constructor:

public Throwable(String message) {
    fillInStackTrace();
    detailMessage = message;
}

/**
 * Fills in the execution stack trace. This method records within this
 * {@code Throwable} object information about the current state of
 * the stack frames for the current thread.
 *
 * <p>If the stack trace of this {@code Throwable} {@linkplain
 * Throwable#Throwable(String, Throwable, boolean, boolean) is not
 * writable}, calling this method has no effect.
 *
 * @return  a reference to this {@code Throwable} instance.
 * @see     java.lang.Throwable#printStackTrace()
 */
public synchronized Throwable fillInStackTrace(a) {
    if(stackTrace ! =null|| backtrace ! =null /* Out of protocol state */ ) {
        backtrace = nativeFillInStackTrace();
        stackTrace = libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
    }
    return this;
}
Copy the code

FillInStackTrace (), as you might expect, traces method calls step by step until the end of the thread is traced. FillInStackTrace is a native method, so I’m not going to follow it.

An Exception represents an Exception error that can be caught and handled by a program, and the JVM tracks a series of method calls in each thread using a method call stack that holds local information about each called method.

When a new method is called, the JVM places the stack structure describing the method at the top of the stack. The method at the top of the stack is the correctly executed method. When a Java method completes its normal execution, the JVM pops the stack structure of that method from the call stack. If a Java method throws an exception during code execution, the JVM must find a catch block that can catch the exception. It first looks to see if such a catch block exists in the current method and executes it if it does. Otherwise, the JVM returns to the stack structure of the method at the top of the stack and continues to look for the appropriate catch block in the previous method. Finally, if the JVM reaches up to main(), that is, it throws the exception all the way to main() and still does not find the exception block, the thread terminates abnormally. If the thread is the main thread, the application terminates, and the JVM throws the exception directly to the user, where the original exception message is seen on the user terminal.

My public number: Wu Xiaolong students, welcome to pay attention to exchange, public number reply keyword “1024” have a surprise oh.