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 static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 20 21 import android.annotation.SystemApi; 22 23 import libcore.icu.ICU; 24 25 import java.io.File; 26 import java.io.FileDescriptor; 27 import java.lang.reflect.Method; 28 import java.lang.ClassNotFoundException; 29 import java.lang.NoSuchMethodException; 30 import java.lang.ReflectiveOperationException; 31 32 /** 33 * Provides hooks for the zygote to call back into the runtime to perform 34 * parent or child specific initialization.. 35 * 36 * @hide 37 */ 38 @SystemApi(client = MODULE_LIBRARIES) 39 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) 40 public final class ZygoteHooks { 41 private static long token; 42 private static Method enableMemoryMappedDataMethod; 43 44 /** All methods are static, no need to instantiate. */ ZygoteHooks()45 private ZygoteHooks() { 46 } 47 48 /** 49 * Called by the zygote when starting up. It marks the point when any thread 50 * start should be an error, as only internal daemon threads are allowed there. 51 * 52 * @hide 53 */ 54 @SystemApi(client = MODULE_LIBRARIES) 55 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) startZygoteNoThreadCreation()56 public static native void startZygoteNoThreadCreation(); 57 58 /** 59 * Called when the zygote begins preloading classes and data. 60 * 61 * @hide 62 */ 63 @SystemApi(client = MODULE_LIBRARIES) 64 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onBeginPreload()65 public static void onBeginPreload() { 66 com.android.i18n.system.ZygoteHooks.onBeginPreload(); 67 68 ICU.initializeCacheInZygote(); 69 70 // Look up JaCoCo on the boot classpath, if it exists. This will be used later for enabling 71 // memory-mapped Java coverage. 72 try { 73 Class<?> jacocoOfflineClass = Class.forName("org.jacoco.agent.rt.internal.Offline"); 74 enableMemoryMappedDataMethod = jacocoOfflineClass.getMethod("enableMemoryMappedData"); 75 } catch (ClassNotFoundException e) { 76 // JaCoCo was not on the boot classpath, so this is not a coverage build. 77 } catch (NoSuchMethodException e) { 78 // Method was not found in the JaCoCo Offline class. The version of JaCoCo is not 79 // compatible with memory-mapped coverage. 80 throw new RuntimeException(e); 81 } 82 } 83 84 /** 85 * Called when the zygote has completed preloading classes and data. 86 * 87 * @hide 88 */ 89 @SystemApi(client = MODULE_LIBRARIES) 90 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) onEndPreload()91 public static void onEndPreload() { 92 com.android.i18n.system.ZygoteHooks.onEndPreload(); 93 94 // Clone standard descriptors as originals closed / rebound during zygote post fork. 95 FileDescriptor.in.cloneForFork(); 96 FileDescriptor.out.cloneForFork(); 97 FileDescriptor.err.cloneForFork(); 98 } 99 100 /** 101 * Runs several special GCs to try to clean up a few generations of 102 * softly- and final-reachable objects, along with any other garbage. 103 * This is only useful just before a fork(). 104 * 105 * @hide 106 */ 107 @SystemApi(client = MODULE_LIBRARIES) 108 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) gcAndFinalize()109 public static void gcAndFinalize() { 110 final VMRuntime runtime = VMRuntime.getRuntime(); 111 112 /* runFinalizationSync() lets finalizers be called in Zygote, 113 * which doesn't have a HeapWorker thread. 114 */ 115 System.gc(); 116 runtime.runFinalizationSync(); 117 System.gc(); 118 } 119 120 /** 121 * Called by the zygote when startup is finished. It marks the point when it is 122 * conceivable that threads would be started again, e.g., restarting daemons. 123 * 124 * @hide 125 */ 126 @SystemApi(client = MODULE_LIBRARIES) 127 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) stopZygoteNoThreadCreation()128 public static native void stopZygoteNoThreadCreation(); 129 130 /** 131 * Called by the zygote prior to every fork. Each call to {@code preFork} 132 * is followed by a matching call to {@link #postForkChild(int, boolean, boolean, String)} on 133 * the child process and {@link #postForkCommon()} on both the parent and the child 134 * process. {@code postForkCommon} is called after {@code postForkChild} in 135 * the child process. 136 * 137 * @hide 138 */ 139 @SystemApi(client = MODULE_LIBRARIES) 140 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) preFork()141 public static void preFork() { 142 Daemons.stop(); 143 token = nativePreFork(); 144 waitUntilAllThreadsStopped(); 145 } 146 147 /** 148 * Called by the zygote in the system server process after forking. This method is is called 149 * before {@code postForkChild} for system server. 150 * 151 * @param runtimeFlags The flags listed in com.android.internal.os.Zygote passed to the runtime. 152 * 153 * @hide 154 */ 155 @SystemApi(client = MODULE_LIBRARIES) 156 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) postForkSystemServer(int runtimeFlags)157 public static void postForkSystemServer(int runtimeFlags) { 158 nativePostForkSystemServer(runtimeFlags); 159 } 160 161 /** 162 * Called by the zygote in the child process after every fork. 163 * 164 * @param runtimeFlags The runtime flags to apply to the child process. 165 * @param isSystemServer Whether the child process is system server. 166 * @param isChildZygote Whether the child process is a child zygote. 167 * @param instructionSet The instruction set of the child, used to determine 168 * whether to use a native bridge. 169 * 170 * @hide 171 */ 172 @SystemApi(client = MODULE_LIBRARIES) 173 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) postForkChild(int runtimeFlags, boolean isSystemServer, boolean isChildZygote, String instructionSet)174 public static void postForkChild(int runtimeFlags, boolean isSystemServer, 175 boolean isChildZygote, String instructionSet) { 176 nativePostForkChild(token, runtimeFlags, isSystemServer, isChildZygote, instructionSet); 177 178 Math.setRandomSeedInternal(System.currentTimeMillis()); 179 180 // Enable memory-mapped coverage if JaCoCo is in the boot classpath. system_server is 181 // skipped due to being persistent and having its own coverage writing mechanism. 182 if (!isSystemServer && enableMemoryMappedDataMethod != null) { 183 try { 184 enableMemoryMappedDataMethod.invoke(null); 185 } catch (ReflectiveOperationException e) { 186 throw new RuntimeException(e); 187 } 188 } 189 } 190 191 /** 192 * Called by the zygote in both the parent and child processes after 193 * every fork. In the child process, this method is called after 194 * {@code postForkChild}. 195 * 196 * @hide 197 */ 198 @SystemApi(client = MODULE_LIBRARIES) 199 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) postForkCommon()200 public static void postForkCommon() { 201 // Notify the runtime before creating new threads. 202 nativePostZygoteFork(); 203 Daemons.startPostZygoteFork(); 204 } 205 206 /** 207 * Is it safe to keep all ART daemon threads stopped indefinitely in the zygote? 208 * The answer may change from false to true dynamically, but not in the other 209 * direction. Only called in Zygote. 210 * 211 * @return {@code true} if it's safe to keep all ART daemon threads stopped 212 * indefinitely in the zygote; and {@code false} otherwise 213 * 214 * @hide 215 */ 216 @SystemApi(client = MODULE_LIBRARIES) 217 @libcore.api.CorePlatformApi(status = libcore.api.CorePlatformApi.Status.STABLE) isIndefiniteThreadSuspensionSafe()218 public static boolean isIndefiniteThreadSuspensionSafe() { 219 return nativeZygoteLongSuspendOk(); 220 } 221 222 // Hook for SystemServer specific early initialization post-forking. nativePostForkSystemServer(int runtimeFlags)223 private static native void nativePostForkSystemServer(int runtimeFlags); 224 nativePreFork()225 private static native long nativePreFork(); nativePostZygoteFork()226 private static native void nativePostZygoteFork(); 227 228 // Hook for all child processes post forking. nativePostForkChild(long token, int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)229 private static native void nativePostForkChild(long token, int runtimeFlags, 230 boolean isSystemServer, boolean isZygote, 231 String instructionSet); 232 nativeZygoteLongSuspendOk()233 private static native boolean nativeZygoteLongSuspendOk(); 234 235 /** 236 * We must not fork until we're single-threaded again. Wait until /proc shows we're 237 * down to just one thread. 238 */ waitUntilAllThreadsStopped()239 private static void waitUntilAllThreadsStopped() { 240 File tasks = new File("/proc/self/task"); 241 // All Java daemons are stopped already. We're just waiting for their OS counterparts to 242 // finish as well. This shouldn't take much time so spinning is ok here. 243 while (tasks.list().length > 1) { 244 Thread.yield(); 245 } 246 } 247 } 248