The main method runs in a separate JVM thread, this is the parent thread of the child thread, so you do not see the child thread at the top of the call hierarchy.
So, in your case, the JVM created a thread that runs your program, which also extends Thread.
Then in your main method, you created a new instance of your class called start on it. This will start a new thread, which is a child thread launched by the JVM to run your program.
Since the main method is the starting point for a stand-alone java program, it is the responsibility of the JVM to run in a separate thread, you do not write code for it.
When starting a program by calling the main method, the JVM does not need to be a thread or implement Runnable, this is the standard procedure.
Description from Inside the Java Virtual Machine
The main () method of the application's source class serves as a starting point for this application seed. The starting thread may in turn disable other threads.
In the Java virtual machine, threads are presented in two versions: daemon and non-daemon. A daemon thread is usually a thread used by the virtual machine itself, such as a thread that runs the garbage collection. However, an application can mark any threads it creates as daemon threads. The initial thread of the application - the one that starts with main () - is a thread without a daemon.
The Java application continues to run (the virtual machine instance continues to live) as long as any non-daemon threads are still running. When all non-daemon threads of a Java application terminate, the virtual machine instance terminates. If allowed by the protection manager, the application can also cause its own demise by calling exit () of the Runtime or System class.
The call hierarchy is not controlled by you; it is managed by the main thread scheduler.
So, for example, if I run the same code on my machine, this is the output file
Exception in thread "main" java.lang.RuntimeException: Exception from main thread at TestThread.main(TestThread.java:6) Exception in thread "Thread-1" java.lang.RuntimeException: Exception from child thread at TestThread.run(TestThread.java:9) at java.lang.Thread.run(Thread.java:662)
therefore, when you run your example, the scheduler decided to release the child thread first before the main one.
Adding to @JB Nizet how the program will be called or how the life cycle of the stream will be implemented depends on the underlying OS and hardware, which will and will change.
No implementation details would provide a complete answer; each implementation would be different.