entrypoint_utils.cc revision cbb2d20bea2861f244da2e2318d8c088300a3710
12d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao/* 20f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes * Copyright (C) 2012 The Android Open Source Project 32d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 42d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License"); 52d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * you may not use this file except in compliance with the License. 62d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * You may obtain a copy of the License at 72d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 82d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * http://www.apache.org/licenses/LICENSE-2.0 92d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * 102d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * Unless required by applicable law or agreed to in writing, software 112d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS, 122d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * See the License for the specific language governing permissions and 142d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao * limitations under the License. 152d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao */ 162d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 177655f29fabc0a12765de828914a18314382e5a35Ian Rogers#include "entrypoints/entrypoint_utils.h" 182d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao 192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 204f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 211d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 22ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 23ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 26bd136a29f08486525d6abc7d0a0006ce5b4011c1Dragos Sbirlea#include "object_utils.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/proxy.h" 29af6e67a4816d2593586115b89faa659225363246Ian Rogers#include "reflection.h" 30af6e67a4816d2593586115b89faa659225363246Ian Rogers#include "scoped_thread_state_change.h" 315bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa#include "ScopedLocalRef.h" 32eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "well_known_classes.h" 335bb8601175bbb9cd761c715f4ba04f84d65e913bTDYa 3441005ddb5576b8630a1084fbb3979ffa602c0599jeffhaonamespace art { 3541005ddb5576b8630a1084fbb3979ffa602c0599jeffhao 36cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartierstatic inline mirror::Class* CheckFilledNewArrayAlloc(uint32_t type_idx, mirror::ArtMethod* referrer, 37cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier int32_t component_count, Thread* self, 38cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check) 393b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 4057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(component_count < 0)) { 4162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowNegativeArraySizeException(component_count); 42cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 43ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 443b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->GetWithoutChecks(type_idx); 4557b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve 4662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer); 4757b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass == NULL) { // Error 4850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers DCHECK(self->IsExceptionPending()); 49cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 50ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 51ea2a11d5f20814f17985ae3d4defc8dd843f19b9Ian Rogers } 5257b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { 5357b86d47b66322693a070185fadfb43cb9c12eabIan Rogers if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { 5462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowRuntimeException("Bad filled array request for type %s", 5562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers PrettyDescriptor(klass).c_str()); 56573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } else { 5762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 5862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DCHECK(throw_location.GetMethod() == referrer); 5962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;", 6050b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers "Found type %s; filled-new-array not implemented for anything but \'int\'", 6150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers PrettyDescriptor(klass).c_str()); 62573db4a2077380d81fa74ee2309162530db87a98Ian Rogers } 63cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 643b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 653b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi if (access_check) { 663b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi mirror::Class* referrer_klass = referrer->GetDeclaringClass(); 673b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi if (UNLIKELY(!referrer_klass->CanAccess(klass))) { 683b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi ThrowIllegalAccessErrorClass(referrer_klass, klass); 69cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; // Failure 7057b86d47b66322693a070185fadfb43cb9c12eabIan Rogers } 71ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers } 723b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi DCHECK(klass->IsArrayClass()) << PrettyClass(klass); 73cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return klass; 743b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi} 753b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi 763b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi// Helper function to allocate array for FILLED_NEW_ARRAY. 773b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchimirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* referrer, 783b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi int32_t component_count, Thread* self, 79cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check, 80cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier gc::AllocatorType allocator_type) { 81cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, referrer, component_count, self, 82cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier access_check); 83cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier if (UNLIKELY(klass == nullptr)) { 84cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; 853b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 86cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return mirror::Array::Alloc<false>(self, klass, component_count, allocator_type); 873b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi} 883b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi 893b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi// Helper function to allocate array for FILLED_NEW_ARRAY. 903b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchimirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx, mirror::ArtMethod* referrer, 913b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi int32_t component_count, Thread* self, 92cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier bool access_check, 93cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier gc::AllocatorType allocator_type) { 94cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier mirror::Class* klass = CheckFilledNewArrayAlloc(type_idx, referrer, component_count, self, 95cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier access_check); 96cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier if (UNLIKELY(klass == nullptr)) { 97cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return nullptr; 983b4c18933c24b8a33f38573c2ebcdb9aa16efeb5Hiroshi Yamauchi } 99cbb2d20bea2861f244da2e2318d8c088300a3710Mathieu Chartier return mirror::Array::Alloc<true>(self, klass, component_count, allocator_type); 100ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers} 101ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers 102d752132c73072084a3def9257cca4fcee76047b6jeffhaovoid ThrowStackOverflowError(Thread* self) { 1037571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom if (self->IsHandlingStackOverflow()) { 1047571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom LOG(ERROR) << "Recursive stack overflow."; 1057571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom // We don't fail here because SetStackEndForStackOverflow will print better diagnostics. 1067571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom } 10762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 10862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) { 10962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Remove extra entry pushed onto second stack during method tracing. 11062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false); 111d752132c73072084a3def9257cca4fcee76047b6jeffhao } 11262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers 113d752132c73072084a3def9257cca4fcee76047b6jeffhao self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute. 114d752132c73072084a3def9257cca4fcee76047b6jeffhao JNIEnvExt* env = self->GetJniEnv(); 115d752132c73072084a3def9257cca4fcee76047b6jeffhao std::string msg("stack size "); 116d752132c73072084a3def9257cca4fcee76047b6jeffhao msg += PrettySize(self->GetStackSize()); 117d752132c73072084a3def9257cca4fcee76047b6jeffhao // Use low-level JNI routine and pre-baked error class to avoid class linking operations that 118d752132c73072084a3def9257cca4fcee76047b6jeffhao // would consume more stack. 119d752132c73072084a3def9257cca4fcee76047b6jeffhao int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError, 120d752132c73072084a3def9257cca4fcee76047b6jeffhao msg.c_str(), NULL); 121d752132c73072084a3def9257cca4fcee76047b6jeffhao if (rc != JNI_OK) { 122d752132c73072084a3def9257cca4fcee76047b6jeffhao // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME 123d752132c73072084a3def9257cca4fcee76047b6jeffhao // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError 124d752132c73072084a3def9257cca4fcee76047b6jeffhao // instead. 125d752132c73072084a3def9257cca4fcee76047b6jeffhao LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed."; 126d752132c73072084a3def9257cca4fcee76047b6jeffhao CHECK(self->IsExceptionPending()); 127d752132c73072084a3def9257cca4fcee76047b6jeffhao } 128d752132c73072084a3def9257cca4fcee76047b6jeffhao self->ResetDefaultStackEnd(); // Return to default stack size. 129d752132c73072084a3def9257cca4fcee76047b6jeffhao} 130d752132c73072084a3def9257cca4fcee76047b6jeffhao 131af6e67a4816d2593586115b89faa659225363246Ian RogersJValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty, 132af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject rcvr_jobj, jobject interface_method_jobj, 133af6e67a4816d2593586115b89faa659225363246Ian Rogers std::vector<jvalue>& args) { 134af6e67a4816d2593586115b89faa659225363246Ian Rogers DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy)); 135af6e67a4816d2593586115b89faa659225363246Ian Rogers 136af6e67a4816d2593586115b89faa659225363246Ian Rogers // Build argument array possibly triggering GC. 137af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Self()->AssertThreadSuspensionIsAllowable(); 138af6e67a4816d2593586115b89faa659225363246Ian Rogers jobjectArray args_jobj = NULL; 139af6e67a4816d2593586115b89faa659225363246Ian Rogers const JValue zero; 140af6e67a4816d2593586115b89faa659225363246Ian Rogers if (args.size() > 0) { 141af6e67a4816d2593586115b89faa659225363246Ian Rogers args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL); 142af6e67a4816d2593586115b89faa659225363246Ian Rogers if (args_jobj == NULL) { 143af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 144af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 145af6e67a4816d2593586115b89faa659225363246Ian Rogers } 146af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < args.size(); ++i) { 147af6e67a4816d2593586115b89faa659225363246Ian Rogers if (shorty[i + 1] == 'L') { 148af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject val = args.at(i).l; 149af6e67a4816d2593586115b89faa659225363246Ian Rogers soa.Env()->SetObjectArrayElement(args_jobj, i, val); 150af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 151af6e67a4816d2593586115b89faa659225363246Ian Rogers JValue jv; 152af6e67a4816d2593586115b89faa659225363246Ian Rogers jv.SetJ(args.at(i).j); 1532dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv); 154af6e67a4816d2593586115b89faa659225363246Ian Rogers if (val == NULL) { 155af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK(soa.Self()->IsExceptionPending()); 156af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 157af6e67a4816d2593586115b89faa659225363246Ian Rogers } 1582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set(i, val); 159af6e67a4816d2593586115b89faa659225363246Ian Rogers } 160af6e67a4816d2593586115b89faa659225363246Ian Rogers } 161af6e67a4816d2593586115b89faa659225363246Ian Rogers } 162af6e67a4816d2593586115b89faa659225363246Ian Rogers 163ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args). 164af6e67a4816d2593586115b89faa659225363246Ian Rogers jvalue invocation_args[3]; 165af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[0].l = rcvr_jobj; 166af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[1].l = interface_method_jobj; 167af6e67a4816d2593586115b89faa659225363246Ian Rogers invocation_args[2].l = args_jobj; 168af6e67a4816d2593586115b89faa659225363246Ian Rogers jobject result = 169ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy, 170ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom WellKnownClasses::java_lang_reflect_Proxy_invoke, 171ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom invocation_args); 172af6e67a4816d2593586115b89faa659225363246Ian Rogers 173af6e67a4816d2593586115b89faa659225363246Ian Rogers // Unbox result and handle error conditions. 17462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (LIKELY(!soa.Self()->IsExceptionPending())) { 17562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) { 176af6e67a4816d2593586115b89faa659225363246Ian Rogers // Do nothing. 177af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 178af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 1792dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* result_ref = soa.Decode<mirror::Object*>(result); 18062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 181ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* interface_method = 182ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Decode<mirror::ArtMethod*>(interface_method_jobj); 18362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Class* result_type = MethodHelper(interface_method).GetReturnType(); 184ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method; 18562d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (interface_method->GetDeclaringClass()->IsInterface()) { 18662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); 18762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } else { 18862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers // Proxy dispatch to a method defined in Object. 18962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers DCHECK(interface_method->GetDeclaringClass()->IsObjectClass()); 19062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers proxy_method = interface_method; 19162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers } 19262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 19362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers JValue result_unboxed; 19462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, result_unboxed)) { 195530f71c040cb1a7b946d5566d5a746f08f2d082cIan Rogers DCHECK(soa.Self()->IsExceptionPending()); 19662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers return zero; 197af6e67a4816d2593586115b89faa659225363246Ian Rogers } 198af6e67a4816d2593586115b89faa659225363246Ian Rogers return result_unboxed; 199af6e67a4816d2593586115b89faa659225363246Ian Rogers } 200af6e67a4816d2593586115b89faa659225363246Ian Rogers } else { 201af6e67a4816d2593586115b89faa659225363246Ian Rogers // In the case of checked exceptions that aren't declared, the exception must be wrapped by 202af6e67a4816d2593586115b89faa659225363246Ian Rogers // a UndeclaredThrowableException. 20362d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = soa.Self()->GetException(NULL); 204af6e67a4816d2593586115b89faa659225363246Ian Rogers if (exception->IsCheckedException()) { 2052dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj); 2062dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::SynthesizedProxyClass* proxy_class = 2072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass()); 208ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* interface_method = 209ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom soa.Decode<mirror::ArtMethod*>(interface_method_jobj); 210ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* proxy_method = 211af6e67a4816d2593586115b89faa659225363246Ian Rogers rcvr->GetClass()->FindVirtualMethodForInterface(interface_method); 212af6e67a4816d2593586115b89faa659225363246Ian Rogers int throws_index = -1; 213af6e67a4816d2593586115b89faa659225363246Ian Rogers size_t num_virt_methods = proxy_class->NumVirtualMethods(); 214af6e67a4816d2593586115b89faa659225363246Ian Rogers for (size_t i = 0; i < num_virt_methods; i++) { 215af6e67a4816d2593586115b89faa659225363246Ian Rogers if (proxy_class->GetVirtualMethod(i) == proxy_method) { 216af6e67a4816d2593586115b89faa659225363246Ian Rogers throws_index = i; 217af6e67a4816d2593586115b89faa659225363246Ian Rogers break; 218af6e67a4816d2593586115b89faa659225363246Ian Rogers } 219af6e67a4816d2593586115b89faa659225363246Ian Rogers } 220af6e67a4816d2593586115b89faa659225363246Ian Rogers CHECK_NE(throws_index, -1); 2212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); 2222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* exception_class = exception->GetClass(); 223af6e67a4816d2593586115b89faa659225363246Ian Rogers bool declares_exception = false; 224af6e67a4816d2593586115b89faa659225363246Ian Rogers for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) { 2252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* declared_exception = declared_exceptions->Get(i); 226af6e67a4816d2593586115b89faa659225363246Ian Rogers declares_exception = declared_exception->IsAssignableFrom(exception_class); 227af6e67a4816d2593586115b89faa659225363246Ian Rogers } 228af6e67a4816d2593586115b89faa659225363246Ian Rogers if (!declares_exception) { 22962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location(rcvr, proxy_method, -1); 23062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers soa.Self()->ThrowNewWrappedException(throw_location, 23162d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers "Ljava/lang/reflect/UndeclaredThrowableException;", 232af6e67a4816d2593586115b89faa659225363246Ian Rogers NULL); 233af6e67a4816d2593586115b89faa659225363246Ian Rogers } 234af6e67a4816d2593586115b89faa659225363246Ian Rogers } 235af6e67a4816d2593586115b89faa659225363246Ian Rogers return zero; 236af6e67a4816d2593586115b89faa659225363246Ian Rogers } 237af6e67a4816d2593586115b89faa659225363246Ian Rogers} 2382d831014d88e38c0c499ce8597dcdb17b9d4c4b9Shih-wei Liao} // namespace art 239