Minor class loading optimization.
In internal bug 1836311, the String.replace() in PathLoader.findClass
was identifed by traceview as 6.6% of startup time for an app. This
adds a (hidden) alternative that takes a "binary name" like the
functions in ClassLoader, and we do the slash-to-dot conversion inside
the VM as we convert it to a descriptor. (This is really how it should
have been done in the first place, but now it's part of the visible API
and engraved in stone.)
The original function now does a slash-to-dot conversion and calls the
new one.
(We may want to un-hide the method for the benefit of people writing
custom class loaders. If so, we can do that in a separate API-update
commit.)
diff --git a/libcore/dalvik/src/main/java/dalvik/system/DexFile.java b/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
index da51e45..00de314 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -38,11 +38,13 @@
/**
* Opens a DEX file from a given File object. This will usually be a ZIP/JAR
- * file with a "classes.dex" inside. The method should not be used for files
- * inside the Dalvik cache.
- *
- * @cts What will happen if we refer to the Dalvik cache? Should be either
- * specified or throw an exception...
+ * file with a "classes.dex" inside.
+ *
+ * The VM will generate the name of the coresponding file in
+ * /data/dalvik-cache and open it, possibly creating or updating
+ * it first if system permissions allow. Don't pass in the name of
+ * a file in /data/dalvik-cache, as the named file is expected to be
+ * in its original (pre-dexopt) state.
*
* @param file
* the File object referencing the actual DEX file
@@ -57,11 +59,13 @@
/**
* Opens a DEX file from a given filename. This will usually be a ZIP/JAR
- * file with a "classes.dex" inside. The method should not be used for files
- * inside the Dalvik cache.
- *
- * @cts What will happen if we refer to the Dalvik cache? Should be either
- * specified or throw an exception...
+ * file with a "classes.dex" inside.
+ *
+ * The VM will generate the name of the coresponding file in
+ * /data/dalvik-cache and open it, possibly creating or updating
+ * it first if system permissions allow. Don't pass in the name of
+ * a file in /data/dalvik-cache, as the named file is expected to be
+ * in its original (pre-dexopt) state.
*
* @param fileName
* the filename of the DEX file
@@ -190,11 +194,23 @@
* @cts Exception comment is a bit cryptic. What exception will be thrown?
*/
public Class loadClass(String name, ClassLoader loader) {
+ String slashName = name.replace('.', '/');
+ return loadClassBinaryName(slashName, loader);
+ }
+
+ /**
+ * See {@link #loadClass(String, ClassLoader)}.
+ *
+ * This takes a "binary" class name to better match ClassLoader semantics.
+ *
+ * {@hide}
+ */
+ public Class loadClassBinaryName(String name, ClassLoader loader) {
return defineClass(name, loader, mCookie,
null);
//new ProtectionDomain(name) /*DEBUG ONLY*/);
}
-
+
native private static Class defineClass(String name, ClassLoader loader,
int cookie, ProtectionDomain pd);
diff --git a/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java b/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
index 55e61a9..597eb5b 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
@@ -179,8 +179,9 @@
* parent ClassLoader has failed to find a loaded class of the same name.
*
* @param name
- * The name of the class to search for, in a human-readable form
- * like "java.lang.String" or "java.net.URLClassLoader$3$1".
+ * The "binary name" of the class to search for, in a
+ * human-readable form like "java.lang.String" or
+ * "java.net.URLClassLoader$3$1".
* @return the {@link Class} object representing the class
* @throws ClassNotFoundException
* if the class cannot be found
@@ -199,8 +200,7 @@
//System.out.println("My path is: " + mPaths[i]);
if (mDexs[i] != null) {
- String slashName = name.replace('.', '/');
- Class clazz = mDexs[i].loadClass(slashName, this);
+ Class clazz = mDexs[i].loadClassBinaryName(name, this);
if (clazz != null)
return clazz;
} else if (mZips[i] != null) {
diff --git a/vm/native/dalvik_system_DexFile.c b/vm/native/dalvik_system_DexFile.c
index f4e576c..4c7412c 100644
--- a/vm/native/dalvik_system_DexFile.c
+++ b/vm/native/dalvik_system_DexFile.c
@@ -249,6 +249,8 @@
* creation of a specific class. The difference is that the search for and
* reading of the bytes is done within the VM.
*
+ * The class name is a "binary name", e.g. "java.lang.String".
+ *
* Returns a null pointer with no exception if the class was not found.
* Throws an exception on other failures.
*/
@@ -266,8 +268,8 @@
char* descriptor;
name = dvmCreateCstrFromString(nameObj);
- descriptor = dvmNameToDescriptor(name);
- LOGV("--- Explicit class load '%s' 0x%08x\n", name, cookie);
+ descriptor = dvmDotToDescriptor(name);
+ LOGV("--- Explicit class load '%s' 0x%08x\n", descriptor, cookie);
free(name);
if (!validateCookie(cookie))