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