Android-x86
Fork
Donation


Commit MetaInfo

Revision7348a4f236177005123c181da13b3db65ca0bf37 (tree)
Time2017-06-28 07:31:57
AuthorRoland Levillain <rpl@goog...>
Commiterandroid-build-team Robot

Log Message

Only look for method optimization annotations in the bootstrap class loader.

When checking for an optimization annotation (FastNative or
CriticalNative) on a method, do not resolve the method's annotations'
classes as a side effect -- instead, look them up in the bootstrap
class loader's resolved types. This is to prevent exceptions from being
thrown (during class resolution) in JNI transitions.

This change does not affect annotation lookup rules in the context of
reflection.

(cherry-picked from commit 35e42f0ab3b70203038fe037ee50d39e2d37af9a)

Test: art/test/testrunner/testrunner.py -t 656-annotation-lookup-generic-jni
Bug: 38454151
Bug: 34659969
Change-Id: Ie6b8b30b96a08baa629c449e3803a031515508d1
(cherry picked from commit 2ed6cce6fcfd031b0f9d83111f01b6b48ead1a32)

Change Summary

Incremental Difference

--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -403,15 +403,19 @@ bool ArtMethod::IsOverridableByDefaultMethod() {
403403
404404 bool ArtMethod::IsAnnotatedWithFastNative() {
405405 return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_FastNative,
406- DexFile::kDexVisibilityBuild);
406+ DexFile::kDexVisibilityBuild,
407+ /* lookup_in_resolved_boot_classes */ true);
407408 }
408409
409410 bool ArtMethod::IsAnnotatedWithCriticalNative() {
410411 return IsAnnotatedWith(WellKnownClasses::dalvik_annotation_optimization_CriticalNative,
411- DexFile::kDexVisibilityBuild);
412+ DexFile::kDexVisibilityBuild,
413+ /* lookup_in_resolved_boot_classes */ true);
412414 }
413415
414-bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {
416+bool ArtMethod::IsAnnotatedWith(jclass klass,
417+ uint32_t visibility,
418+ bool lookup_in_resolved_boot_classes) {
415419 Thread* self = Thread::Current();
416420 ScopedObjectAccess soa(self);
417421 StackHandleScope<1> shs(self);
@@ -420,10 +424,8 @@ bool ArtMethod::IsAnnotatedWith(jclass klass, uint32_t visibility) {
420424 DCHECK(annotation->IsAnnotation());
421425 Handle<mirror::Class> annotation_handle(shs.NewHandle(annotation));
422426
423- // Note: Resolves any method annotations' classes as a side-effect.
424- // -- This seems allowed by the spec since it says we can preload any classes
425- // referenced by another classes's constant pool table.
426- return annotations::IsMethodAnnotationPresent(this, annotation_handle, visibility);
427+ return annotations::IsMethodAnnotationPresent(
428+ this, annotation_handle, visibility, lookup_in_resolved_boot_classes);
427429 }
428430
429431 static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -716,7 +716,10 @@ class ArtMethod FINAL {
716716 private:
717717 uint16_t FindObsoleteDexClassDefIndex() REQUIRES_SHARED(Locks::mutator_lock_);
718718
719- bool IsAnnotatedWith(jclass klass, uint32_t visibility);
719+ // If `lookup_in_resolved_boot_classes` is true, look up any of the
720+ // method's annotations' classes in the bootstrap class loader's
721+ // resolved types; otherwise, resolve them as a side effect.
722+ bool IsAnnotatedWith(jclass klass, uint32_t visibility, bool lookup_in_resolved_boot_classes);
720723
721724 static constexpr size_t PtrSizedFieldsOffset(PointerSize pointer_size) {
722725 // Round up to pointer size for padding field. Tested in art_method.cc.
--- a/runtime/dex_file_annotations.cc
+++ b/runtime/dex_file_annotations.cc
@@ -751,7 +751,8 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet(
751751 const ClassData& klass,
752752 const DexFile::AnnotationSetItem* annotation_set,
753753 uint32_t visibility,
754- Handle<mirror::Class> annotation_class)
754+ Handle<mirror::Class> annotation_class,
755+ bool lookup_in_resolved_boot_classes = false)
755756 REQUIRES_SHARED(Locks::mutator_lock_) {
756757 const DexFile& dex_file = klass.GetDexFile();
757758 for (uint32_t i = 0; i < annotation_set->size_; ++i) {
@@ -761,19 +762,37 @@ const DexFile::AnnotationItem* GetAnnotationItemFromAnnotationSet(
761762 }
762763 const uint8_t* annotation = annotation_item->annotation_;
763764 uint32_t type_index = DecodeUnsignedLeb128(&annotation);
764- StackHandleScope<2> hs(Thread::Current());
765- mirror::Class* resolved_class = Runtime::Current()->GetClassLinker()->ResolveType(
766- klass.GetDexFile(),
767- dex::TypeIndex(type_index),
768- hs.NewHandle(klass.GetDexCache()),
769- hs.NewHandle(klass.GetClassLoader()));
770- if (resolved_class == nullptr) {
771- std::string temp;
772- LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
773- klass.GetRealClass()->GetDescriptor(&temp), type_index);
774- CHECK(Thread::Current()->IsExceptionPending());
775- Thread::Current()->ClearException();
776- continue;
765+ mirror::Class* resolved_class;
766+ if (lookup_in_resolved_boot_classes) {
767+ ObjPtr<mirror::Class> looked_up_class =
768+ Runtime::Current()->GetClassLinker()->LookupResolvedType(
769+ klass.GetDexFile(),
770+ dex::TypeIndex(type_index),
771+ klass.GetDexCache(),
772+ // Force the use of the bootstrap class loader.
773+ static_cast<mirror::ClassLoader*>(nullptr));
774+ resolved_class = looked_up_class.Ptr();
775+ if (resolved_class == nullptr) {
776+ // If `resolved_class` is null, this is fine: just ignore that
777+ // annotation item. We expect this to happen, as we do not
778+ // attempt to resolve the annotation's class in this code path.
779+ continue;
780+ }
781+ } else {
782+ StackHandleScope<2> hs(Thread::Current());
783+ resolved_class = Runtime::Current()->GetClassLinker()->ResolveType(
784+ klass.GetDexFile(),
785+ dex::TypeIndex(type_index),
786+ hs.NewHandle(klass.GetDexCache()),
787+ hs.NewHandle(klass.GetClassLoader()));
788+ if (resolved_class == nullptr) {
789+ std::string temp;
790+ LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
791+ klass.GetRealClass()->GetDescriptor(&temp), type_index);
792+ CHECK(Thread::Current()->IsExceptionPending());
793+ Thread::Current()->ClearException();
794+ continue;
795+ }
777796 }
778797 if (resolved_class == annotation_class.Get()) {
779798 return annotation_item;
@@ -1200,15 +1219,20 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod*
12001219 return GetSignatureValue(ClassData(method), annotation_set);
12011220 }
12021221
1203-bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class,
1204- uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) {
1222+bool IsMethodAnnotationPresent(ArtMethod* method,
1223+ Handle<mirror::Class> annotation_class,
1224+ uint32_t visibility /* = DexFile::kDexVisibilityRuntime */,
1225+ bool lookup_in_resolved_boot_classes /* = false */) {
12051226 const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
12061227 if (annotation_set == nullptr) {
12071228 return false;
12081229 }
12091230 const DexFile::AnnotationItem* annotation_item =
12101231 GetAnnotationItemFromAnnotationSet(ClassData(method),
1211- annotation_set, visibility, annotation_class);
1232+ annotation_set,
1233+ visibility,
1234+ annotation_class,
1235+ lookup_in_resolved_boot_classes);
12121236 return annotation_item != nullptr;
12131237 }
12141238
--- a/runtime/dex_file_annotations.h
+++ b/runtime/dex_file_annotations.h
@@ -65,8 +65,15 @@ bool GetParametersMetadataForMethod(ArtMethod* method,
6565 REQUIRES_SHARED(Locks::mutator_lock_);
6666 mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method)
6767 REQUIRES_SHARED(Locks::mutator_lock_);
68-bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class,
69- uint32_t visibility = DexFile::kDexVisibilityRuntime)
68+// Check whether `method` is annotated with `annotation_class`.
69+// If `lookup_in_resolved_boot_classes` is true, look up any of the
70+// method's annotations' classes in the bootstrap class loader's
71+// resolved types; if it is false (default value), resolve them as a
72+// side effect.
73+bool IsMethodAnnotationPresent(ArtMethod* method,
74+ Handle<mirror::Class> annotation_class,
75+ uint32_t visibility = DexFile::kDexVisibilityRuntime,
76+ bool lookup_in_resolved_boot_classes = false)
7077 REQUIRES_SHARED(Locks::mutator_lock_);
7178
7279 // Class annotations.
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2086,6 +2086,11 @@ extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod**
20862086 self->SetTopOfStack(sp);
20872087 uint32_t shorty_len = 0;
20882088 const char* shorty = called->GetShorty(&shorty_len);
2089+ // Optimization annotations lookup does not try to resolve classes,
2090+ // as this may throw an exception, which is not supported by the
2091+ // Generic JNI trampoline at this stage; instead, method's
2092+ // annotations' classes are looked up in the bootstrap class
2093+ // loader's resolved types (which won't trigger an exception).
20892094 bool critical_native = called->IsAnnotatedWithCriticalNative();
20902095 // ArtMethod::IsAnnotatedWithCriticalNative should not throw
20912096 // an exception; clear it if it happened anyway.
Show on old repository browser