DO NOT MERGE Fix all unsafe caching to be like libcore.
This way, if a runtime is restarted within a process, we re-initialize all
the cached data.
Conflicts:
src/native/java_lang_Runtime.cc -- nativeExit lost an argument in dalvik-dev
(cherry picked from commit 7756d5473fa27ce7e6ac7c31770eef7030431da4)
Change-Id: I6184fc20c2a9ec16c4b053584a4d1c3b64452d0f
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 57baee7..9af92da 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -194,6 +194,7 @@
src/trace.cc \
src/utf.cc \
src/utils.cc \
+ src/well_known_classes.cc \
src/zip_archive.cc \
src/verifier/gc_map.cc \
src/verifier/method_verifier.cc \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b73c2b0..c1382e2 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -52,6 +52,7 @@
#include "thread.h"
#include "UniquePtr.h"
#include "utils.h"
+#include "well_known_classes.h"
namespace art {
@@ -141,24 +142,17 @@
env->ExceptionClear();
- // TODO: add java.lang.Error to JniConstants?
- ScopedLocalRef<jclass> error_class(env, env->FindClass("java/lang/Error"));
- CHECK(error_class.get() != NULL);
- if (env->IsInstanceOf(cause.get(), error_class.get())) {
+ if (env->IsInstanceOf(cause.get(), WellKnownClasses::java_lang_Error)) {
// We only wrap non-Error exceptions; an Error can just be used as-is.
env->Throw(cause.get());
return;
}
- // TODO: add java.lang.ExceptionInInitializerError to JniConstants?
- ScopedLocalRef<jclass> eiie_class(env, env->FindClass("java/lang/ExceptionInInitializerError"));
- CHECK(eiie_class.get() != NULL);
-
- jmethodID mid = env->GetMethodID(eiie_class.get(), "<init>" , "(Ljava/lang/Throwable;)V");
+ jmethodID mid = env->GetMethodID(WellKnownClasses::java_lang_ExceptionInInitializerError, "<init>" , "(Ljava/lang/Throwable;)V");
CHECK(mid != NULL);
ScopedLocalRef<jthrowable> eiie(env,
- reinterpret_cast<jthrowable>(env->NewObject(eiie_class.get(), mid, cause.get())));
+ reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ExceptionInInitializerError, mid, cause.get())));
env->Throw(eiie.get());
}
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 0db3187..a8101ba 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -28,6 +28,7 @@
#include "thread.h"
#include "thread_list.h"
#include "verifier/method_verifier.h"
+#include "well_known_classes.h"
#include <algorithm>
#include <cstdarg>
@@ -729,22 +730,11 @@
args->Set(i, val.GetL());
}
- // Get the InvocationHandler method and the field that holds it within the Proxy object
- static jmethodID inv_hand_invoke_mid = NULL;
- static jfieldID proxy_inv_hand_fid = NULL;
- if (proxy_inv_hand_fid == NULL) {
- ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
- proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
- ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
- inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
- "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
- }
+ DCHECK(env->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
- DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));
-
- jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
+ jobject inv_hand = env->GetObjectField(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy_h);
// Call InvocationHandler.invoke
- jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);
+ jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj);
// Place result in stack args
if (!thread->IsExceptionPending()) {
diff --git a/src/debugger.cc b/src/debugger.cc
index 2156482..342d548 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -34,6 +34,7 @@
#include "space.h"
#include "stack_indirect_reference_table.h"
#include "thread_list.h"
+#include "well_known_classes.h"
extern "C" void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*), void*);
#ifndef HAVE_ANDROID_OS
@@ -2322,14 +2323,6 @@
Thread* self = Thread::Current();
JNIEnv* env = self->GetJniEnv();
- static jclass Chunk_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/Chunk");
- static jclass DdmServer_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
- static jmethodID dispatch_mid = env->GetStaticMethodID(DdmServer_class, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;");
- static jfieldID data_fid = env->GetFieldID(Chunk_class, "data", "[B");
- static jfieldID length_fid = env->GetFieldID(Chunk_class, "length", "I");
- static jfieldID offset_fid = env->GetFieldID(Chunk_class, "offset", "I");
- static jfieldID type_fid = env->GetFieldID(Chunk_class, "type", "I");
-
// Create a byte[] corresponding to 'buf'.
ScopedLocalRef<jbyteArray> dataArray(env, env->NewByteArray(dataLen));
if (dataArray.get() == NULL) {
@@ -2352,7 +2345,9 @@
}
// Call "private static Chunk dispatch(int type, byte[] data, int offset, int length)".
- ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(DdmServer_class, dispatch_mid, type, dataArray.get(), offset, length));
+ ScopedLocalRef<jobject> chunk(env, env->CallStaticObjectMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
+ WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch,
+ type, dataArray.get(), offset, length));
if (env->ExceptionCheck()) {
LOG(INFO) << StringPrintf("Exception thrown by dispatcher for 0x%08x", type);
env->ExceptionDescribe();
@@ -2376,10 +2371,10 @@
*
* So we're pretty much stuck with copying data around multiple times.
*/
- ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), data_fid)));
- length = env->GetIntField(chunk.get(), length_fid);
- offset = env->GetIntField(chunk.get(), offset_fid);
- type = env->GetIntField(chunk.get(), type_fid);
+ ScopedLocalRef<jbyteArray> replyData(env, reinterpret_cast<jbyteArray>(env->GetObjectField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data)));
+ length = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length);
+ offset = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset);
+ type = env->GetIntField(chunk.get(), WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type);
VLOG(jdwp) << StringPrintf("DDM reply: type=0x%08x data=%p offset=%d length=%d", type, replyData.get(), offset, length);
if (length == 0 || replyData.get() == NULL) {
@@ -2418,10 +2413,10 @@
}
JNIEnv* env = self->GetJniEnv();
- static jclass DdmServer_class = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
- static jmethodID broadcast_mid = env->GetStaticMethodID(DdmServer_class, "broadcast", "(I)V");
jint event = connect ? 1 /*DdmServer.CONNECTED*/ : 2 /*DdmServer.DISCONNECTED*/;
- env->CallStaticVoidMethod(DdmServer_class, broadcast_mid, event);
+ env->CallStaticVoidMethod(WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer,
+ WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast,
+ event);
if (env->ExceptionCheck()) {
LOG(ERROR) << "DdmServer.broadcast " << event << " failed";
env->ExceptionDescribe();
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 78f0fdc..f18b215 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -38,6 +38,7 @@
#include "UniquePtr.h"
#include "utf.h"
#include "utils.h"
+#include "well_known_classes.h"
#include "zip_archive.h"
namespace art {
@@ -234,19 +235,11 @@
return NULL;
}
- jclass c = env->FindClass("com/android/dex/Dex");
- if (c == NULL) {
- return NULL;
- }
-
- jmethodID mid = env->GetStaticMethodID(c, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
- if (mid == NULL) {
- return NULL;
- }
-
jvalue args[1];
args[0].l = byte_buffer;
- jobject local = env->CallStaticObjectMethodA(c, mid, args);
+ jobject local = env->CallStaticObjectMethodA(WellKnownClasses::com_android_dex_Dex,
+ WellKnownClasses::com_android_dex_Dex_create,
+ args);
if (local == NULL) {
return NULL;
}
diff --git a/src/heap.cc b/src/heap.cc
index 02e3ac7..bc59cfc 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -35,6 +35,7 @@
#include "thread_list.h"
#include "timing_logger.h"
#include "UniquePtr.h"
+#include "well_known_classes.h"
namespace art {
@@ -854,9 +855,7 @@
return;
}
JNIEnv* env = Thread::Current()->GetJniEnv();
- static jclass Daemons_class = CacheClass(env, "java/lang/Daemons");
- static jmethodID Daemons_requestHeapTrim = env->GetStaticMethodID(Daemons_class, "requestHeapTrim", "()V");
- env->CallStaticVoidMethod(Daemons_class, Daemons_requestHeapTrim);
+ env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons, WellKnownClasses::java_lang_Daemons_requestHeapTrim);
CHECK(!env->ExceptionCheck());
}
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 61f7c3c..03d668c 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -37,6 +37,7 @@
#include "stringpiece.h"
#include "thread.h"
#include "UniquePtr.h"
+#include "well_known_classes.h"
namespace art {
@@ -55,6 +56,16 @@
static const size_t kWeakGlobalsInitial = 16; // Arbitrary.
static const size_t kWeakGlobalsMax = 51200; // Arbitrary sanity check.
+void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, size_t method_count) {
+ ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name));
+ if (c.get() == NULL) {
+ LOG(FATAL) << "Couldn't find class: " << jni_class_name;
+ }
+ if (env->RegisterNatives(c.get(), methods, method_count) != JNI_OK) {
+ LOG(FATAL) << "Failed to register natives methods: " << jni_class_name;
+ }
+}
+
void SetJniGlobalsMax(size_t max) {
if (max != 0) {
gGlobalsMax = max;
@@ -511,17 +522,6 @@
}
}
-static jclass InitDirectByteBufferClass(JNIEnv* env) {
- ScopedLocalRef<jclass> buffer_class(env, env->FindClass("java/nio/ReadWriteDirectByteBuffer"));
- CHECK(buffer_class.get() != NULL);
- return reinterpret_cast<jclass>(env->NewGlobalRef(buffer_class.get()));
-}
-
-static jclass GetDirectByteBufferClass(JNIEnv* env) {
- static jclass buffer_class = InitDirectByteBufferClass(env);
- return buffer_class;
-}
-
static jint JII_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* raw_args, bool as_daemon) {
if (vm == NULL || p_env == NULL) {
return JNI_ERR;
@@ -2315,32 +2315,26 @@
CHECK(address != NULL); // TODO: ReportJniError
CHECK_GT(capacity, 0); // TODO: ReportJniError
- jclass buffer_class = GetDirectByteBufferClass(env);
- jmethodID mid = env->GetMethodID(buffer_class, "<init>", "(II)V");
- if (mid == NULL) {
- return NULL;
- }
-
// At the moment, the Java side is limited to 32 bits.
CHECK_LE(reinterpret_cast<uintptr_t>(address), 0xffffffff);
CHECK_LE(capacity, 0xffffffff);
jint address_arg = reinterpret_cast<jint>(address);
jint capacity_arg = static_cast<jint>(capacity);
- jobject result = env->NewObject(buffer_class, mid, address_arg, capacity_arg);
+ jobject result = env->NewObject(WellKnownClasses::java_nio_ReadWriteDirectByteBuffer,
+ WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_init,
+ address_arg, capacity_arg);
return ts.Self()->IsExceptionPending() ? NULL : result;
}
static void* GetDirectBufferAddress(JNIEnv* env, jobject java_buffer) {
ScopedJniThreadState ts(env);
- static jfieldID fid = env->GetFieldID(GetDirectByteBufferClass(env), "effectiveDirectAddress", "I");
- return reinterpret_cast<void*>(env->GetIntField(java_buffer, fid));
+ return reinterpret_cast<void*>(env->GetIntField(java_buffer, WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress));
}
static jlong GetDirectBufferCapacity(JNIEnv* env, jobject java_buffer) {
ScopedJniThreadState ts(env);
- static jfieldID fid = env->GetFieldID(GetDirectByteBufferClass(env), "capacity", "I");
- return static_cast<jlong>(env->GetIntField(java_buffer, fid));
+ return static_cast<jlong>(env->GetIntField(java_buffer, WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_capacity));
}
static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
@@ -3011,14 +3005,6 @@
// The weak_globals table is visited by the GC itself (because it mutates the table).
}
-jclass CacheClass(JNIEnv* env, const char* jni_class_name) {
- ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name));
- if (c.get() == NULL) {
- return NULL;
- }
- return reinterpret_cast<jclass>(env->NewGlobalRef(c.get()));
-}
-
} // namespace art
std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs) {
diff --git a/src/jni_internal.h b/src/jni_internal.h
index 0d97aa4..2964bba 100644
--- a/src/jni_internal.h
+++ b/src/jni_internal.h
@@ -29,6 +29,13 @@
#include <iosfwd>
#include <string>
+#ifndef NATIVE_METHOD
+#define NATIVE_METHOD(className, functionName, signature) \
+ { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
+#endif
+#define REGISTER_NATIVE_METHODS(jni_class_name) \
+ RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods))
+
namespace art {
class ClassLoader;
@@ -41,7 +48,7 @@
void SetJniGlobalsMax(size_t max);
void JniAbort(const char* jni_function_name);
void* FindNativeMethod(Thread* thread);
-jclass CacheClass(JNIEnv* env, const char* jni_class_name);
+void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, size_t method_count);
template<typename T> T Decode(JNIEnv*, jobject);
template<typename T> T AddLocalReference(JNIEnv*, const Object*);
diff --git a/src/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 96a1ac1..afa09b3 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -16,20 +16,19 @@
#include <unistd.h>
-#include "class_loader.h"
#include "class_linker.h"
+#include "class_loader.h"
#include "dex_file.h"
#include "image.h"
+#include "jni_internal.h"
#include "logging.h"
#include "os.h"
#include "runtime.h"
-#include "space.h"
-#include "zip_archive.h"
-#include "toStringArray.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+#include "space.h"
+#include "toStringArray.h"
+#include "zip_archive.h"
namespace art {
@@ -98,23 +97,23 @@
}
if (dex_file == NULL) {
LOG(WARNING) << "Failed to open dex file: " << source;
- jniThrowExceptionFmt(env, "java/io/IOException", "unable to open dex file: %s",
- source.c_str());
+ Thread::Current()->ThrowNewExceptionF("Ljava/io/IOException;", "Unable to open dex file: %s",
+ source.c_str());
return 0;
}
return static_cast<jint>(reinterpret_cast<uintptr_t>(dex_file));
}
-static const DexFile* toDexFile(JNIEnv* env, int dex_file_address) {
+static const DexFile* toDexFile(int dex_file_address) {
const DexFile* dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(dex_file_address));
if (dex_file == NULL) {
- jniThrowNullPointerException(env, "dex_file == null");
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", "dex_file == null");
}
return dex_file;
}
-static void DexFile_closeDexFile(JNIEnv* env, jclass, jint cookie) {
- const DexFile* dex_file = toDexFile(env, cookie);
+static void DexFile_closeDexFile(JNIEnv*, jclass, jint cookie) {
+ const DexFile* dex_file = toDexFile(cookie);
if (dex_file == NULL) {
return;
}
@@ -127,7 +126,7 @@
static jclass DexFile_defineClassNative(JNIEnv* env, jclass, jstring javaName, jobject javaLoader,
jint cookie) {
ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- const DexFile* dex_file = toDexFile(env, cookie);
+ const DexFile* dex_file = toDexFile(cookie);
if (dex_file == NULL) {
return NULL;
}
@@ -150,7 +149,7 @@
}
static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jint cookie) {
- const DexFile* dex_file = toDexFile(env, cookie);
+ const DexFile* dex_file = toDexFile(cookie);
if (dex_file == NULL) {
return NULL;
}
@@ -175,7 +174,7 @@
if (!OS::FileExists(filename.c_str())) {
LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename.c_str() << "' does not exist";
- jniThrowExceptionFmt(env, "java/io/FileNotFoundException", "%s", filename.c_str());
+ Thread::Current()->ThrowNewExceptionF("Ljava/io/FileNotFoundException;", "%s", filename.c_str());
return JNI_TRUE;
}
@@ -265,7 +264,7 @@
};
void register_dalvik_system_DexFile(JNIEnv* env) {
- jniRegisterNativeMethods(env, "dalvik/system/DexFile", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("dalvik/system/DexFile");
}
} // namespace art
diff --git a/src/native/dalvik_system_VMDebug.cc b/src/native/dalvik_system_VMDebug.cc
index 49ef593..bb6f8bc 100644
--- a/src/native/dalvik_system_VMDebug.cc
+++ b/src/native/dalvik_system_VMDebug.cc
@@ -14,19 +14,17 @@
* limitations under the License.
*/
-#include "class_linker.h"
-#include "debugger.h"
-#include "jni_internal.h"
-#include "trace.h"
-#include "hprof/hprof.h"
-#include "ScopedUtfChars.h"
-#include "toStringArray.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
#include <string.h>
#include <unistd.h>
+#include "class_linker.h"
+#include "debugger.h"
+#include "hprof/hprof.h"
+#include "jni_internal.h"
+#include "ScopedUtfChars.h"
+#include "toStringArray.h"
+#include "trace.h"
+
namespace art {
static jobjectArray VMDebug_getVmFeatureList(JNIEnv* env, jclass) {
@@ -66,7 +64,7 @@
int fd = dup(originalFd);
if (fd < 0) {
- jniThrowExceptionFmt(env, "java/lang/RuntimeException", "dup(%d) failed: %s", originalFd, strerror(errno));
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "dup(%d) failed: %s", originalFd, strerror(errno));
return;
}
@@ -115,20 +113,20 @@
return Dbg::LastDebuggerActivity();
}
-static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+static void VMDebug_startInstructionCounting(JNIEnv*, jclass) {
+ Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
}
-static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+static void VMDebug_stopInstructionCounting(JNIEnv*, jclass) {
+ Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
}
-static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+static void VMDebug_getInstructionCount(JNIEnv*, jclass, jintArray /*javaCounts*/) {
+ Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
}
-static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
- jniThrowException(env, "java/lang/UnsupportedOperationException", NULL);
+static void VMDebug_resetInstructionCount(JNIEnv*, jclass) {
+ Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
}
static void VMDebug_printLoadedClasses(JNIEnv*, jclass, jint flags) {
@@ -156,7 +154,7 @@
static void VMDebug_dumpHprofData(JNIEnv* env, jclass, jstring javaFilename, jobject javaFd) {
// Only one of these may be NULL.
if (javaFilename == NULL && javaFd == NULL) {
- jniThrowNullPointerException(env, "fileName == null && fd == null");
+ Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "fileName == null && fd == null");
return;
}
@@ -175,7 +173,7 @@
if (javaFd != NULL) {
fd = jniGetFDFromFileDescriptor(env, javaFd);
if (fd < 0) {
- jniThrowException(env, "Ljava/lang/RuntimeException;", "Invalid file descriptor");
+ Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", "Invalid file descriptor");
return;
}
}
@@ -183,16 +181,16 @@
int result = hprof::DumpHeap(filename.c_str(), fd, false);
if (result != 0) {
// TODO: ideally we'd throw something more specific based on actual failure
- jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details: %d", result);
return;
}
}
-static void VMDebug_dumpHprofDataDdms(JNIEnv* env, jclass) {
+static void VMDebug_dumpHprofDataDdms(JNIEnv*, jclass) {
int result = hprof::DumpHeap("[DDMS]", -1, true);
if (result != 0) {
// TODO: ideally we'd throw something more specific based on actual failure
- jniThrowException(env, "Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details");
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Failure during heap dump; check log output for details: %d", result);
return;
}
}
@@ -255,7 +253,7 @@
};
void register_dalvik_system_VMDebug(JNIEnv* env) {
- jniRegisterNativeMethods(env, "dalvik/system/VMDebug", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("dalvik/system/VMDebug");
}
} // namespace art
diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc
index caac283..fbc2a01 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <limits.h>
+
#include "class_linker.h"
#include "debugger.h"
#include "jni_internal.h"
@@ -24,12 +26,8 @@
#include "space.h"
#include "thread.h"
#include "thread_list.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
#include "toStringArray.h"
-#include <limits.h>
-
namespace art {
static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) {
@@ -187,7 +185,7 @@
};
void register_dalvik_system_VMRuntime(JNIEnv* env) {
- jniRegisterNativeMethods(env, "dalvik/system/VMRuntime", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime");
}
} // namespace art
diff --git a/src/native/dalvik_system_VMStack.cc b/src/native/dalvik_system_VMStack.cc
index e0862c3..ab82694 100644
--- a/src/native/dalvik_system_VMStack.cc
+++ b/src/native/dalvik_system_VMStack.cc
@@ -14,16 +14,14 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_loader.h"
+#include "jni_internal.h"
#include "nth_caller_visitor.h"
#include "object.h"
#include "scoped_heap_lock.h"
#include "scoped_thread_list_lock.h"
#include "thread_list.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jobject GetThreadStack(JNIEnv* env, jobject javaThread) {
@@ -99,7 +97,7 @@
};
void register_dalvik_system_VMStack(JNIEnv* env) {
- jniRegisterNativeMethods(env, "dalvik/system/VMStack", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("dalvik/system/VMStack");
}
} // namespace art
diff --git a/src/native/dalvik_system_Zygote.cc b/src/native/dalvik_system_Zygote.cc
index b4f69fb..65fadf2 100644
--- a/src/native/dalvik_system_Zygote.cc
+++ b/src/native/dalvik_system_Zygote.cc
@@ -25,7 +25,6 @@
#include "cutils/sched_policy.h"
#include "debugger.h"
#include "jni_internal.h"
-#include "JniConstants.h"
#include "JNIHelp.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
@@ -375,7 +374,7 @@
};
void register_dalvik_system_Zygote(JNIEnv* env) {
- jniRegisterNativeMethods(env, "dalvik/system/Zygote", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("dalvik/system/Zygote");
}
} // namespace art
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 2cd7090..66c83c7 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -14,16 +14,15 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_linker.h"
#include "class_loader.h"
+#include "jni_internal.h"
#include "nth_caller_visitor.h"
#include "object.h"
#include "object_utils.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
+#include "well_known_classes.h"
namespace art {
@@ -62,9 +61,9 @@
if (c == NULL) {
ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
env->ExceptionClear();
- static jclass ClassNotFoundException_class = CacheClass(env, "java/lang/ClassNotFoundException");
- static jmethodID ctor = env->GetMethodID(ClassNotFoundException_class, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
- jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(ClassNotFoundException_class, ctor, javaName, cause.get()));
+ jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
+ WellKnownClasses::java_lang_ClassNotFoundException_init,
+ javaName, cause.get()));
env->Throw(cnfe);
return NULL;
}
@@ -89,8 +88,8 @@
template<typename T>
static jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
- jclass array_class = env->FindClass(array_class_name);
- jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
+ ScopedLocalRef<jclass> array_class(env, env->FindClass(array_class_name));
+ jobjectArray result = env->NewObjectArray(objects.size(), array_class.get(), NULL);
for (size_t i = 0; i < objects.size(); ++i) {
ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
env->SetObjectArrayElement(result, i, object.get());
@@ -472,7 +471,7 @@
};
void register_java_lang_Class(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/Class", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/Class");
}
} // namespace art
diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc
index 7c79fc1..51e4581 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "object.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jobject Object_internalClone(JNIEnv* env, jobject javaThis) {
@@ -50,7 +48,7 @@
};
void register_java_lang_Object(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/Object", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/Object");
}
} // namespace art
diff --git a/src/native/java_lang_Runtime.cc b/src/native/java_lang_Runtime.cc
index 1b5520b..b7e81af 100644
--- a/src/native/java_lang_Runtime.cc
+++ b/src/native/java_lang_Runtime.cc
@@ -14,15 +14,13 @@
* limitations under the License.
*/
-#include <unistd.h>
#include <limits.h>
+#include <unistd.h>
#include "heap.h"
#include "jni_internal.h"
#include "object.h"
#include "runtime.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
#include "ScopedUtfChars.h"
namespace art {
@@ -77,16 +75,16 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Runtime, freeMemory, "()J"),
- NATIVE_METHOD(Runtime, gc, "()V"),
- NATIVE_METHOD(Runtime, maxMemory, "()J"),
- NATIVE_METHOD(Runtime, nativeExit, "(IZ)V"),
- NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;"),
- NATIVE_METHOD(Runtime, totalMemory, "()J"),
+ NATIVE_METHOD(Runtime, freeMemory, "()J"),
+ NATIVE_METHOD(Runtime, gc, "()V"),
+ NATIVE_METHOD(Runtime, maxMemory, "()J"),
+ NATIVE_METHOD(Runtime, nativeExit, "(IZ)V"),
+ NATIVE_METHOD(Runtime, nativeLoad, "(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/String;"),
+ NATIVE_METHOD(Runtime, totalMemory, "()J"),
};
void register_java_lang_Runtime(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/Runtime", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/Runtime");
}
} // namespace art
diff --git a/src/native/java_lang_String.cc b/src/native/java_lang_String.cc
index 49bf234..f8fb4a7 100644
--- a/src/native/java_lang_String.cc
+++ b/src/native/java_lang_String.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "object.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
#ifdef HAVE__MEMCMP16
// "count" is in 16-bit units.
extern "C" uint32_t __memcmp16(const uint16_t* s0, const uint16_t* s1, size_t count);
@@ -108,7 +106,7 @@
};
void register_java_lang_String(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/String", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/String");
}
} // namespace art
diff --git a/src/native/java_lang_System.cc b/src/native/java_lang_System.cc
index 741b319..b0d1eec 100644
--- a/src/native/java_lang_System.cc
+++ b/src/native/java_lang_System.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "object.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
/*
* We make guarantees about the atomicity of accesses to primitive
* variables. These guarantees also apply to elements of arrays.
@@ -253,7 +251,7 @@
};
void register_java_lang_System(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/System");
}
} // namespace art
diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc
index 197c1b9..e009157 100644
--- a/src/native/java_lang_Thread.cc
+++ b/src/native/java_lang_Thread.cc
@@ -22,8 +22,6 @@
#include "thread.h"
#include "thread_list.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jobject Thread_currentThread(JNIEnv* env, jclass) {
@@ -145,7 +143,7 @@
};
void register_java_lang_Thread(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/Thread", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/Thread");
}
} // namespace art
diff --git a/src/native/java_lang_Throwable.cc b/src/native/java_lang_Throwable.cc
index 1d73027..625a34b 100644
--- a/src/native/java_lang_Throwable.cc
+++ b/src/native/java_lang_Throwable.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "thread.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jobject Throwable_nativeFillInStackTrace(JNIEnv* env, jclass) {
@@ -39,7 +37,7 @@
};
void register_java_lang_Throwable(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/Throwable", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/Throwable");
}
} // namespace art
diff --git a/src/native/java_lang_VMClassLoader.cc b/src/native/java_lang_VMClassLoader.cc
index 3d96c47..a976933 100644
--- a/src/native/java_lang_VMClassLoader.cc
+++ b/src/native/java_lang_VMClassLoader.cc
@@ -19,8 +19,6 @@
#include "ScopedUtfChars.h"
#include "zip_archive.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, jstring javaName) {
@@ -91,7 +89,7 @@
};
void register_java_lang_VMClassLoader(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/VMClassLoader", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/VMClassLoader");
}
} // namespace art
diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc
index 1c86aac..ea635d3 100644
--- a/src/native/java_lang_reflect_Array.cc
+++ b/src/native/java_lang_reflect_Array.cc
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_linker.h"
+#include "jni_internal.h"
#include "object.h"
#include "object_utils.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
// Recursively create an array with multiple dimensions. Elements may be
@@ -150,7 +148,7 @@
};
void register_java_lang_reflect_Array(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/reflect/Array", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Array");
}
} // namespace art
diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc
index 5d0434d..1094d06 100644
--- a/src/native/java_lang_reflect_Constructor.cc
+++ b/src/native/java_lang_reflect_Constructor.cc
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_linker.h"
+#include "jni_internal.h"
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
/*
@@ -63,7 +61,7 @@
};
void register_java_lang_reflect_Constructor(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/reflect/Constructor", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Constructor");
}
} // namespace art
diff --git a/src/native/java_lang_reflect_Field.cc b/src/native/java_lang_reflect_Field.cc
index 3e0c9d7..bd33c0e 100644
--- a/src/native/java_lang_reflect_Field.cc
+++ b/src/native/java_lang_reflect_Field.cc
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_linker.h"
+#include "jni_internal.h"
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
@@ -79,7 +77,7 @@
o = Decode<Object*>(env, javaObj);
Class* declaringClass = f->GetDeclaringClass();
- if (!VerifyObjectInClass(env, o, declaringClass)) {
+ if (!VerifyObjectInClass(o, declaringClass)) {
return false;
}
return true;
@@ -323,7 +321,7 @@
};
void register_java_lang_reflect_Field(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/reflect/Field", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Field");
}
} // namespace art
diff --git a/src/native/java_lang_reflect_Method.cc b/src/native/java_lang_reflect_Method.cc
index a5a705b..bf5c850 100644
--- a/src/native/java_lang_reflect_Method.cc
+++ b/src/native/java_lang_reflect_Method.cc
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#include "jni_internal.h"
#include "class_linker.h"
+#include "jni_internal.h"
#include "object.h"
#include "object_utils.h"
#include "reflection.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver, jobject javaArgs) {
@@ -60,7 +58,7 @@
};
void register_java_lang_reflect_Method(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/reflect/Method", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Method");
}
} // namespace art
diff --git a/src/native/java_lang_reflect_Proxy.cc b/src/native/java_lang_reflect_Proxy.cc
index bac20b0..eca6c32 100644
--- a/src/native/java_lang_reflect_Proxy.cc
+++ b/src/native/java_lang_reflect_Proxy.cc
@@ -14,11 +14,9 @@
* limitations under the License.
*/
+#include "class_linker.h"
#include "jni_internal.h"
#include "object.h"
-#include "class_linker.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
namespace art {
@@ -40,7 +38,7 @@
};
void register_java_lang_reflect_Proxy(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/reflect/Proxy", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Proxy");
}
} // namespace art
diff --git a/src/native/java_util_concurrent_atomic_AtomicLong.cc b/src/native/java_util_concurrent_atomic_AtomicLong.cc
index 118b9e4..7caa23f 100644
--- a/src/native/java_util_concurrent_atomic_AtomicLong.cc
+++ b/src/native/java_util_concurrent_atomic_AtomicLong.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "object.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jboolean AtomicLong_VMSupportsCS8(JNIEnv*, jclass) {
@@ -30,7 +28,7 @@
};
void register_java_util_concurrent_atomic_AtomicLong(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/util/concurrent/atomic/AtomicLong", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("java/util/concurrent/atomic/AtomicLong");
}
} // namespace art
diff --git a/src/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/src/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
index ed36590..e3c31b0 100644
--- a/src/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
+++ b/src/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc
@@ -16,9 +16,7 @@
#include "debugger.h"
#include "logging.h"
-
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-#include "ScopedPrimitiveArray.h" // Last to avoid problems with LOG redefinition.
+#include "ScopedPrimitiveArray.h"
namespace art {
@@ -34,7 +32,7 @@
};
void register_org_apache_harmony_dalvik_ddmc_DdmServer(JNIEnv* env) {
- jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/ddmc/DdmServer", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("org/apache/harmony/dalvik/ddmc/DdmServer");
}
} // namespace art
diff --git a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
index 88416af..3766546 100644
--- a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
+++ b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
@@ -15,15 +15,14 @@
*/
#include "debugger.h"
+#include "jni_internal.h"
#include "logging.h"
#include "scoped_heap_lock.h"
#include "scoped_thread_list_lock.h"
+#include "ScopedPrimitiveArray.h"
#include "stack.h"
#include "thread_list.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-#include "ScopedPrimitiveArray.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static void DdmVmInternal_enableRecentAllocations(JNIEnv*, jclass, jboolean enable) {
@@ -162,7 +161,7 @@
};
void register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(JNIEnv* env) {
- jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/ddmc/DdmVmInternal", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("org/apache/harmony/dalvik/ddmc/DdmVmInternal");
}
} // namespace art
diff --git a/src/native/sun_misc_Unsafe.cc b/src/native/sun_misc_Unsafe.cc
index 8cc549a..360f241 100644
--- a/src/native/sun_misc_Unsafe.cc
+++ b/src/native/sun_misc_Unsafe.cc
@@ -17,8 +17,6 @@
#include "jni_internal.h"
#include "object.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
static jlong Unsafe_objectFieldOffset0(JNIEnv* env, jclass, jobject javaField) {
@@ -187,7 +185,7 @@
};
void register_sun_misc_Unsafe(JNIEnv* env) {
- jniRegisterNativeMethods(env, "sun/misc/Unsafe", gMethods, NELEM(gMethods));
+ REGISTER_NATIVE_METHODS("sun/misc/Unsafe");
}
} // namespace art
diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc
index 66d0e2c..26f61cf 100644
--- a/src/oat/runtime/support_proxy.cc
+++ b/src/oat/runtime/support_proxy.cc
@@ -19,6 +19,7 @@
#include "reflection.h"
#include "runtime_support.h"
#include "thread.h"
+#include "well_known_classes.h"
#include "ScopedLocalRef.h"
@@ -161,19 +162,10 @@
param_index++;
}
// Get the InvocationHandler method and the field that holds it within the Proxy object
- static jmethodID inv_hand_invoke_mid = NULL;
- static jfieldID proxy_inv_hand_fid = NULL;
- if (proxy_inv_hand_fid == NULL) {
- ScopedLocalRef<jclass> proxy(env, env->FindClass("java/lang/reflect/Proxy"));
- proxy_inv_hand_fid = env->GetFieldID(proxy.get(), "h", "Ljava/lang/reflect/InvocationHandler;");
- ScopedLocalRef<jclass> inv_hand_class(env, env->FindClass("java/lang/reflect/InvocationHandler"));
- inv_hand_invoke_mid = env->GetMethodID(inv_hand_class.get(), "invoke",
- "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
- }
- DCHECK(env->IsInstanceOf(rcvr_jobj, env->FindClass("java/lang/reflect/Proxy")));
- jobject inv_hand = env->GetObjectField(rcvr_jobj, proxy_inv_hand_fid);
+ DCHECK(env->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
+ jobject inv_hand = env->GetObjectField(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy_h);
// Call InvocationHandler.invoke
- jobject result = env->CallObjectMethodA(inv_hand, inv_hand_invoke_mid, args_jobj);
+ jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj);
// Place result in stack args
if (!self->IsExceptionPending()) {
Object* result_ref = self->DecodeJObject(result);
diff --git a/src/oatexec.cc b/src/oatexec.cc
index d080560..e8e2050 100644
--- a/src/oatexec.cc
+++ b/src/oatexec.cc
@@ -21,12 +21,13 @@
#include <cstring>
#include <string>
-#include "ScopedLocalRef.h"
-#include "UniquePtr.h"
#include "jni.h"
#include "logging.h"
-#include "toStringArray.h"
#include "object.h"
+#include "ScopedLocalRef.h"
+#include "toStringArray.h"
+#include "UniquePtr.h"
+#include "well_known_classes.h"
namespace art {
@@ -39,17 +40,12 @@
}
// We now have a Method instance. We need to call its
// getModifiers() method.
- ScopedLocalRef<jclass> method(env, env->FindClass("java/lang/reflect/Method"));
- if (method.get() == NULL) {
- fprintf(stderr, "Failed to find class Method\n");
+ jmethodID mid = env->GetMethodID(WellKnownClasses::java_lang_reflect_Method, "getModifiers", "()I");
+ if (mid == NULL) {
+ fprintf(stderr, "Failed to find java.lang.reflect.Method.getModifiers\n");
return false;
}
- jmethodID get_modifiers = env->GetMethodID(method.get(), "getModifiers", "()I");
- if (get_modifiers == NULL) {
- fprintf(stderr, "Failed to find reflect.Method.getModifiers\n");
- return false;
- }
- int modifiers = env->CallIntMethod(reflected.get(), get_modifiers);
+ int modifiers = env->CallIntMethod(reflected.get(), mid);
if ((modifiers & kAccPublic) == 0) {
return false;
}
diff --git a/src/reflection.cc b/src/reflection.cc
index 010211e..2b72944 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -21,8 +21,6 @@
#include "object.h"
#include "object_utils.h"
-#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
-
namespace art {
Method* gBoolean_valueOf;
@@ -62,7 +60,7 @@
if (!m->IsStatic()) {
// Check that the receiver is non-null and an instance of the field's declaring class.
receiver = Decode<Object*>(env, javaReceiver);
- if (!VerifyObjectInClass(env, receiver, declaring_class)) {
+ if (!VerifyObjectInClass(receiver, declaring_class)) {
return NULL;
}
@@ -117,18 +115,18 @@
return AddLocalReference<jobject>(env, value.GetL());
}
-bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
+bool VerifyObjectInClass(Object* o, Class* c) {
const char* exception = NULL;
if (o == NULL) {
- exception = "java/lang/NullPointerException";
+ exception = "Ljava/lang/NullPointerException;";
} else if (!o->InstanceOf(c)) {
- exception = "java/lang/IllegalArgumentException";
+ exception = "Ljava/lang/IllegalArgumentException;";
}
if (exception != NULL) {
std::string expected_class_name(PrettyDescriptor(c));
std::string actual_class_name(PrettyTypeOf(o));
- jniThrowExceptionFmt(env, exception, "expected receiver of type %s, but got %s",
- expected_class_name.c_str(), actual_class_name.c_str());
+ Thread::Current()->ThrowNewExceptionF(exception, "expected receiver of type %s, but got %s",
+ expected_class_name.c_str(), actual_class_name.c_str());
return false;
}
return true;
diff --git a/src/reflection.h b/src/reflection.h
index 50c36d7..6b47440 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -38,7 +38,7 @@
jobject InvokeMethod(JNIEnv* env, jobject method, jobject receiver, jobject args);
-bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c);
+bool VerifyObjectInClass(Object* o, Class* c);
} // namespace art
diff --git a/src/runtime.cc b/src/runtime.cc
index e033059..226334e 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -43,9 +43,9 @@
#include "trace.h"
#include "UniquePtr.h"
#include "verifier/method_verifier.h"
+#include "well_known_classes.h"
-// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
-#include "JniConstants.h"
+#include "JniConstants.h" // Last to avoid LOG redefinition in ics-mr1-plus-art.
namespace art {
@@ -516,21 +516,17 @@
CHECK_EQ(self->GetState(), kNative);
JNIEnv* env = self->GetJniEnv();
- ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
- CHECK(ClassLoader_class.get() != NULL);
- jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
+ jmethodID getSystemClassLoader = env->GetStaticMethodID(WellKnownClasses::java_lang_ClassLoader,
"getSystemClassLoader",
"()Ljava/lang/ClassLoader;");
CHECK(getSystemClassLoader != NULL);
- ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
+ ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(WellKnownClasses::java_lang_ClassLoader,
getSystemClassLoader));
CHECK(class_loader.get() != NULL);
Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
- ScopedLocalRef<jclass> Thread_class(env, env->FindClass("java/lang/Thread"));
- CHECK(Thread_class.get() != NULL);
- jfieldID contextClassLoader = env->GetFieldID(Thread_class.get(),
+ jfieldID contextClassLoader = env->GetFieldID(WellKnownClasses::java_lang_Thread,
"contextClassLoader",
"Ljava/lang/ClassLoader;");
CHECK(contextClassLoader != NULL);
@@ -595,11 +591,7 @@
CHECK_EQ(self->GetState(), kNative);
JNIEnv* env = self->GetJniEnv();
- ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Daemons"));
- CHECK(c.get() != NULL);
- jmethodID mid = env->GetStaticMethodID(c.get(), "start", "()V");
- CHECK(mid != NULL);
- env->CallStaticVoidMethod(c.get(), mid);
+ env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons, WellKnownClasses::java_lang_Daemons_start);
CHECK(!env->ExceptionCheck());
VLOG(startup) << "Runtime::StartDaemonThreads exiting";
@@ -708,6 +700,7 @@
// First set up JniConstants, which is used by both the runtime's built-in native
// methods and libcore.
JniConstants::init(env);
+ WellKnownClasses::Init(env);
// Then set up the native methods provided by the runtime itself.
RegisterRuntimeNativeMethods(env);
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index f8b40a2..8d649a6 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -17,6 +17,7 @@
#include "runtime_support.h"
#include "ScopedLocalRef.h"
+#include "well_known_classes.h"
double art_l2d(int64_t l) {
return (double) l;
@@ -609,21 +610,15 @@
}
void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
- ScopedLocalRef<jclass> jlr_UTE_class(env,
- env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
- if (jlr_UTE_class.get() == NULL) {
+ jmethodID jlre_UTE_constructor = env->GetMethodID(WellKnownClasses::java_lang_reflect_UndeclaredThrowableException, "<init>",
+ "(Ljava/lang/Throwable;)V");
+ jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
+ ScopedLocalRef<jthrowable> jlr_UTE(env,
+ reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_reflect_UndeclaredThrowableException,
+ jlre_UTE_constructor, jexception)));
+ int rc = env->Throw(jlr_UTE.get());
+ if (rc != JNI_OK) {
LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
- } else {
- jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
- "(Ljava/lang/Throwable;)V");
- jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
- ScopedLocalRef<jthrowable> jlr_UTE(env,
- reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
- jexception)));
- int rc = env->Throw(jlr_UTE.get());
- if (rc != JNI_OK) {
- LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
- }
}
CHECK(self->IsExceptionPending());
}
diff --git a/src/thread.cc b/src/thread.cc
index 01e0771..a986ed5 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -50,6 +50,7 @@
#include "thread_list.h"
#include "utils.h"
#include "verifier/gc_map.h"
+#include "well_known_classes.h"
namespace art {
@@ -339,15 +340,16 @@
jint thread_priority = GetNativePriority();
jboolean thread_is_daemon = as_daemon;
- ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/Thread"));
- ScopedLocalRef<jobject> peer(env, env->AllocObject(c.get()));
+ ScopedLocalRef<jobject> peer(env, env->AllocObject(WellKnownClasses::java_lang_Thread));
peer_ = DecodeJObject(peer.get());
if (peer_ == NULL) {
CHECK(IsExceptionPending());
return;
}
- jmethodID mid = env->GetMethodID(c.get(), "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
- env->CallNonvirtualVoidMethod(peer.get(), c.get(), mid, java_thread_group.get(), thread_name.get(), thread_priority, thread_is_daemon);
+ env->CallNonvirtualVoidMethod(peer.get(),
+ WellKnownClasses::java_lang_Thread,
+ WellKnownClasses::java_lang_Thread_init,
+ java_thread_group.get(), thread_name.get(), thread_priority, thread_is_daemon);
CHECK(!IsExceptionPending()) << " " << PrettyTypeOf(GetException());
SetVmData(peer_, Thread::Current());
@@ -524,11 +526,10 @@
os << " | schedstat=( " << scheduler_stats << " )"
<< " utm=" << utime
<< " stm=" << stime
- << " core=" << task_cpu
- << " HZ=" << sysconf(_SC_CLK_TCK) << "\n";
-
- os << " | stackSize=" << PrettySize(stack_size_)
- << " stack=" << reinterpret_cast<void*>(stack_begin_) << "-" << reinterpret_cast<void*>(stack_end_) << "\n";
+ << " core=" << task_cpu;
+ os << " HZ=" << sysconf(_SC_CLK_TCK) << "\n"
+ << " | stack=" << reinterpret_cast<void*>(stack_begin_) << "-" << reinterpret_cast<void*>(stack_end_)
+ << " stackSize=" << PrettySize(stack_size_) << "\n";
}
#if !defined(ART_USE_LLVM_COMPILER)
diff --git a/src/well_known_classes.cc b/src/well_known_classes.cc
new file mode 100644
index 0000000..7e21a66
--- /dev/null
+++ b/src/well_known_classes.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "well_known_classes.h"
+
+#include <stdlib.h>
+
+#include "logging.h"
+#include "ScopedLocalRef.h"
+
+namespace art {
+
+jclass WellKnownClasses::com_android_dex_Dex;
+jclass WellKnownClasses::java_lang_ClassLoader;
+jclass WellKnownClasses::java_lang_ClassNotFoundException;
+jclass WellKnownClasses::java_lang_Daemons;
+jclass WellKnownClasses::java_lang_Error;
+jclass WellKnownClasses::java_lang_ExceptionInInitializerError;
+jclass WellKnownClasses::java_lang_reflect_InvocationHandler;
+jclass WellKnownClasses::java_lang_reflect_Method;
+jclass WellKnownClasses::java_lang_reflect_Proxy;
+jclass WellKnownClasses::java_lang_reflect_UndeclaredThrowableException;
+jclass WellKnownClasses::java_lang_Thread;
+jclass WellKnownClasses::java_nio_ReadWriteDirectByteBuffer;
+jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk;
+jclass WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer;
+
+jmethodID WellKnownClasses::com_android_dex_Dex_create;
+jmethodID WellKnownClasses::java_lang_ClassNotFoundException_init;
+jmethodID WellKnownClasses::java_lang_Daemons_requestHeapTrim;
+jmethodID WellKnownClasses::java_lang_Daemons_start;
+jmethodID WellKnownClasses::java_lang_reflect_InvocationHandler_invoke;
+jmethodID WellKnownClasses::java_lang_Thread_init;
+jmethodID WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_init;
+jmethodID WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_broadcast;
+jmethodID WellKnownClasses::org_apache_harmony_dalvik_ddmc_DdmServer_dispatch;
+
+jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
+jfieldID WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_capacity;
+jfieldID WellKnownClasses::java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress;
+jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_data;
+jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_length;
+jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_offset;
+jfieldID WellKnownClasses::org_apache_harmony_dalvik_ddmc_Chunk_type;
+
+static jclass CacheClass(JNIEnv* env, const char* jni_class_name) {
+ ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name));
+ if (c.get() == NULL) {
+ LOG(FATAL) << "Couldn't find class: " << jni_class_name;
+ }
+ return reinterpret_cast<jclass>(env->NewGlobalRef(c.get()));
+}
+
+static jfieldID CacheField(JNIEnv* env, jclass c, const char* name, const char* signature) {
+ jfieldID fid = env->GetFieldID(c, name, signature);
+ if (fid == NULL) {
+ LOG(FATAL) << "Couldn't find field \"" << name << "\" with signature \"" << signature << "\"";
+ }
+ return fid;
+}
+
+static jmethodID CacheMethod(JNIEnv* env, jclass c, bool is_static, const char* name, const char* signature) {
+ jmethodID mid = is_static ? env->GetStaticMethodID(c, name, signature) : env->GetMethodID(c, name, signature);
+ if (mid == NULL) {
+ LOG(FATAL) << "Couldn't find method \"" << name << "\" with signature \"" << signature << "\"";
+ }
+ return mid;
+}
+
+void WellKnownClasses::Init(JNIEnv* env) {
+ com_android_dex_Dex = CacheClass(env, "com/android/dex/Dex");
+ java_lang_ClassLoader = CacheClass(env, "java/lang/ClassLoader");
+ java_lang_ClassNotFoundException = CacheClass(env, "java/lang/ClassNotFoundException");
+ java_lang_Daemons = CacheClass(env, "java/lang/Daemons");
+ java_lang_Error = CacheClass(env, "java/lang/Error");
+ java_lang_ExceptionInInitializerError = CacheClass(env, "java/lang/ExceptionInInitializerError");
+ java_lang_reflect_InvocationHandler = CacheClass(env, "java/lang/reflect/InvocationHandler");
+ java_lang_reflect_Method = CacheClass(env, "java/lang/reflect/Method");
+ java_lang_reflect_Proxy = CacheClass(env, "java/lang/reflect/Proxy");
+ java_lang_reflect_UndeclaredThrowableException = CacheClass(env, "java/lang/reflect/UndeclaredThrowableException");
+ java_lang_Thread = CacheClass(env, "java/lang/Thread");
+ java_nio_ReadWriteDirectByteBuffer = CacheClass(env, "java/nio/ReadWriteDirectByteBuffer");
+ org_apache_harmony_dalvik_ddmc_Chunk = CacheClass(env, "org/apache/harmony/dalvik/ddmc/Chunk");
+ org_apache_harmony_dalvik_ddmc_DdmServer = CacheClass(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
+
+ com_android_dex_Dex_create = CacheMethod(env, com_android_dex_Dex, true, "create", "(Ljava/nio/ByteBuffer;)Lcom/android/dex/Dex;");
+ java_lang_ClassNotFoundException_init = CacheMethod(env, java_lang_ClassNotFoundException, false, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
+ java_lang_Daemons_requestHeapTrim = CacheMethod(env, java_lang_Daemons, true, "requestHeapTrim", "()V");
+ java_lang_Daemons_start = CacheMethod(env, java_lang_Daemons, true, "start", "()V");
+ java_lang_reflect_InvocationHandler_invoke = CacheMethod(env, java_lang_reflect_InvocationHandler, false, "invoke", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
+ java_lang_Thread_init = CacheMethod(env, java_lang_Thread, false, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
+ java_nio_ReadWriteDirectByteBuffer_init = CacheMethod(env, java_nio_ReadWriteDirectByteBuffer, false, "<init>", "(II)V");
+ org_apache_harmony_dalvik_ddmc_DdmServer_broadcast = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "broadcast", "(I)V");
+ org_apache_harmony_dalvik_ddmc_DdmServer_dispatch = CacheMethod(env, org_apache_harmony_dalvik_ddmc_DdmServer, true, "dispatch", "(I[BII)Lorg/apache/harmony/dalvik/ddmc/Chunk;");
+
+ java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, "h", "Ljava/lang/reflect/InvocationHandler;");
+ java_nio_ReadWriteDirectByteBuffer_capacity = CacheField(env, java_nio_ReadWriteDirectByteBuffer, "capacity", "I");
+ java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_ReadWriteDirectByteBuffer, "effectiveDirectAddress", "I");
+ org_apache_harmony_dalvik_ddmc_Chunk_data = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, "data", "[B");
+ org_apache_harmony_dalvik_ddmc_Chunk_length = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, "length", "I");
+ org_apache_harmony_dalvik_ddmc_Chunk_offset = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, "offset", "I");
+ org_apache_harmony_dalvik_ddmc_Chunk_type = CacheField(env, org_apache_harmony_dalvik_ddmc_Chunk, "type", "I");
+}
+
+} // namespace art
diff --git a/src/well_known_classes.h b/src/well_known_classes.h
new file mode 100644
index 0000000..5d45938
--- /dev/null
+++ b/src/well_known_classes.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ART_SRC_WELL_KNOWN_CLASSES_H_
+#define ART_SRC_WELL_KNOWN_CLASSES_H_
+
+#include "jni.h"
+
+namespace art {
+
+// Various classes used in JNI. We cache them so we don't have to keep looking
+// them up. Similar to libcore's JniConstants (except there's no overlap, so
+// we keep them separate).
+
+struct WellKnownClasses {
+ static void Init(JNIEnv* env);
+
+ static jclass com_android_dex_Dex;
+ static jclass java_lang_ClassLoader;
+ static jclass java_lang_ClassNotFoundException;
+ static jclass java_lang_Daemons;
+ static jclass java_lang_Error;
+ static jclass java_lang_ExceptionInInitializerError;
+ static jclass java_lang_reflect_InvocationHandler;
+ static jclass java_lang_reflect_Method;
+ static jclass java_lang_reflect_Proxy;
+ static jclass java_lang_reflect_UndeclaredThrowableException;
+ static jclass java_lang_Thread;
+ static jclass java_nio_ReadWriteDirectByteBuffer;
+ static jclass org_apache_harmony_dalvik_ddmc_Chunk;
+ static jclass org_apache_harmony_dalvik_ddmc_DdmServer;
+
+ static jmethodID com_android_dex_Dex_create;
+ static jmethodID java_lang_ClassNotFoundException_init;
+ static jmethodID java_lang_Daemons_requestHeapTrim;
+ static jmethodID java_lang_Daemons_start;
+ static jmethodID java_lang_reflect_InvocationHandler_invoke;
+ static jmethodID java_lang_Thread_init;
+ static jmethodID java_nio_ReadWriteDirectByteBuffer_init;
+ static jmethodID org_apache_harmony_dalvik_ddmc_DdmServer_broadcast;
+ static jmethodID org_apache_harmony_dalvik_ddmc_DdmServer_dispatch;
+
+ static jfieldID java_lang_reflect_Proxy_h;
+ static jfieldID java_nio_ReadWriteDirectByteBuffer_capacity;
+ static jfieldID java_nio_ReadWriteDirectByteBuffer_effectiveDirectAddress;
+ static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_data;
+ static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_length;
+ static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_offset;
+ static jfieldID org_apache_harmony_dalvik_ddmc_Chunk_type;
+};
+
+} // namespace art
+
+#endif // ART_SRC_WELL_KNOWN_CLASSES_H_