diff options
-rw-r--r-- | dalvik/src/main/java/dalvik/system/TouchDex.java | 147 | ||||
-rw-r--r-- | dalvik/src/main/java/dalvik/system/TouchDexLoader.java | 298 | ||||
-rw-r--r-- | dalvik/src/main/native/dalvik_system_TouchDex.cpp | 269 | ||||
-rw-r--r-- | dalvik/src/main/native/sub.mk | 2 | ||||
-rw-r--r-- | luni/src/main/native/Register.cpp | 11 |
5 files changed, 3 insertions, 724 deletions
diff --git a/dalvik/src/main/java/dalvik/system/TouchDex.java b/dalvik/src/main/java/dalvik/system/TouchDex.java deleted file mode 100644 index 53cd00c..0000000 --- a/dalvik/src/main/java/dalvik/system/TouchDex.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -package dalvik.system; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * Induces optimization/verification of a set of DEX files. - * - * @hide - */ -public class TouchDex { - - /** - * Forks a process, makes sure the DEX files are prepared, and returns - * when everything is finished. - * <p> - * The filenames must be the same as will be used when the files are - * actually opened, because the dalvik-cache filename is based upon - * this filename. (The absolute path to the JAR/ZIP/APK should work.) - * - * @param dexFiles a colon-separated list of DEX files. - * @return zero on success - */ - public static int start(String dexFiles) { - return trampoline(dexFiles, System.getProperty("java.boot.class.path")); - } - - /** - * This calls fork() and then, in the child, calls cont(dexFiles). - * - * @param dexFiles Colon-separated list of DEX files. - * @return zero on success - */ - native private static int trampoline(String dexFiles, String bcp); - - /** - * The entry point for the child process. args[0] can be a colon-separated - * path list, or "-" to read from stdin. - * <p> - * Alternatively, if we're invoked directly from the command line we - * just start here (skipping the fork/exec stuff). - * - * @param args command line args - */ - public static void main(String[] args) { - - if ("-".equals(args[0])) { - BufferedReader in = new BufferedReader( - new InputStreamReader(System.in), 256); - - String line; - try { - while ((line = in.readLine()) != null) { - prepFiles(line); - } - } catch (IOException ex) { - throw new RuntimeException ("Error processing stdin"); - } - } else { - prepFiles(args[0]); - } - - System.out.println(" Prep complete"); - } - - - private static String expandDirectories(String dexPath) { - String[] parts = dexPath.split(":"); - StringBuilder outPath = new StringBuilder(dexPath.length()); - - // A filename filter accepting *.jar and *.apk - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".jar") || name.endsWith(".apk"); - } - }; - - for (String part: parts) { - File f = new File(part); - - if (f.isFile()) { - outPath.append(part); - outPath.append(':'); - } else if (f.isDirectory()) { - String[] filenames = f.list(filter); - - if (filenames == null) { - System.err.println("I/O error with directory: " + part); - continue; - } - - for (String filename: filenames) { - outPath.append(part); - outPath.append(File.separatorChar); - outPath.append(filename); - outPath.append(':'); - } - } else { - System.err.println("File not found: " + part); - } - } - - - return outPath.toString(); - } - - private static void prepFiles(String dexPath) { - - System.out.println(" Prepping: " + dexPath); - - TouchDexLoader loader - = new TouchDexLoader(expandDirectories(dexPath), null); - - try { - /* By looking for a nonexistent class, we'll trick TouchDexLoader - * into trying to load something from every file on dexPath, - * optimizing all of them as a side-effect. - * - * The optimization happens implicitly in the VM the first time - * someone tries to load a class from an unoptimized dex file. - */ - loader.loadClass("com.google.NonexistentClassNeverFound"); - throw new RuntimeException("nonexistent class loaded?!"); - } catch (ClassNotFoundException cnfe) { - //System.out.println("got expected dnfe"); - } - } -} diff --git a/dalvik/src/main/java/dalvik/system/TouchDexLoader.java b/dalvik/src/main/java/dalvik/system/TouchDexLoader.java deleted file mode 100644 index 63cbea9..0000000 --- a/dalvik/src/main/java/dalvik/system/TouchDexLoader.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -package dalvik.system; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import libcore.io.IoUtils; - -/** - * Cloned out of PathClassLoader for TouchDex. This could be made - * substantially smaller, since we don't need most of this. - */ -class TouchDexLoader extends ClassLoader { - - private String path; - - /* - * Parallel arrays for jar/apk files. - * - * (could stuff these into an object and have a single array; - * improves clarity but adds overhead) - */ - private final String[] mPaths; - private final File[] mFiles; - private final ZipFile[] mZips; - private final DexFile[] mDexs; - - /** - * Native library path. - */ - private final String[] mLibPaths; - - /** - * Create a ClassLoader that finds files in the specified path. - */ - public TouchDexLoader(String path, ClassLoader parent) { - super(parent); - - if (path == null) - throw new NullPointerException(); - - this.path = path; - - mPaths = path.split(":"); - //System.out.println("TouchDexLoader: " + mPaths); - mFiles = new File[mPaths.length]; - mZips = new ZipFile[mPaths.length]; - mDexs = new DexFile[mPaths.length]; - - /* open all Zip and DEX files up front */ - for (int i = 0; i < mPaths.length; i++) { - //System.out.println("My path is: " + mPaths[i]); - File pathFile = new File(mPaths[i]); - mFiles[i] = pathFile; - - if (pathFile.isFile()) { - /* we need both DEX and Zip, because dex has no resources */ - try { - mDexs[i] = new DexFile(pathFile); - } catch (IOException ioex) { - System.err.println("Couldn't open " + mPaths[i] + " as DEX"); - } - } else { - System.err.println("File not found: " + mPaths[i]); - } - } - - /* - * Prep for native library loading. - */ - String pathList = System.getProperty("java.library.path", "."); - String pathSep = System.getProperty("path.separator", ":"); - String fileSep = System.getProperty("file.separator", "/"); - - mLibPaths = pathList.split(pathSep); - - // Add a '/' to the end so we don't have to do the property lookup - // and concatenation later. - for (int i = 0; i < mLibPaths.length; i++) { - if (!mLibPaths[i].endsWith(fileSep)) - mLibPaths[i] += fileSep; - if (false) - System.out.println("Native lib path: " + mLibPaths[i]); - } - } - - /** - * Find the class with the specified name. None of our ancestors were - * able to find it, so it's up to us now. - * - * "name" is a "binary name", e.g. "java.lang.String" or - * "java.net.URLClassLoader$3$1". - * - * This method will either return a valid Class object or throw an - * exception. Does not return null. - */ - protected Class<?> findClass(String name) throws ClassNotFoundException - { - byte[] data = null; - int i; - - //System.out.println("TouchDexLoader " + this + ": findClass '" + name + "'"); - - for (i = 0; i < mPaths.length; i++) { - //System.out.println("My path is: " + mPaths[i]); - - if (mDexs[i] != null) { - String slashName = name.replace('.', '/'); - Class clazz = mDexs[i].loadClass(slashName, this); - if (clazz != null) - return clazz; - } else if (mZips[i] != null) { - String fileName = name.replace('.', '/') + ".class"; - data = loadFromArchive(mZips[i], fileName); - } else { - File pathFile = mFiles[i]; - if (pathFile.isDirectory()) { - String fileName = - mPaths[i] + "/" + name.replace('.', '/') + ".class"; - data = loadFromDirectory(fileName); - } else { - //System.out.println("TouchDexLoader: can't find '" - // + mPaths[i] + "'"); - } - - } - - if (data != null) { - //System.out.println(" found class " + name); - int dotIndex = name.lastIndexOf('.'); - if (dotIndex != -1) { - String packageName = name.substring(0, dotIndex); - synchronized (this) { - Package packageObj = getPackage(packageName); - if (packageObj == null) { - definePackage(packageName, null, null, - null, null, null, null, null); - } - } - } - - return defineClass(name, data, 0, data.length); - } - } - - throw new ClassNotFoundException(name + " in loader " + this); - } - - /* - * Find a resource by name. This could be in a directory or in an - * archive. - */ - protected URL findResource(String name) { - byte[] data = null; - int i; - - //System.out.println("TouchDexLoader: findResource '" + name + "'"); - - for (i = 0; i < mPaths.length; i++) { - File pathFile = mFiles[i]; - ZipFile zip = mZips[i]; - if (zip != null) { - if (isInArchive(zip, name)) { - //System.out.println(" found " + name + " in " + pathFile); - // Create URL correctly - was XXX, new code should be ok. - try { - return new URL("jar:file://" + pathFile + "!/" + name); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - } else if (pathFile.isDirectory()) { - File dataFile = new File(mPaths[i] + "/" + name); - if (dataFile.exists()) { - //System.out.println(" found resource " + name); - // Create URL correctly - was XXX, new code should be ok. - try { - return new URL("file:" + name); - } - catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - } else if (pathFile.isFile()) { - } else { - System.err.println("TouchDexLoader: can't find '" - + mPaths[i] + "'"); - } - } - - return null; - } - - - /* - * Load the contents of a file from a file in a directory. - * - * Returns null if the class wasn't found. - */ - private byte[] loadFromDirectory(String path) { - try { - return IoUtils.readFileAsByteArray(path); - } catch (IOException ex) { - System.err.println("Error reading from " + path); - // swallow it, return null instead - return null; - } - } - - /* - * Load a class from a file in an archive. We currently assume that - * the file is a Zip archive. - * - * Returns null if the class wasn't found. - */ - private byte[] loadFromArchive(ZipFile zip, String name) { - ZipEntry entry; - - entry = zip.getEntry(name); - if (entry == null) - return null; - - ByteArrayOutputStream byteStream; - InputStream stream; - int count; - - /* - * Copy the data out of the stream. Because we got the ZipEntry - * from a ZipFile, the uncompressed size is known, and we can set - * the initial size of the ByteArrayOutputStream appropriately. - */ - try { - stream = zip.getInputStream(entry); - byteStream = new ByteArrayOutputStream((int) entry.getSize()); - byte[] buf = new byte[4096]; - while ((count = stream.read(buf)) > 0) - byteStream.write(buf, 0, count); - - stream.close(); - } - catch (IOException ioex) { - //System.out.println("Failed extracting '" + archive + "': " +ioex); - return null; - } - - //System.out.println(" loaded from Zip"); - return byteStream.toByteArray(); - } - - /* - * Figure out if "name" is a member of "archive". - */ - private boolean isInArchive(ZipFile zip, String name) { - return zip.getEntry(name) != null; - } - - /** - * Find a native library. - * - * Return the full pathname of the first appropriate-looking file - * we find. - */ - protected String findLibrary(String libname) { - String fileName = System.mapLibraryName(libname); - for (int i = 0; i < mLibPaths.length; i++) { - String pathName = mLibPaths[i] + fileName; - File test = new File(pathName); - - if (test.exists()) - return pathName; - } - - return null; - } -} diff --git a/dalvik/src/main/native/dalvik_system_TouchDex.cpp b/dalvik/src/main/native/dalvik_system_TouchDex.cpp deleted file mode 100644 index 719ac3c..0000000 --- a/dalvik/src/main/native/dalvik_system_TouchDex.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2007 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. - */ - -/* - * Bit of code to wrap DEX force-updating with a fork() call. - */ - -#define LOG_TAG "TouchDex" -#include "JNIHelp.h" - -#include "cutils/properties.h" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> -#include <assert.h> -#include <errno.h> - -#define JAVA_PACKAGE "dalvik/system" - -#ifndef HAVE_ANDROID_OS -# define BASE_DIR "/work/device/out/linux-x86-debug-sim" -#else -# define BASE_DIR "" -#endif - -namespace android { - -// fwd -static void logProcStatus(pid_t pid); - - -/* - * private static int trampoline(String dexFiles, String bcp) - */ -static jint dalvik_system_TouchDex_trampoline(JNIEnv* env, - jclass, jstring dexFilesStr, jstring bcpStr) -{ -#ifndef HAVE_ANDROID_OS - /* don't do this on simulator -- gdb goes "funny" in goobuntu */ - return 0; -#endif - - const int kMinTimeout = 900; // 90 seconds - const char* bcp; - const char* dexFiles; - static const char* kExecFile = BASE_DIR "/system/bin/dalvikvm"; - //static const char* kDebugArg = - // "-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"; - static const char* kBcpArgName = "-Xbootclasspath:"; - static const char* kClassName = "dalvik.system.TouchDex"; - static const char* kExecMode = "-Xint"; - static const int argc = 7; - const char* argv[argc+1]; - const char* kVerifyArg; - const char* kDexOptArg; - int timeoutMult; - pid_t pid; - struct timeval startWhen, endWhen; - char propBuf[PROPERTY_VALUE_MAX]; - char execModeBuf[PROPERTY_VALUE_MAX + sizeof("-X")]; - bool verifyJava = true; - - property_get("dalvik.vm.verify-bytecode", propBuf, ""); - if (strcmp(propBuf, "true") == 0) { - verifyJava = true; - } else if (strcmp(propBuf, "false") == 0) { - verifyJava = false; - } else { - /* bad value or not defined; use default */ - } - - if (verifyJava) { - kVerifyArg = "-Xverify:all"; - kDexOptArg = "-Xdexopt:verified"; - timeoutMult = 11; - } else { - kVerifyArg = "-Xverify:none"; - //kDexOptArg = "-Xdexopt:all"; - kDexOptArg = "-Xdexopt:verified"; - timeoutMult = 7; - } - - property_get("dalvik.vm.execution-mode", propBuf, ""); - if (strncmp(propBuf, "int:", 4) == 0) { - strcpy(execModeBuf, "-X"); - strcat(execModeBuf, propBuf); - kExecMode = execModeBuf; - } - - LOGV("TouchDex trampoline forking\n"); - gettimeofday(&startWhen, NULL); - - /* - * Retrieve strings. Note we want to do this *before* the fork() -- bad - * idea to perform Java operations in the child process (not all threads - * get carried over to the new process). - */ - bcp = env->GetStringUTFChars(bcpStr, NULL); - dexFiles = env->GetStringUTFChars(dexFilesStr, NULL); - if (bcp == NULL || dexFiles == NULL) { - LOGE("Bad values for bcp=%p dexFiles=%p\n", bcp, dexFiles); - abort(); - } - - pid = fork(); - if (pid < 0) { - LOGE("fork failed: %s", strerror(errno)); - return -1; - } - - if (pid == 0) { - /* child */ - char* bcpArg; - - LOGV("TouchDex trampoline in child\n"); - - bcpArg = (char*) malloc(strlen(bcp) + strlen(kBcpArgName) +1); - strcpy(bcpArg, kBcpArgName); - strcat(bcpArg, bcp); - - argv[0] = kExecFile; - argv[1] = bcpArg; - argv[2] = kVerifyArg; - argv[3] = kDexOptArg; - argv[4] = kExecMode; - argv[5] = kClassName; - argv[6] = dexFiles; - argv[7] = NULL; - - //LOGI("Calling execv with args:\n"); - //for (int i = 0; i < argc; i++) - // LOGI(" %d: '%s'\n", i, argv[i]); - - execv(kExecFile, (char* const*) argv); - free(bcpArg); - - LOGE("execv '%s' failed: %s\n", kExecFile, strerror(errno)); - exit(1); - } else { - int cc, count, dexCount, timeout; - int result = -1; - const char* cp; - - /* - * Adjust the timeout based on how many DEX files we have to - * process. Larger DEX files take longer, so this is a crude - * approximation at best. - * - * We need this for http://b/issue?id=836771, which can leave us - * stuck waiting for a long time even if there is no work to be done. - * - * This is currently being (ab)used to convert single files, which - * sort of spoils the timeout calculation. We establish a minimum - * timeout for single apps. - * - * The timeout calculation doesn't work at all right when a - * directory is specified. So the minimum is now a minute. At - * this point it's probably safe to just remove the timeout. - * - * The timeout is in 1/10ths of a second. - */ - dexCount = 1; - cp = dexFiles; - while (*++cp != '\0') { - if (*cp == ':') - dexCount++; - } - timeout = timeoutMult * dexCount; - if (timeout < kMinTimeout) - timeout = kMinTimeout; - - env->ReleaseStringUTFChars(bcpStr, bcp); - env->ReleaseStringUTFChars(dexFilesStr, dexFiles); - - - LOGD("TouchDex parent waiting for pid=%d (timeout=%.1fs)\n", - (int) pid, timeout / 10.0); - for (count = 0; count < timeout; count++) { - /* waitpid doesn't take a timeout, so poll and sleep */ - cc = waitpid(pid, &result, WNOHANG); - if (cc < 0) { - LOGE("waitpid(%d) failed: %s", (int) pid, strerror(errno)); - return -1; - } else if (cc == 0) { - usleep(100000); /* 0.1 sec */ - } else { - /* success! */ - break; - } - } - - if (count == timeout) { - /* note kill(0) returns 0 if the pid is a zombie */ - LOGE("timed out waiting for %d; kill(0) returns %d\n", - (int) pid, kill(pid, 0)); - logProcStatus(pid); - } else { - LOGV("TouchDex done after %d iterations (kill(0) returns %d)\n", - count, kill(pid, 0)); - } - - gettimeofday(&endWhen, NULL); - long long start = startWhen.tv_sec * 1000000 + startWhen.tv_usec; - long long end = endWhen.tv_sec * 1000000 + endWhen.tv_usec; - - LOGI("Dalvik-cache prep: status=0x%04x, finished in %dms\n", - result, (int) ((end - start) / 1000)); - - if (WIFEXITED(result)) - return WEXITSTATUS(result); - else - return result; - } -} - -/* - * Dump the contents of /proc/<pid>/status to the log file. - */ -static void logProcStatus(pid_t pid) -{ - char localBuf[256]; - FILE* fp; - - sprintf(localBuf, "/proc/%d/status", (int) pid); - fp = fopen(localBuf, "r"); - if (fp == NULL) { - LOGI("Unable to open '%s'\n", localBuf); - return; - } - - LOGI("Contents of %s:\n", localBuf); - while (true) { - fgets(localBuf, sizeof(localBuf), fp); - if (ferror(fp) || feof(fp)) - break; - LOGI(" %s", localBuf); - } - - fclose(fp); -} - -static JNINativeMethod gMethods[] = { - { "trampoline", "(Ljava/lang/String;Ljava/lang/String;)I", - (void*) dalvik_system_TouchDex_trampoline }, -}; -int register_dalvik_system_TouchDex(JNIEnv* env) { - return jniRegisterNativeMethods(env, JAVA_PACKAGE "/TouchDex", gMethods, NELEM(gMethods)); -} - -}; // namespace android diff --git a/dalvik/src/main/native/sub.mk b/dalvik/src/main/native/sub.mk index ad62649..4adc8a1 100644 --- a/dalvik/src/main/native/sub.mk +++ b/dalvik/src/main/native/sub.mk @@ -4,7 +4,6 @@ # or BUILD_*_LIBRARY. LOCAL_SRC_FILES := \ - dalvik_system_TouchDex.cpp \ org_apache_harmony_dalvik_NativeTestTarget.cpp #LOCAL_C_INCLUDES += @@ -16,4 +15,3 @@ LOCAL_SRC_FILES := \ #LOCAL_SHARED_LIBRARIES += #LOCAL_STATIC_LIBRARIES += - diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp index a6e49dc..0cdf51d 100644 --- a/luni/src/main/native/Register.cpp +++ b/luni/src/main/native/Register.cpp @@ -21,10 +21,6 @@ #include <stdlib.h> -namespace android { - extern int register_dalvik_system_TouchDex(JNIEnv* env); -} - extern int register_java_io_Console(JNIEnv* env); extern int register_java_io_File(JNIEnv* env); extern int register_java_io_FileDescriptor(JNIEnv* env); @@ -109,16 +105,15 @@ extern "C" int registerCoreLibrariesJni(JNIEnv* env) { register_libcore_icu_TimeZones(env) != -1 && register_libcore_io_IoUtils(env) != -1 && register_libcore_net_RawSocket(env) != -1 && + register_org_apache_harmony_dalvik_NativeTestTarget(env) != -1 && register_org_apache_harmony_luni_platform_OSFileSystem(env) != -1 && register_org_apache_harmony_luni_platform_OSMemory(env) != -1 && register_org_apache_harmony_luni_platform_OSNetworkSystem(env) != -1 && register_org_apache_harmony_luni_util_fltparse(env) != -1 && register_org_apache_harmony_text_NativeBidi(env) != -1 && + register_org_apache_harmony_xml_ExpatParser(env) != -1 && register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(env) != -1 && - // Initialize the Android classes last, as they have dependencies on the "corer" core classes. - android::register_dalvik_system_TouchDex(env) != -1 && - register_org_apache_harmony_dalvik_NativeTestTarget(env) != -1 && - register_org_apache_harmony_xml_ExpatParser(env) != -1; + true; if (!result) { LOGE("Failed to initialize the core libraries; aborting..."); |