Implement the dalvik side of libcore.reflect.
(Cherry-pick of b4d5cf78d4731ffc6211d07a0d69c92c559ba792.)
Change-Id: I5d1b41f029c9c49a2d60a066a5fb0ed0f52f4b52
diff --git a/vm/DvmDex.h b/vm/DvmDex.h
index b3b5960..1785c26 100644
--- a/vm/DvmDex.h
+++ b/vm/DvmDex.h
@@ -21,6 +21,7 @@
#ifndef DALVIK_DVMDEX_H_
#define DALVIK_DVMDEX_H_
+#include "jni.h"
#include "libdex/DexFile.h"
/* extern */
@@ -61,6 +62,8 @@
bool isMappedReadOnly;
MemMapping memMap;
+ jobject dex_object;
+
/* lock ensuring mutual exclusion during updates */
pthread_mutex_t modLock;
};
diff --git a/vm/InitRefs.cpp b/vm/InitRefs.cpp
index 672abaa..9a04842 100644
--- a/vm/InitRefs.cpp
+++ b/vm/InitRefs.cpp
@@ -321,12 +321,12 @@
{ &gDvm.methJavaLangStackTraceElement_init, "Ljava/lang/StackTraceElement;",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V" },
{ &gDvm.methJavaLangReflectConstructor_init, "Ljava/lang/reflect/Constructor;",
- "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;I)V" },
+ "(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;II)V" },
{ &gDvm.methJavaLangReflectField_init, "Ljava/lang/reflect/Field;",
- "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;I)V" },
+ "(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;II)V" },
{ &gDvm.methJavaLangReflectMethod_init, "Ljava/lang/reflect/Method;",
"(Ljava/lang/Class;[Ljava/lang/Class;[Ljava/lang/Class;Ljava/lang/Class;"
- "Ljava/lang/String;I)V" },
+ "Ljava/lang/String;II)V" },
{ &gDvm.methJavaNioDirectByteBuffer_init, "Ljava/nio/DirectByteBuffer;",
"(JI)V" },
{ &gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init,
diff --git a/vm/native/java_lang_Class.cpp b/vm/native/java_lang_Class.cpp
index 93455e7..88d31ef 100644
--- a/vm/native/java_lang_Class.cpp
+++ b/vm/native/java_lang_Class.cpp
@@ -19,7 +19,7 @@
*/
#include "Dalvik.h"
#include "native/InternalNativePriv.h"
-
+#include "ScopedPthreadMutexLock.h"
/*
* native public boolean desiredAssertionStatus()
@@ -757,6 +757,52 @@
}
}
+JNIEXPORT jobject JNICALL Java_java_lang_Class_getDex(JNIEnv* env, jclass javaClass) {
+ Thread* self = dvmThreadSelf();
+ ClassObject* c = (ClassObject*) dvmDecodeIndirectRef(self, javaClass);
+
+ DvmDex* dvm_dex = c->pDvmDex;
+ if (dvm_dex == NULL) {
+ return NULL;
+ }
+
+ ScopedPthreadMutexLock lock(&dvm_dex->modLock);
+
+ // Already cached?
+ if (dvm_dex->dex_object != NULL) {
+ return dvm_dex->dex_object;
+ }
+
+ jobject byte_buffer = env->NewDirectByteBuffer(dvm_dex->memMap.addr, dvm_dex->memMap.length);
+ if (byte_buffer == NULL) {
+ return NULL;
+ }
+
+ jclass com_android_dex_Dex = env->FindClass("com/android/dex/Dex");
+ if (com_android_dex_Dex == NULL) {
+ return NULL;
+ }
+
+ jmethodID com_android_dex_Dex_create =
+ env->GetStaticMethodID(com_android_dex_Dex,
+ "<init>", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
+ if (com_android_dex_Dex_create == NULL) {
+ return NULL;
+ }
+
+ jvalue args[1];
+ args[0].l = byte_buffer;
+ jobject local_ref = env->CallStaticObjectMethodA(com_android_dex_Dex,
+ com_android_dex_Dex_create,
+ args);
+ if (local_ref == NULL) {
+ return NULL;
+ }
+
+ dvm_dex->dex_object = env->NewGlobalRef(local_ref);
+ return dvm_dex->dex_object;
+}
+
const DalvikNativeMethod dvm_java_lang_Class[] = {
{ "desiredAssertionStatus", "()Z",
Dalvik_java_lang_Class_desiredAssertionStatus },
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index 4e6103a..ca41157 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -306,6 +306,8 @@
u4 accessFlags;
};
+u4 dvmGetFieldIdx(const Field* field);
+
/*
* Static field.
*/
@@ -582,6 +584,8 @@
bool inProfile;
};
+u4 dvmGetMethodIdx(const Method* method);
+
/*
* Find a method within a class. The superclass is not searched.
diff --git a/vm/reflect/Annotation.cpp b/vm/reflect/Annotation.cpp
index bb1d2f5..942027c 100644
--- a/vm/reflect/Annotation.cpp
+++ b/vm/reflect/Annotation.cpp
@@ -1610,8 +1610,10 @@
* out reasonably well because it's in sorted order, though we're still left
* doing a fair number of string comparisons.
*/
-static u4 getMethodIdx(const Method* method)
+u4 dvmGetMethodIdx(const Method* method)
{
+ if (method->clazz->pDvmDex == NULL) return 0;
+
DexFile* pDexFile = method->clazz->pDvmDex->pDexFile;
u4 hi = pDexFile->pHeader->methodIdsSize -1;
u4 lo = 0;
@@ -1676,7 +1678,7 @@
* find the method definition in the DEX file and perform string
* comparisons on class name, method name, and signature.
*/
- u4 methodIdx = getMethodIdx(method);
+ u4 methodIdx = dvmGetMethodIdx(method);
u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir);
u4 idx;
@@ -1918,10 +1920,12 @@
/*
* Given a field, determine the field's index.
*
- * This has the same tradeoffs as getMethodIdx.
+ * This has the same tradeoffs as dvmGetMethodIdx.
*/
-static u4 getFieldIdx(const Field* field)
+u4 dvmGetFieldIdx(const Field* field)
{
+ if (field->clazz->pDvmDex == NULL) return 0;
+
DexFile* pDexFile = field->clazz->pDvmDex->pDexFile;
u4 hi = pDexFile->pHeader->fieldIdsSize -1;
u4 lo = 0;
@@ -1987,7 +1991,7 @@
* find the field definition in the DEX file and perform string
* comparisons on class name, field name, and signature.
*/
- u4 fieldIdx = getFieldIdx(field);
+ u4 fieldIdx = dvmGetFieldIdx(field);
u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir);
u4 idx;
@@ -2169,7 +2173,7 @@
* find the method definition in the DEX file and perform string
* comparisons on class name, method name, and signature.
*/
- u4 methodIdx = getMethodIdx(method);
+ u4 methodIdx = dvmGetMethodIdx(method);
u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir);
u4 idx;
diff --git a/vm/reflect/Reflect.cpp b/vm/reflect/Reflect.cpp
index 1d055c1..9cb9fc7 100644
--- a/vm/reflect/Reflect.cpp
+++ b/vm/reflect/Reflect.cpp
@@ -226,7 +226,7 @@
ClassObject* type;
char* mangle;
char* cp;
- int slot;
+ int slot, field_idx;
assert(dvmIsClassInitialized(gDvm.classJavaLangReflectField));
@@ -245,10 +245,11 @@
goto bail;
slot = fieldToSlot(field, clazz);
+ field_idx = dvmGetFieldIdx(field);
JValue unused;
dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectField_init,
- fieldObj, &unused, clazz, type, nameObj, slot);
+ fieldObj, &unused, clazz, type, nameObj, slot, field_idx);
if (dvmCheckException(dvmThreadSelf())) {
ALOGD("Field class init threw exception");
goto bail;
@@ -393,7 +394,7 @@
Object* consObj;
DexStringCache mangle;
char* cp;
- int slot;
+ int slot, method_idx;
dexStringCacheInit(&mangle);
@@ -425,10 +426,11 @@
goto bail;
slot = methodToSlot(meth);
+ method_idx = dvmGetMethodIdx(meth);
JValue unused;
dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectConstructor_init,
- consObj, &unused, meth->clazz, params, exceptions, slot);
+ consObj, &unused, meth->clazz, params, exceptions, slot, method_idx);
if (dvmCheckException(dvmThreadSelf())) {
ALOGD("Constructor class init threw exception");
goto bail;
@@ -532,7 +534,7 @@
ClassObject* returnType;
DexStringCache mangle;
char* cp;
- int slot;
+ int slot, method_idx;
if (dvmCheckException(dvmThreadSelf())) {
ALOGW("WARNING: dvmCreateReflectMethodObject called with "
@@ -577,11 +579,12 @@
goto bail;
slot = methodToSlot(meth);
+ method_idx = dvmGetMethodIdx(meth);
JValue unused;
dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangReflectMethod_init,
methObj, &unused, meth->clazz, params, exceptions, returnType,
- nameObj, slot);
+ nameObj, slot, method_idx);
if (dvmCheckException(dvmThreadSelf())) {
ALOGD("Method class init threw exception");
goto bail;