4

I'm a beginner of Java and Android, and I was puzzled after reading the Zygote init code.

After Zygote forks a child process, at the end of invokeStaticMain, it throws a

throw new ZygoteInit.MethodAndArgsCaller(m, argv)

which is handled in ZygoteInit.main by a catch block that does the child process work

catch (MethodAndArgsCaller caller) {
    caller.run();
}

The comments of throw new ZygoteInit.MethodAndArgsCaller say it will clean up all the stack frames that were required in setting up the process.

But I can't figure out how the stack frames are cleaned up here. I checked the related SO question, What are ZygoteInit calls?, but neither the question nor its answer explain the clean up job.

Does the exception lead to stack recycle work?

Community
  • 1
  • 1
butter
  • 305
  • 4
  • 11

1 Answers1

6

Helpful Background Information

In Java, if a method completes by executing a return statement, or by successfully executing the last line of a method declared as void, then it is said to complete normally.

When a method completes normally, the JVM (Java Virtual Machine) pops the returning method's stack frame, and continues executing just after the method invocation in the calling method. The calling method becomes the current method and its stack frame becomes the current frame.

If a method throws an exception that it does not catch itself, then it is said to complete abruptly. Methods that complete abruptly do not return a value, though they do pass along an exception object, like java.io.IOException.

When a method completes abruptly, meaning it has thrown an exception that it has not caught itself, the JVM pops that method's stack frame. The JVM then examines the next method up the invocation stack for a catch clause that handles the thrown exception. This cycle continues until one of two things occurs:

  1. A method with the proper catch clause is found, wherein the JVM will make that method's stack frame current and continue execution at the first statement in the catch clause.

  2. The JVM will examine public static void main(String[] args) on the invocation stack, and when it does not find the proper catch clause, it will pop main's stack frame. The invocation stack is now empty, since main is the first method invoked by a thread. This results in an uncaught exception, which will be handled by a default handler, and the death of the thread. In most JREs (Java Runtime Environment), the default handler for an uncaught exception will print out a stack trace when a thread dies.

Information Specific to Your Question

Exceptions, or methods that complete abruptly, can be used to control the flow of a program. While 99.99 percent of the time the use of exceptions for control flow is considered an anti-pattern, there still exists that 0.01 percent of the time where it may be necessary or could drastically improve a program.

The use of exceptions as control flow can be seen throughout the com.android.internal.os.ZygoteInit class. Mainly through the use of the following exception:

/**
 * Helper exception class which holds a method and arguments and
 * can call them. This is used as part of a trampoline to get rid of
 * the initial process setup stack frames.
 */
public static class MethodAndArgsCaller extends Exception
       implements Runnable { ... }

When the method's documentation states "This is used as part of a trampoline to get rid of the initial process setup stack frames." I believe the term trampoline is referring to what I mentioned above, about the JVM popping stack frames and examining methods on the invocation stack until a proper catch clause is found. Another term for trampoline could be propagation.

The only method I have found thus far that catches a ZygoteInit.MethodAndArgsCaller exception is the ZygoteInit class' main method, which seems to be the central control. However, I have found many methods in the com.android.internal.os.RuntimeInit class that have throws ZygoteInit.MethodAndArgsCaller in their declarations. Meaning, the methods called in those methods throw or propagate the MethodAndArgsCaller exception. Who knows how far down it goes?

I'm not an expert in Android, Java or the Zygote process and I don't know the author(s), so I can only assume based off what I researched and the Android source code. I hope I helped shed some light, let me know if more help is needed.

Helpful Links

Community
  • 1
  • 1
Jonny Henly
  • 3,725
  • 4
  • 23
  • 41