TouchDex.java revision 72e93344b4d1ffc71e9c832ec23de0657e5b04a5
1/* 2 * Copyright (C) 2007 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 17package dalvik.system; 18 19import java.io.BufferedReader; 20import java.io.InputStreamReader; 21import java.io.IOException; 22import java.io.File; 23import java.io.FilenameFilter; 24 25/** 26 * Induces optimization/verification of a set of DEX files. 27 * 28 * @deprecated this is an internal Dalvik class that is not appropriate for 29 * general use. It will be removed from the public API in a future release. 30 */ 31public class TouchDex { 32 33 /** 34 * Forks a process, makes sure the DEX files are prepared, and returns 35 * when everything is finished. 36 * <p> 37 * The filenames must be the same as will be used when the files are 38 * actually opened, because the dalvik-cache filename is based upon 39 * this filename. (The absolute path to the JAR/ZIP/APK should work.) 40 * 41 * @param dexFiles a colon-separated list of DEX files. 42 * @return zero on success 43 * 44 * @cts What about error cases? 45 */ 46 public static int start(String dexFiles) { 47 return trampoline(dexFiles, System.getProperty("java.boot.class.path")); 48 } 49 50 /** 51 * This calls fork() and then, in the child, calls cont(dexFiles). 52 * 53 * @param dexFiles Colon-separated list of DEX files. 54 * @return zero on success 55 */ 56 native private static int trampoline(String dexFiles, String bcp); 57 58 /** 59 * The entry point for the child process. args[0] can be a colon-separated 60 * path list, or "-" to read from stdin. 61 * <p> 62 * Alternatively, if we're invoked directly from the command line we 63 * just start here (skipping the fork/exec stuff). 64 * 65 * @param args command line args 66 */ 67 public static void main(String[] args) { 68 69 if ("-".equals(args[0])) { 70 BufferedReader in = new BufferedReader( 71 new InputStreamReader(System.in), 256); 72 73 String line; 74 try { 75 while ((line = in.readLine()) != null) { 76 prepFiles(line); 77 } 78 } catch (IOException ex) { 79 throw new RuntimeException ("Error processing stdin"); 80 } 81 } else { 82 prepFiles(args[0]); 83 } 84 85 System.out.println(" Prep complete"); 86 } 87 88 89 private static String expandDirectories(String dexPath) { 90 String[] parts = dexPath.split(":"); 91 StringBuilder outPath = new StringBuilder(dexPath.length()); 92 93 // A filename filter accepting *.jar and *.apk 94 FilenameFilter filter = new FilenameFilter() { 95 public boolean accept(File dir, String name) { 96 return name.endsWith(".jar") || name.endsWith(".apk"); 97 } 98 }; 99 100 for (String part: parts) { 101 File f = new File(part); 102 103 if (f.isFile()) { 104 outPath.append(part); 105 outPath.append(':'); 106 } else if (f.isDirectory()) { 107 String[] filenames = f.list(filter); 108 109 if (filenames == null) { 110 System.err.println("I/O error with directory: " + part); 111 continue; 112 } 113 114 for (String filename: filenames) { 115 outPath.append(part); 116 outPath.append(File.separatorChar); 117 outPath.append(filename); 118 outPath.append(':'); 119 } 120 } else { 121 System.err.println("File not found: " + part); 122 } 123 } 124 125 126 return outPath.toString(); 127 } 128 129 private static void prepFiles(String dexPath) { 130 131 System.out.println(" Prepping: " + dexPath); 132 133 TouchDexLoader loader 134 = new TouchDexLoader(expandDirectories(dexPath), null); 135 136 try { 137 /* By looking for a nonexistent class, we'll trick TouchDexLoader 138 * into trying to load something from every file on dexPath, 139 * optimizing all of them as a side-effect. 140 * 141 * The optimization happens implicitly in the VM the first time 142 * someone tries to load a class from an unoptimized dex file. 143 */ 144 loader.loadClass("com.google.NonexistentClassNeverFound"); 145 throw new RuntimeException("nonexistent class loaded?!"); 146 } catch (ClassNotFoundException cnfe) { 147 //System.out.println("got expected dnfe"); 148 } 149 } 150} 151 152