1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dalvik.system; 18 19 import android.icu.impl.CacheValue; 20 import android.icu.text.DateFormatSymbols; 21 import android.icu.text.DecimalFormatSymbols; 22 import android.icu.util.ULocale; 23 24 import java.io.File; 25 import java.io.FileDescriptor; 26 27 /** 28 * Provides hooks for the zygote to call back into the runtime to perform 29 * parent or child specific initialization.. 30 * 31 * @hide 32 */ 33 @libcore.api.CorePlatformApi 34 public final class ZygoteHooks { 35 private static long token; 36 37 /** All methods are static, no need to instantiate. */ ZygoteHooks()38 private ZygoteHooks() { 39 } 40 41 /** 42 * Called by the zygote when starting up. It marks the point when any thread 43 * start should be an error, as only internal daemon threads are allowed there. 44 */ 45 @libcore.api.CorePlatformApi startZygoteNoThreadCreation()46 public static native void startZygoteNoThreadCreation(); 47 48 /** 49 * Called when the zygote begins preloading classes and data. 50 */ 51 @libcore.api.CorePlatformApi onBeginPreload()52 public static void onBeginPreload() { 53 // Pin ICU data in memory from this point that would normally be held by soft references. 54 // Without this, any references created immediately below or during class preloading 55 // would be collected when the Zygote GC runs in gcAndFinalize(). 56 CacheValue.setStrength(CacheValue.Strength.STRONG); 57 58 // Explicitly exercise code to cache data apps/framework are likely to need. 59 ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() }; 60 for (ULocale uLocale : localesToPin) { 61 new DecimalFormatSymbols(uLocale); 62 new DateFormatSymbols(uLocale); 63 } 64 65 // Framework's LocalLog is used during app start-up. It indirectly uses the current ICU time 66 // zone. Pre-loading the current time zone in ICU improves app startup time. b/150605074 67 // We're being explicit about the fully qualified name of the TimeZone class to avoid 68 // confusion with java.util.TimeZome.getDefault(). 69 android.icu.util.TimeZone.getDefault(); 70 } 71 72 /** 73 * Called when the zygote has completed preloading classes and data. 74 */ 75 @libcore.api.CorePlatformApi onEndPreload()76 public static void onEndPreload() { 77 // All cache references created by ICU from this point will be soft. 78 CacheValue.setStrength(CacheValue.Strength.SOFT); 79 80 // Clone standard descriptors as originals closed / rebound during zygote post fork. 81 FileDescriptor.in.cloneForFork(); 82 FileDescriptor.out.cloneForFork(); 83 FileDescriptor.err.cloneForFork(); 84 } 85 86 /** 87 * Runs several special GCs to try to clean up a few generations of 88 * softly- and final-reachable objects, along with any other garbage. 89 * This is only useful just before a fork(). 90 */ 91 @libcore.api.CorePlatformApi gcAndFinalize()92 public static void gcAndFinalize() { 93 final VMRuntime runtime = VMRuntime.getRuntime(); 94 95 /* runFinalizationSync() lets finalizers be called in Zygote, 96 * which doesn't have a HeapWorker thread. 97 */ 98 System.gc(); 99 runtime.runFinalizationSync(); 100 System.gc(); 101 } 102 103 /** 104 * Called by the zygote when startup is finished. It marks the point when it is 105 * conceivable that threads would be started again, e.g., restarting daemons. 106 */ 107 @libcore.api.CorePlatformApi stopZygoteNoThreadCreation()108 public static native void stopZygoteNoThreadCreation(); 109 110 /** 111 * Called by the zygote prior to every fork. Each call to {@code preFork} 112 * is followed by a matching call to {@link #postForkChild(int, boolean, boolean, String)} on 113 * the child process and {@link #postForkCommon()} on both the parent and the child 114 * process. {@code postForkCommon} is called after {@code postForkChild} in 115 * the child process. 116 */ 117 @libcore.api.CorePlatformApi preFork()118 public static void preFork() { 119 Daemons.stop(); 120 token = nativePreFork(); 121 waitUntilAllThreadsStopped(); 122 } 123 124 /** 125 * Called by the zygote in the system server process after forking. This method is is called 126 * before {@code postForkChild} for system server. 127 */ 128 @libcore.api.CorePlatformApi postForkSystemServer(int runtimeFlags)129 public static void postForkSystemServer(int runtimeFlags) { 130 nativePostForkSystemServer(runtimeFlags); 131 } 132 133 /** 134 * Called by the zygote in the child process after every fork. The runtime 135 * flags from {@code runtimeFlags} are applied to the child process. The string 136 * {@code instructionSet} determines whether to use a native bridge. 137 */ 138 @libcore.api.CorePlatformApi postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)139 public static void postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote, 140 String instructionSet) { 141 nativePostForkChild(token, runtimeFlags, isSystemServer, isZygote, instructionSet); 142 143 Math.setRandomSeedInternal(System.currentTimeMillis()); 144 } 145 146 /** 147 * Called by the zygote in both the parent and child processes after 148 * every fork. In the child process, this method is called after 149 * {@code postForkChild}. 150 */ 151 @libcore.api.CorePlatformApi postForkCommon()152 public static void postForkCommon() { 153 // Notify the runtime before creating new threads. 154 nativePostZygoteFork(); 155 Daemons.startPostZygoteFork(); 156 } 157 158 159 // Hook for SystemServer specific early initialization post-forking. nativePostForkSystemServer(int runtimeFlags)160 private static native void nativePostForkSystemServer(int runtimeFlags); 161 nativePreFork()162 private static native long nativePreFork(); nativePostZygoteFork()163 private static native void nativePostZygoteFork(); 164 165 // Hook for all child processes post forking. nativePostForkChild(long token, int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)166 private static native void nativePostForkChild(long token, int runtimeFlags, 167 boolean isSystemServer, boolean isZygote, 168 String instructionSet); 169 170 /** 171 * We must not fork until we're single-threaded again. Wait until /proc shows we're 172 * down to just one thread. 173 */ waitUntilAllThreadsStopped()174 private static void waitUntilAllThreadsStopped() { 175 File tasks = new File("/proc/self/task"); 176 // All Java daemons are stopped already. We're just waiting for their OS counterparts to 177 // finish as well. This shouldn't take much time so spinning is ok here. 178 while (tasks.list().length > 1) { 179 Thread.yield(); 180 } 181 } 182 } 183