Increase use of ScopedJniThreadState.
Move the routines for changing Object* to jobject and vice-versa
(AddLocalReference and Decode) to ScopedJniThreadState to enforce use of
Object*s in the Runnable thread state. In the Runnable thread state
suspension is necessary before GC can take place.
Reduce use of const ClassLoader* as the code bottoms out in FindClass
and with a field assignment where the const is cast away (ie if we're
not going to enforce the const-ness we shouldn't pretend it is).
Refactor the Thread::Attach API so that we're not handling raw Objects on
unattached threads.
Remove some unreachable code.
Change-Id: I0fa969f49ee6a8f10752af74a6b0e04d46b4cd97
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 99e3a26..ecab777 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -27,8 +27,8 @@
namespace art {
-static Class* DecodeClass(JNIEnv* env, jobject java_class) {
- Class* c = Decode<Class*>(env, java_class);
+static Class* DecodeClass(const ScopedJniThreadState& ts, jobject java_class) {
+ Class* c = ts.Decode<Class*>(java_class);
DCHECK(c != NULL);
DCHECK(c->IsClass());
// TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
@@ -39,7 +39,7 @@
// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
+ ScopedJniThreadState ts(env);
ScopedUtfChars name(env, javaName);
if (name.c_str() == NULL) {
return NULL;
@@ -55,8 +55,7 @@
}
std::string descriptor(DotToDescriptor(name.c_str()));
- Object* loader = Decode<Object*>(env, javaLoader);
- ClassLoader* class_loader = down_cast<ClassLoader*>(loader);
+ ClassLoader* class_loader = ts.Decode<ClassLoader*>(javaLoader);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
if (c == NULL) {
@@ -71,11 +70,12 @@
if (initialize) {
class_linker->EnsureInitialized(c, true, true);
}
- return AddLocalReference<jclass>(env, c);
+ return ts.AddLocalReference<jclass>(c);
}
static jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) {
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
if (c->IsPrimitive() || c->IsArrayClass() || c->IsProxyClass()) {
return 0; // primitive, array and proxy classes don't have class definitions
}
@@ -88,12 +88,13 @@
}
template<typename T>
-static jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
- ScopedLocalRef<jclass> array_class(env, env->FindClass(array_class_name));
- jobjectArray result = env->NewObjectArray(objects.size(), array_class.get(), NULL);
+static jobjectArray ToArray(const ScopedJniThreadState& ts, const char* array_class_name,
+ const std::vector<T*>& objects) {
+ ScopedLocalRef<jclass> array_class(ts.Env(), ts.Env()->FindClass(array_class_name));
+ jobjectArray result = ts.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());
+ ScopedLocalRef<jobject> object(ts.Env(), ts.AddLocalReference<jobject>(objects[i]));
+ ts.Env()->SetObjectArrayElement(result, i, object.get());
}
return result;
}
@@ -109,11 +110,8 @@
}
static jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
std::vector<Method*> constructors;
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
Method* m = c->GetDirectMethod(i);
@@ -122,7 +120,7 @@
}
}
- return ToArray(env, "java/lang/reflect/Constructor", constructors);
+ return ToArray(ts, "java/lang/reflect/Constructor", constructors);
}
static bool IsVisibleField(Field* f, bool public_only) {
@@ -133,12 +131,8 @@
}
static jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
std::vector<Field*> fields;
FieldHelper fh;
for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
@@ -170,7 +164,7 @@
}
}
- return ToArray(env, "java/lang/reflect/Field", fields);
+ return ToArray(ts, "java/lang/reflect/Field", fields);
}
static bool IsVisibleMethod(Method* m, bool public_only) {
@@ -187,8 +181,8 @@
}
static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
- ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
if (c == NULL) {
return NULL;
}
@@ -224,11 +218,12 @@
}
}
- return ToArray(env, "java/lang/reflect/Method", methods);
+ return ToArray(ts, "java/lang/reflect/Method", methods);
}
static jobject Class_getDex(JNIEnv* env, jobject javaClass) {
- Class* c = DecodeClass(env, javaClass);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
DexCache* dex_cache = c->GetDexCache();
if (dex_cache == NULL) {
@@ -287,13 +282,10 @@
static jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName,
jobjectArray javaArgs) {
- Class* c = DecodeClass(env, javaClass);
- if (c == NULL) {
- return NULL;
- }
-
- std::string name(Decode<String*>(env, javaName)->ToModifiedUtf8());
- ObjectArray<Class>* arg_array = Decode<ObjectArray<Class>*>(env, javaArgs);
+ ScopedJniThreadState ts(env);
+ Class* c = DecodeClass(ts, javaClass);
+ std::string name(ts.Decode<String*>(javaName)->ToModifiedUtf8());
+ ObjectArray<Class>* arg_array = ts.Decode<ObjectArray<Class>*>(javaArgs);
Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
if (m == NULL) {
@@ -301,7 +293,7 @@
}
if (m != NULL) {
- return AddLocalReference<jobject>(env, m);
+ return ts.AddLocalReference<jobject>(m);
} else {
return NULL;
}
@@ -309,12 +301,8 @@
static jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass java_class, jobject jname) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, java_class);
- if (c == NULL) {
- return NULL;
- }
-
- String* name = Decode<String*>(env, jname);
+ Class* c = DecodeClass(ts, java_class);
+ String* name = ts.Decode<String*>(jname);
DCHECK(name->GetClass()->IsStringClass());
FieldHelper fh;
@@ -326,7 +314,7 @@
DCHECK(env->ExceptionOccurred());
return NULL;
}
- return AddLocalReference<jclass>(env, f);
+ return ts.AddLocalReference<jclass>(f);
}
}
for (size_t i = 0; i < c->NumStaticFields(); ++i) {
@@ -337,7 +325,7 @@
DCHECK(env->ExceptionOccurred());
return NULL;
}
- return AddLocalReference<jclass>(env, f);
+ return ts.AddLocalReference<jclass>(f);
}
}
return NULL;
@@ -345,20 +333,20 @@
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, javaThis);
- return AddLocalReference<jstring>(env, c->ComputeName());
+ Class* c = DecodeClass(ts, javaThis);
+ return ts.AddLocalReference<jstring>(c->ComputeName());
}
static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(env, javaThis));
- return AddLocalReference<jobjectArray>(env, c->GetInterfaces()->Clone());
+ SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(ts, javaThis));
+ return ts.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone());
}
static jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
ScopedJniThreadState ts(env);
- Class* lhs = DecodeClass(env, javaLhs);
- Class* rhs = Decode<Class*>(env, javaRhs); // Can be null.
+ Class* lhs = DecodeClass(ts, javaLhs);
+ Class* rhs = ts.Decode<Class*>(javaRhs); // Can be null.
if (rhs == NULL) {
ts.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null");
return JNI_FALSE;
@@ -397,7 +385,7 @@
static jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
ScopedJniThreadState ts(env);
- Class* c = DecodeClass(env, javaThis);
+ Class* c = DecodeClass(ts, javaThis);
if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
ts.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
"Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
@@ -451,8 +439,8 @@
}
// invoke constructor; unlike reflection calls, we don't wrap exceptions
- jclass java_class = AddLocalReference<jclass>(env, c);
- jmethodID mid = EncodeMethod(init);
+ jclass java_class = ts.AddLocalReference<jclass>(c);
+ jmethodID mid = ts.EncodeMethod(init);
return env->NewObject(java_class, mid);
}