RuntimeInitpublic class RuntimeInit extends Object Main entry point for runtime initialization. Not for
public consumption. |
Fields Summary |
---|
private static final String | TAG | private static boolean | initializedtrue if commonInit() has been called | private static final AtomicInteger | sInReportExceptionCounter used to prevent reentrancy in {@link #reportException}. | private static android.os.IBinder | mApplicationObjectEnable debugging features. |
Methods Summary |
---|
private static final void | commonInit()
if (Config.LOGV) Log.d(TAG, "Entered RuntimeInit!");
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
int hasQwerty = getQwertyKeyboard();
if (Config.LOGV) Log.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty);
if (hasQwerty == 1) {
System.setProperty("qwerty", "1");
}
/*
* Install a TimezoneGetter subclass for ZoneInfo.db
*/
TimezoneGetter.setInstance(new TimezoneGetter() {
@Override
public String getId() {
return SystemProperties.get("persist.sys.timezone");
}
});
TimeZone.setDefault(null);
/*
* Sets handler for java.util.logging to use Android log facilities.
* The odd "new instance-and-then-throw-away" is a mirror of how
* the "java.util.logging.config.class" system property works. We
* can't use the system property here since the logger has almost
* certainly already been initialized.
*/
LogManager.getLogManager().reset();
new AndroidConfig();
/*
* If we're running in an emulator launched with "-trace", put the
* VM into emulator trace profiling mode so that the user can hit
* F9/F10 at any time to capture traces. This has performance
* consequences, so it's not something you want to do always.
*/
String trace = SystemProperties.get("ro.kernel.android.tracing");
if (trace.equals("1")) {
Log.i(TAG, "NOTE: emulator trace profiling enabled");
Debug.enableEmulatorTraceOutput();
}
initialized = true;
| public static void | crash(java.lang.String tag, java.lang.Throwable t)Report a fatal error in the current process. If this is a user-process,
a dialog may be displayed informing the user of the error. This
function does not return; it forces the current process to exit.
if (mApplicationObject != null) {
byte[] crashData = null;
try {
// Log exception.
Log.e(TAG, Log.getStackTraceString(t));
crashData = marshallException(tag, t);
if (crashData == null) {
throw new NullPointerException("Can't marshall crash data");
}
} catch (Throwable t2) {
try {
// Log exception as a string so we don't get in an infinite loop.
Log.e(TAG, "Error reporting crash: "
+ Log.getStackTraceString(t2));
} catch (Throwable t3) {
// Do nothing, must be OOM so we can't format the message
}
}
try {
// Display user-visible error message.
String msg = t.getMessage();
if (msg == null) {
msg = t.toString();
}
IActivityManager am = ActivityManagerNative.getDefault();
try {
int res = am.handleApplicationError(mApplicationObject,
0, tag, msg, t.toString(), crashData);
// Is waiting for the debugger the right thing?
// For now I have turned off the Debug button, because
// I'm not sure what we should do if it is actually
// selected.
//Log.i(TAG, "Got app error result: " + res);
if (res == 1) {
Debug.waitForDebugger();
return;
}
} catch (RemoteException e) {
}
} catch (Throwable t2) {
try {
// Log exception as a string so we don't get in an infinite loop.
Log.e(TAG, "Error reporting crash: "
+ Log.getStackTraceString(t2));
} catch (Throwable t3) {
// Do nothing, must be OOM so we can't format the message
}
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
} else {
try {
Log.e(TAG, "*** EXCEPTION IN SYSTEM PROCESS. System will crash.");
Log.e(tag, Log.getStackTraceString(t));
reportException(tag, t, true); // synchronous
} catch (Throwable t2) {
// Do nothing, must be OOM so we can't format the message
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
| public static final native void | finishInit()
| public static native int | getQwertyKeyboard()
| private static void | invokeStaticMain(java.lang.String className, java.lang.String[] argv)Invokes a static "main(argv[]) method on class "className".
Converts various failing exceptions into RuntimeExceptions, with
the assumption that they will then cause the VM instance to exit.
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Class<?> cl;
try {
cl = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
| public static final native int | isComputerOn()Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined.
| public static final void | main(java.lang.String[] argv)
commonInit();
/*
* Now that we're running in interpreted code, call back into native code
* to run the system.
*/
finishInit();
if (Config.LOGV) Log.d(TAG, "Leaving RuntimeInit!");
| private static byte[] | marshallException(java.lang.String tag, java.lang.Throwable t)
// Convert crash data to bytes.
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
new CrashData(tag, t).write(dout);
dout.close();
} catch (IOException e) {
return null;
}
return bout.toByteArray();
| public static void | reportException(java.lang.String tag, java.lang.Throwable t, boolean sync)Report an error in the current process. The exception information will
be handed off to the checkin service and eventually uploaded for analysis.
This is expensive! Only use this when the exception indicates a programming
error ("should not happen").
if (!initialized) {
// Exceptions during, eg, zygote cannot use this mechanism
return;
}
// It's important to prevent an infinite crash-reporting loop:
// while this function is running, don't let it be called again.
int reenter = sInReportException.getAndIncrement();
if (reenter != 0) {
sInReportException.decrementAndGet();
Log.e(TAG, "Crash logging skipped, already logging another crash");
return;
}
// TODO: Enable callers to specify a level (i.e. warn or error).
try {
// Submit crash data to statistics service.
byte[] crashData = marshallException(tag, t);
ICheckinService checkin = ICheckinService.Stub.asInterface(
ServiceManager.getService("checkin"));
if (checkin == null) {
Log.e(TAG, "Crash logging skipped, no checkin service");
} else if (sync) {
checkin.reportCrashSync(crashData);
} else {
checkin.reportCrashAsync(crashData);
}
} catch (Throwable t2) {
// Log exception as a string so we don't get in an infinite loop.
Log.e(TAG, "Crash logging failed: " + t2);
} finally {
sInReportException.decrementAndGet();
}
| public static final void | setApplicationObject(android.os.IBinder app)Set the object identifying this application/process, for reporting VM
errors.
mApplicationObject = app;
| public static final native void | turnComputerOn()Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined.
| public static android.server.data.CrashData | unmarshallException(byte[] crashDataBytes)Replay an encoded CrashData record back into a useable CrashData record. This can be
helpful for providing debugging output after a process error.
try {
ByteArrayInputStream bin = new ByteArrayInputStream(crashDataBytes);
DataInputStream din = new DataInputStream(bin);
return new CrashData(din);
} catch (IOException e) {
return null;
}
| public static final void | zygoteInit(java.lang.String[] argv)The main function called when started through the zygote process. This
could be unified with main(), if the native code in finishInit()
were rationalized with Zygote startup.
Current recognized args:
- --nice-name=nice name to appear in ps
-
[--] <start class name> <args>
// TODO: Doing this here works, but it seems kind of arbitrary. Find
// a better place. The goal is to set it up for applications, but not
// tools like am.
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
commonInit();
zygoteInitNative();
int curArg = 0;
for ( /* curArg */ ; curArg < argv.length; curArg++) {
String arg = argv[curArg];
if (arg.equals("--")) {
curArg++;
break;
} else if (!arg.startsWith("--")) {
break;
} else if (arg.startsWith("--nice-name=")) {
String niceName = arg.substring(arg.indexOf('=") + 1);
Process.setArgV0(niceName);
}
}
if (curArg == argv.length) {
Log.e(TAG, "Missing classname argument to RuntimeInit!");
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg];
System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
invokeStaticMain(startClass, startArgs);
| public static final native void | zygoteInitNative()
|
|