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