diff options
Diffstat (limited to 'src/native/java_lang_Class.cc')
-rw-r--r-- | src/native/java_lang_Class.cc | 324 |
1 files changed, 3 insertions, 321 deletions
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc index 488df80e65..59c9bef0f1 100644 --- a/src/native/java_lang_Class.cc +++ b/src/native/java_lang_Class.cc @@ -88,147 +88,6 @@ static jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) { } } -// TODO: Remove this redundant struct when GCC annotalysis works correctly on top-level functions. -struct WorkAroundGccAnnotalysisBug { -template<typename T> -static jobjectArray ToArray(const ScopedObjectAccessUnchecked& soa, const char* array_class_name, - const std::vector<T*>& objects) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - ScopedLocalRef<jclass> array_class(soa.Env(), soa.Env()->FindClass(array_class_name)); - jobjectArray result = soa.Env()->NewObjectArray(objects.size(), array_class.get(), NULL); - for (size_t i = 0; i < objects.size(); ++i) { - ScopedLocalRef<jobject> object(soa.Env(), soa.AddLocalReference<jobject>(objects[i])); - soa.Env()->SetObjectArrayElement(result, i, object.get()); - } - return result; -} -}; -#define ToArray(a, b, c) WorkAroundGccAnnotalysisBug::ToArray(a, b, c) - -static bool IsVisibleConstructor(AbstractMethod* m, bool public_only) { - if (public_only && !m->IsPublic()) { - return false; - } - if (m->IsStatic()) { - return false; - } - return m->IsConstructor(); -} - -static jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); - std::vector<AbstractMethod*> constructors; // TODO: Use Constructor instead of AbstractMethod - for (size_t i = 0; i < c->NumDirectMethods(); ++i) { - AbstractMethod* m = c->GetDirectMethod(i); - if (IsVisibleConstructor(m, publicOnly)) { - constructors.push_back(m); - } - } - - return ToArray(soa, "java/lang/reflect/Constructor", constructors); -} - -static bool IsVisibleField(Field* f, bool public_only) { - if (public_only && !f->IsPublic()) { - return false; - } - return true; -} - -static jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); - std::vector<Field*> fields; - FieldHelper fh; - for (size_t i = 0; i < c->NumInstanceFields(); ++i) { - Field* f = c->GetInstanceField(i); - fh.ChangeField(f); - if (IsVisibleField(f, publicOnly)) { - if (fh.GetType() == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - fields.push_back(f); - } - if (env->ExceptionOccurred()) { - return NULL; - } - } - for (size_t i = 0; i < c->NumStaticFields(); ++i) { - Field* f = c->GetStaticField(i); - fh.ChangeField(f); - if (IsVisibleField(f, publicOnly)) { - if (fh.GetType() == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - fields.push_back(f); - } - if (env->ExceptionOccurred()) { - return NULL; - } - } - - return ToArray(soa, "java/lang/reflect/Field", fields); -} - -static bool IsVisibleMethod(AbstractMethod* m, bool public_only) { - if (public_only && !m->IsPublic()) { - return false; - } - if (m->IsConstructor()) { - return false; - } - if (m->IsMiranda()) { - return false; - } - return true; -} - -static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); - if (c == NULL) { - return NULL; - } - - std::vector<AbstractMethod*> methods; - MethodHelper mh; - for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { - AbstractMethod* m = c->GetVirtualMethod(i); - mh.ChangeMethod(m); - if (IsVisibleMethod(m, publicOnly)) { - // TODO: the use of GetParameterTypes creates an unused array here. - if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - methods.push_back(m); - } - if (env->ExceptionOccurred()) { - return NULL; - } - } - for (size_t i = 0; i < c->NumDirectMethods(); ++i) { - AbstractMethod* m = c->GetDirectMethod(i); - mh.ChangeMethod(m); - if (IsVisibleMethod(m, publicOnly)) { - // TODO: the use of GetParameterTypes creates an unused array here. - if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - methods.push_back(m); - } - if (env->ExceptionOccurred()) { - return NULL; - } - } - - return ToArray(soa, "java/lang/reflect/Method", methods); -} - static jobject Class_getDex(JNIEnv* env, jobject javaClass) { ScopedObjectAccess soa(env); Class* c = DecodeClass(soa, javaClass); @@ -237,109 +96,11 @@ static jobject Class_getDex(JNIEnv* env, jobject javaClass) { if (dex_cache == NULL) { return NULL; } - - return Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache).GetDexObject(env); -} - -static bool MethodMatches(MethodHelper* mh, const std::string& name, ObjectArray<Class>* arg_array) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (name != mh->GetName()) { - return false; - } - const DexFile::TypeList* m_type_list = mh->GetParameterTypeList(); - uint32_t m_type_list_size = m_type_list == NULL ? 0 : m_type_list->Size(); - uint32_t sig_length = arg_array->GetLength(); - - if (m_type_list_size != sig_length) { - return false; - } - - for (uint32_t i = 0; i < sig_length; i++) { - if (mh->GetClassFromTypeIdx(m_type_list->GetTypeItem(i).type_idx_) != arg_array->Get(i)) { - return false; - } - } - return true; -} - -static AbstractMethod* FindConstructorOrMethodInArray(ObjectArray<AbstractMethod>* methods, - const std::string& name, - ObjectArray<Class>* arg_array) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - if (methods == NULL) { + const DexFile* dex_file = dex_cache->GetDexFile(); + if (dex_file == NULL) { return NULL; } - AbstractMethod* result = NULL; - MethodHelper mh; - for (int32_t i = 0; i < methods->GetLength(); ++i) { - AbstractMethod* method = methods->Get(i); - mh.ChangeMethod(method); - if (method->IsMiranda() || !MethodMatches(&mh, name, arg_array)) { - continue; - } - - result = method; - - // Covariant return types permit the class to define multiple - // methods with the same name and parameter types. Prefer to return - // a non-synthetic method in such situations. We may still return - // a synthetic method to handle situations like escalated visibility. - if (!method->IsSynthetic()) { - break; - } - } - return result; -} - -static jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName, - jobjectArray javaArgs) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaClass); - std::string name(soa.Decode<String*>(javaName)->ToModifiedUtf8()); - ObjectArray<Class>* arg_array = soa.Decode<ObjectArray<Class>*>(javaArgs); - - AbstractMethod* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array); - if (m == NULL) { - m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, arg_array); - } - - if (m != NULL) { - return soa.AddLocalReference<jobject>(m); - } else { - return NULL; - } -} - -static jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass java_class, jobject jname) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, java_class); - String* name = soa.Decode<String*>(jname); - DCHECK(name->GetClass()->IsStringClass()); - - FieldHelper fh; - for (size_t i = 0; i < c->NumInstanceFields(); ++i) { - Field* f = c->GetInstanceField(i); - fh.ChangeField(f); - if (name->Equals(fh.GetName())) { - if (fh.GetType() == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - return soa.AddLocalReference<jclass>(f); - } - } - for (size_t i = 0; i < c->NumStaticFields(); ++i) { - Field* f = c->GetStaticField(i); - fh.ChangeField(f); - if (name->Equals(fh.GetName())) { - if (fh.GetType() == NULL) { - DCHECK(env->ExceptionOccurred()); - return NULL; - } - return soa.AddLocalReference<jclass>(f); - } - } - return NULL; + return dex_file->GetDexObject(env); } static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { @@ -354,91 +115,12 @@ static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self())); } -static jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) { - ScopedObjectAccess soa(env); - Class* lhs = DecodeClass(soa, javaLhs); - Class* rhs = soa.Decode<Class*>(javaRhs); // Can be null. - if (rhs == NULL) { - soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null"); - return JNI_FALSE; - } - return lhs->IsAssignableFrom(rhs) ? JNI_TRUE : JNI_FALSE; -} - -static jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) { - ScopedObjectAccess soa(env); - Class* c = DecodeClass(soa, javaThis); - if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) { - soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", - "Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str()); - return NULL; - } - - if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) { - return NULL; - } - - AbstractMethod* init = c->FindDeclaredDirectMethod("<init>", "()V"); - if (init == NULL) { - soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;", - "Class %s has no default <init>()V constructor", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str()); - return NULL; - } - - // Verify access from the call site. - // - // First, make sure the method invoking Class.newInstance() has permission - // to access the class. - // - // Second, make sure it has permission to invoke the constructor. The - // constructor must be public or, if the caller is in the same package, - // have package scope. - - NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetTraceStack(), 2); - visitor.WalkStack(); - Class* caller_class = visitor.caller->GetDeclaringClass(); - - ClassHelper caller_ch(caller_class); - if (!caller_class->CanAccess(c)) { - soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;", - "Class %s is not accessible from class %s", - PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str(), - PrettyDescriptor(caller_ch.GetDescriptor()).c_str()); - return NULL; - } - if (!caller_class->CanAccessMember(init->GetDeclaringClass(), init->GetAccessFlags())) { - soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;", - "%s is not accessible from class %s", - PrettyMethod(init).c_str(), - PrettyDescriptor(caller_ch.GetDescriptor()).c_str()); - return NULL; - } - - Object* new_obj = c->AllocObject(soa.Self()); - if (new_obj == NULL) { - DCHECK(soa.Self()->IsExceptionPending()); - return NULL; - } - - // invoke constructor; unlike reflection calls, we don't wrap exceptions - jclass java_class = soa.AddLocalReference<jclass>(c); - jmethodID mid = soa.EncodeMethod(init); - return env->NewObject(java_class, mid); -} - static JNINativeMethod gMethods[] = { NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), NATIVE_METHOD(Class, getAnnotationDirectoryOffset, "()I"), - NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"), - NATIVE_METHOD(Class, getDeclaredConstructors, "(Z)[Ljava/lang/reflect/Constructor;"), - NATIVE_METHOD(Class, getDeclaredFieldNative, "(Ljava/lang/String;)Ljava/lang/reflect/Field;"), - NATIVE_METHOD(Class, getDeclaredFields, "(Z)[Ljava/lang/reflect/Field;"), - NATIVE_METHOD(Class, getDeclaredMethods, "(Z)[Ljava/lang/reflect/Method;"), NATIVE_METHOD(Class, getDex, "()Lcom/android/dex/Dex;"), NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"), NATIVE_METHOD(Class, getProxyInterfaces, "()[Ljava/lang/Class;"), - NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"), - NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"), }; void register_java_lang_Class(JNIEnv* env) { |