blob: b209af0c25f607c4e68ce8f771305487428f3ad1 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.Set;
import java.util.TreeSet;
/**
* Writes /frameworks/base/preloaded-classes. Also updates LoadedClass.preloaded
* fields and writes over compiled log file.
*/
public class WritePreloadedClassFile {
public static void main(String[] args) throws IOException, ClassNotFoundException {
if (args.length != 1) {
System.err.println("Usage: WritePreloadedClassFile [compiled log]");
System.exit(-1);
}
String rootFile = args[0];
Root root = Root.fromFile(rootFile);
// No classes are preloaded to start.
for (LoadedClass loadedClass : root.loadedClasses.values()) {
loadedClass.preloaded = false;
}
// Open preloaded-classes file for output.
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(Policy.getPreloadedClassFileName()),
Charset.forName("US-ASCII")));
out.write("# Classes which are preloaded by com.android.internal.os.ZygoteInit.\n");
out.write("# Automatically generated by /frameworks/base/tools/preload.\n");
out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD
+ ", weight=" + ClassRank.SEQUENCE_WEIGHT
+ ", bucket_size=" + ClassRank.BUCKET_SIZE
+ "\n");
Set<LoadedClass> toPreload = new TreeSet<LoadedClass>();
// Preload all classes that were loaded by at least 2 apps, if both
// apps run at the same time, they'll share memory.
for (LoadedClass loadedClass : root.loadedClasses.values()) {
if (!loadedClass.isPreloadable()) {
continue;
}
Set<String> appNames = loadedClass.applicationNames();
if (appNames.size() > 3) {
toPreload.add(loadedClass);
}
}
// Try to make individual apps start faster by preloading slowest
// classes.
for (Proc proc : root.processes.values()) {
toPreload.addAll(proc.highestRankedClasses());
}
System.out.println(toPreload.size() + " classes will be preloaded.");
// Make classes that were already loaded by the zygote explicit.
// This adds minimal overhead but avoid confusion about classes not
// appearing in the list.
addAllClassesFor("zygote", root, toPreload);
for (LoadedClass loadedClass : toPreload) {
out.write(loadedClass.name);
out.write('\n');
}
out.close();
// Update data to reflect LoadedClass.preloaded changes.
for (LoadedClass loadedClass : toPreload) {
loadedClass.preloaded = true;
}
root.toFile(rootFile);
}
private static void addAllClassesFor(String packageName, Root root,
Set<LoadedClass> toPreload) {
for (Proc proc : root.processes.values()) {
if (proc.name.equals(packageName)) {
for (Operation operation : proc.operations) {
// TODO: I'm not sure how the zygote loaded classes that
// aren't supposed to be preloadable...
if (operation.loadedClass.isPreloadable()) {
toPreload.add(operation.loadedClass);
}
}
}
}
}
}