summaryrefslogtreecommitdiffstats
path: root/libdvm
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-09-19 02:51:22 -0700
committerIan Rogers <irogers@google.com>2013-09-21 22:05:00 -0700
commita6e22fc9b70ebe39abd716ce37450bda935c0fb8 (patch)
tree2bbdf94c92895e7c2faf1db2e8482bf85906a129 /libdvm
parent98430d0d75f4cfd40614b77debeb3c8d0abf40df (diff)
downloadlibcore-a6e22fc9b70ebe39abd716ce37450bda935c0fb8.zip
libcore-a6e22fc9b70ebe39abd716ce37450bda935c0fb8.tar.gz
libcore-a6e22fc9b70ebe39abd716ce37450bda935c0fb8.tar.bz2
Avoid computing class def indices.
Bug: 10244719 Also tidy AnnotationAccess. (cherry-picked from 8b2c0b9abc3f520495f4387ea040132ba85cae69) Change-Id: I6ec8fd4e36b428d7e16e01d98b7bebc143fac8c3 Conflicts: libdvm/src/main/java/java/lang/Class.java
Diffstat (limited to 'libdvm')
-rw-r--r--libdvm/src/main/java/java/lang/Class.java117
1 files changed, 96 insertions, 21 deletions
diff --git a/libdvm/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
index 4ad9614..4b36f3c 100644
--- a/libdvm/src/main/java/java/lang/Class.java
+++ b/libdvm/src/main/java/java/lang/Class.java
@@ -54,13 +54,14 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
-import libcore.util.BasicLruCache;
-import libcore.util.CollectionUtils;
-import libcore.util.EmptyArray;
import org.apache.harmony.kernel.vm.StringUtils;
import libcore.reflect.AnnotationAccess;
import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.InternalNames;
import libcore.reflect.Types;
+import libcore.util.BasicLruCache;
+import libcore.util.CollectionUtils;
+import libcore.util.EmptyArray;
/**
* The in-memory representation of a Java class. This representation serves as
@@ -122,12 +123,24 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
private static final long serialVersionUID = 3206093459760846163L;
/**
- * Lazily computed name of this class; always prefer calling getName().
+ * Class def index from dex file. An index of -1 indicates that there is no class definition,
+ * for example for an array type.
*/
- private transient String name;
+ private transient int dexClassDefIndex;
+ /** The type index of this class within the dex file that defines it. */
private transient int dexTypeIndex;
+ /**
+ * Have we computed the type and class def indices? Volatile to avoid double check locking bugs.
+ */
+ private transient volatile boolean dexIndicesInitialized;
+
+ /**
+ * Lazily computed name of this class; always prefer calling getName().
+ */
+ private transient String name;
+
private Class() {
// Prevent this class to be instantiated, instance
// should be created by JVM only
@@ -139,23 +152,45 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
*/
public native Dex getDex();
+ /** Lazily compute indices in to Dex */
+ private synchronized void computeDexIndices() {
+ if (!dexIndicesInitialized) {
+ Dex dex = getDex();
+ dexTypeIndex = dex.findTypeIndex(InternalNames.getInternalName(this));
+ if (dexTypeIndex < 0) {
+ dexTypeIndex = -1;
+ dexClassDefIndex = -1;
+ } else {
+ dexClassDefIndex = dex.findClassDefIndexFromTypeIndex(dexTypeIndex);
+ }
+ dexIndicesInitialized = true;
+ }
+ }
+
/**
- * The type index of this class in its own Dex, or 0 if it is unknown. If a
- * class is referenced by multiple Dex files, it will have a different type
- * index in each. Dex files support 65534 type indices, with 65535
- * representing no index.
+ * The class def of this class in its own Dex, or -1 if there is no class def.
*
- * TODO: 0 is a valid index; this should be -1 if it is unknown
+ * @hide
+ */
+ public int getDexClassDefIndex() {
+ if (!dexIndicesInitialized) {
+ computeDexIndices();
+ }
+ return dexClassDefIndex;
+ }
+
+ /**
+ * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced
+ * by multiple Dex files, it will have a different type index in each. Dex files support 65534
+ * type indices, with 65535 representing no index.
*
* @hide
*/
- public int getTypeIndex() {
- int result = dexTypeIndex;
- if (result == 0) { // uncomputed => Dalvik
- result = AnnotationAccess.computeTypeIndex(getDex(), this);
- dexTypeIndex = result;
+ public int getDexTypeIndex() {
+ if (!dexIndicesInitialized) {
+ computeDexIndices();
}
- return result;
+ return dexTypeIndex;
}
/**
@@ -777,7 +812,7 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
Caches.genericInterfaces.put(this, result);
}
}
- return result;
+ return (result.length == 0) ? result : result.clone();
}
/**
@@ -1100,7 +1135,11 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
* {@code enum}.
*/
public boolean isEnum() {
- return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class);
+ if (getSuperclass() != Enum.class) {
+ return false;
+ }
+ int mod = getModifiers(this, true);
+ return (mod & 0x4000) != 0;
}
/**
@@ -1262,12 +1301,48 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe
*
* @hide
*/
- public int getAnnotationDirectoryOffset() {
- return AnnotationAccess.typeIndexToAnnotationDirectoryOffset(getDex(), getTypeIndex());
+ public int getDexAnnotationDirectoryOffset() {
+ Dex dex = getDex();
+ if (dex == null) {
+ return 0;
+ }
+ int classDefIndex = getDexClassDefIndex();
+ if (classDefIndex < 0) {
+ return 0;
+ }
+ return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex);
}
+
+ /**
+ * Returns a resolved type from the dex cache, computing the type from the dex file if
+ * necessary.
+ * TODO: use Dalvik's dex cache.
+ * @hide
+ */
+ public Class<?> getDexCacheType(Dex dex, int typeIndex) {
+ String internalName = dex.typeNames().get(typeIndex);
+ return InternalNames.getClass(getClassLoader(), internalName);
+ }
+
+ /**
+ * Returns a string from the dex cache, computing the string from the dex file if necessary.
+ *
+ * @hide
+ */
+ public String getDexCacheString(Dex dex, int dexStringIndex) {
+ return dex.strings().get(dexStringIndex);
+ }
+
+
private static class Caches {
+ /**
+ * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon.
+ * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic
+ * interfaces (required to avoid time outs). Validated by running reflection heavy code
+ * such as applications using Guice-like frameworks.
+ */
private static final BasicLruCache<Class, Type[]> genericInterfaces
- = new BasicLruCache<Class, Type[]>(50);
+ = new BasicLruCache<Class, Type[]>(8);
}
}