blob: 8c2b30c14fa537bc723c0172a282c73270fe7640 [file] [log] [blame]
Shih-wei Liao2d831012011-09-28 22:06:53 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Shih-wei Liao2d831012011-09-28 22:06:53 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "runtime_support.h"
18
TDYa1275bb86012012-04-11 05:57:28 -070019#include "ScopedLocalRef.h"
20
Shih-wei Liao2d831012011-09-28 22:06:53 -070021namespace art {
22
Ian Rogers57b86d42012-03-27 16:05:41 -070023void ThrowNewIllegalAccessErrorClass(Thread* self,
24 Class* referrer,
25 Class* accessed) {
26 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
27 "illegal class access: '%s' -> '%s'",
28 PrettyDescriptor(referrer).c_str(),
29 PrettyDescriptor(accessed).c_str());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -080030}
31
Ian Rogers57b86d42012-03-27 16:05:41 -070032void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
33 Class* referrer,
34 Class* accessed,
35 const Method* caller,
36 const Method* called,
37 InvokeType type) {
38 std::ostringstream type_stream;
39 type_stream << type;
40 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
41 "illegal class access ('%s' -> '%s')"
42 "in attempt to invoke %s method '%s' from '%s'",
43 PrettyDescriptor(referrer).c_str(),
44 PrettyDescriptor(accessed).c_str(),
45 type_stream.str().c_str(),
46 PrettyMethod(called).c_str(),
47 PrettyMethod(caller).c_str());
buzbee44b412b2012-02-04 08:50:53 -080048}
49
Ian Rogers57b86d42012-03-27 16:05:41 -070050void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
51 const Method* referrer,
52 const Method* interface_method,
53 Object* this_object) {
54 self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
55 "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
56 PrettyDescriptor(this_object->GetClass()).c_str(),
57 PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
58 PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -070059}
60
Ian Rogers57b86d42012-03-27 16:05:41 -070061void ThrowNewIllegalAccessErrorField(Thread* self,
62 Class* referrer,
63 Field* accessed) {
64 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
65 "Field '%s' is inaccessible to class '%s'",
66 PrettyField(accessed, false).c_str(),
67 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -070068}
69
Ian Rogers57b86d42012-03-27 16:05:41 -070070void ThrowNewIllegalAccessErrorFinalField(Thread* self,
71 const Method* referrer,
72 Field* accessed) {
73 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
74 "Final field '%s' cannot be written to by method '%s'",
75 PrettyField(accessed, false).c_str(),
76 PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -070077}
78
Ian Rogers57b86d42012-03-27 16:05:41 -070079void ThrowNewIllegalAccessErrorMethod(Thread* self,
80 Class* referrer,
81 Method* accessed) {
82 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
83 "Method '%s' is inaccessible to class '%s'",
84 PrettyMethod(accessed).c_str(),
85 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -070086}
87
Ian Rogers57b86d42012-03-27 16:05:41 -070088void ThrowNullPointerExceptionForFieldAccess(Thread* self,
89 Field* field,
90 bool is_read) {
91 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
92 "Attempt to %s field '%s' on a null object reference",
93 is_read ? "read from" : "write to",
94 PrettyField(field, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -070095}
96
Ian Rogers57b86d42012-03-27 16:05:41 -070097void ThrowNullPointerExceptionForMethodAccess(Thread* self,
98 Method* caller,
99 uint32_t method_idx,
100 InvokeType type) {
101 const DexFile& dex_file =
102 Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
103 std::ostringstream type_stream;
104 type_stream << type;
105 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
106 "Attempt to invoke %s method '%s' on a null object reference",
107 type_stream.str().c_str(),
108 PrettyMethod(method_idx, dex_file, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700109}
110
TDYa1273f9137d2012-04-08 15:59:19 -0700111void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* throw_method, uint32_t dex_pc) {
112 const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
113 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
114 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
115 DecodedInstruction dec_insn(instr);
116 switch (instr->Opcode()) {
117 case Instruction::INVOKE_DIRECT:
118 case Instruction::INVOKE_DIRECT_RANGE:
119 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
120 break;
121 case Instruction::INVOKE_VIRTUAL:
122 case Instruction::INVOKE_VIRTUAL_RANGE:
123 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
124 break;
125 case Instruction::IGET:
126 case Instruction::IGET_WIDE:
127 case Instruction::IGET_OBJECT:
128 case Instruction::IGET_BOOLEAN:
129 case Instruction::IGET_BYTE:
130 case Instruction::IGET_CHAR:
131 case Instruction::IGET_SHORT: {
132 Field* field =
133 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
134 ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
135 break;
136 }
137 case Instruction::IPUT:
138 case Instruction::IPUT_WIDE:
139 case Instruction::IPUT_OBJECT:
140 case Instruction::IPUT_BOOLEAN:
141 case Instruction::IPUT_BYTE:
142 case Instruction::IPUT_CHAR:
143 case Instruction::IPUT_SHORT: {
144 Field* field =
145 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
146 ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
147 break;
148 }
149 case Instruction::AGET:
150 case Instruction::AGET_WIDE:
151 case Instruction::AGET_OBJECT:
152 case Instruction::AGET_BOOLEAN:
153 case Instruction::AGET_BYTE:
154 case Instruction::AGET_CHAR:
155 case Instruction::AGET_SHORT:
156 self->ThrowNewException("Ljava/lang/NullPointerException;",
157 "Attempt to read from null array");
158 break;
159 case Instruction::APUT:
160 case Instruction::APUT_WIDE:
161 case Instruction::APUT_OBJECT:
162 case Instruction::APUT_BOOLEAN:
163 case Instruction::APUT_BYTE:
164 case Instruction::APUT_CHAR:
165 case Instruction::APUT_SHORT:
166 self->ThrowNewException("Ljava/lang/NullPointerException;",
167 "Attempt to write to null array");
168 break;
169 default: {
170 const DexFile& dex_file = Runtime::Current()->GetClassLinker()
171 ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
172 std::string message("Null pointer exception during instruction '");
173 message += instr->DumpString(&dex_file);
174 message += "'";
175 self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
176 break;
177 }
178 }
179}
180
Ian Rogers57b86d42012-03-27 16:05:41 -0700181std::string FieldNameFromIndex(const Method* method, uint32_t ref,
182 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700183 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700184
185 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
186 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
187
188 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700189 std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700190 const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700191 if (!access) {
192 return class_name + "." + field_name;
193 }
194
195 std::string result;
196 result += "tried to access field ";
197 result += class_name + "." + field_name;
198 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800199 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700200 return result;
201}
202
Ian Rogers57b86d42012-03-27 16:05:41 -0700203std::string MethodNameFromIndex(const Method* method, uint32_t ref,
204 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700205 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700206
207 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
208 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
209
210 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700211 std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700212 const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700213 if (!access) {
214 return class_name + "." + method_name;
215 }
216
217 std::string result;
218 result += "tried to access method ";
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700219 result += class_name + "." + method_name + ":" +
Ian Rogers0571d352011-11-03 19:51:38 -0700220 dex_file.CreateMethodSignature(id.proto_idx_, NULL);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700221 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800222 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700223 return result;
224}
225
TDYa127b92bcab2012-04-08 00:09:51 -0700226static std::string ClassNameFromIndex(const Method* method, uint32_t ref,
227 verifier::VerifyErrorRefType ref_type, bool access) {
Logan Chien9e5f5c12012-04-10 13:51:45 +0800228 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
229 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
230
231 uint16_t type_idx = 0;
232 if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
233 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
234 type_idx = id.class_idx_;
235 } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
236 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
237 type_idx = id.class_idx_;
238 } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
239 type_idx = ref;
240 } else {
241 CHECK(false) << static_cast<int>(ref_type);
242 }
243
244 std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
245 if (!access) {
246 return class_name;
247 }
248
249 std::string result;
250 result += "tried to access class ";
251 result += class_name;
252 result += " from class ";
253 result += PrettyDescriptor(method->GetDeclaringClass());
254 return result;
255}
256
257void ThrowVerificationError(Thread* self, const Method* method,
258 int32_t kind, int32_t ref) {
259 verifier::VerifyErrorRefType ref_type =
260 static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
261
262 const char* exception_class = "Ljava/lang/VerifyError;";
263 std::string msg;
264
265 switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
266 case verifier::VERIFY_ERROR_NO_CLASS:
267 exception_class = "Ljava/lang/NoClassDefFoundError;";
268 msg = ClassNameFromIndex(method, ref, ref_type, false);
269 break;
270 case verifier::VERIFY_ERROR_NO_FIELD:
271 exception_class = "Ljava/lang/NoSuchFieldError;";
272 msg = FieldNameFromIndex(method, ref, ref_type, false);
273 break;
274 case verifier::VERIFY_ERROR_NO_METHOD:
275 exception_class = "Ljava/lang/NoSuchMethodError;";
276 msg = MethodNameFromIndex(method, ref, ref_type, false);
277 break;
278 case verifier::VERIFY_ERROR_ACCESS_CLASS:
279 exception_class = "Ljava/lang/IllegalAccessError;";
280 msg = ClassNameFromIndex(method, ref, ref_type, true);
281 break;
282 case verifier::VERIFY_ERROR_ACCESS_FIELD:
283 exception_class = "Ljava/lang/IllegalAccessError;";
284 msg = FieldNameFromIndex(method, ref, ref_type, true);
285 break;
286 case verifier::VERIFY_ERROR_ACCESS_METHOD:
287 exception_class = "Ljava/lang/IllegalAccessError;";
288 msg = MethodNameFromIndex(method, ref, ref_type, true);
289 break;
290 case verifier::VERIFY_ERROR_CLASS_CHANGE:
291 exception_class = "Ljava/lang/IncompatibleClassChangeError;";
292 msg = ClassNameFromIndex(method, ref, ref_type, false);
293 break;
294 case verifier::VERIFY_ERROR_INSTANTIATION:
295 exception_class = "Ljava/lang/InstantiationError;";
296 msg = ClassNameFromIndex(method, ref, ref_type, false);
297 break;
298 case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
299 case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
300 // Generic VerifyError; use default exception, no message.
301 break;
302 case verifier::VERIFY_ERROR_NONE:
303 CHECK(false);
304 break;
305 }
306
307 self->ThrowNewException(exception_class, msg.c_str());
308}
309
Ian Rogers57b86d42012-03-27 16:05:41 -0700310// Helper function to allocate array for FILLED_NEW_ARRAY.
311Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
312 Thread* self, bool access_check) {
313 if (UNLIKELY(component_count < 0)) {
314 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
315 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700316 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700317 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
318 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
319 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
320 if (klass == NULL) { // Error
321 DCHECK(Thread::Current()->IsExceptionPending());
322 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800323 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700324 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700325 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
326 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
327 Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
328 "Bad filled array request for type %s",
329 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800330 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700331 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
332 "Found type %s; filled-new-array not implemented for anything but \'int\'",
333 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800334 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700335 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700336 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700337 if (access_check) {
338 Class* referrer = method->GetDeclaringClass();
339 if (UNLIKELY(!referrer->CanAccess(klass))) {
340 ThrowNewIllegalAccessErrorClass(self, referrer, klass);
341 return NULL; // Failure
342 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800343 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700344 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
345 return Array::Alloc(klass, component_count);
346 }
347}
348
349// Slow path field resolution and declaring class initialization
350Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
351 bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
352 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
353 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
354 if (UNLIKELY(resolved_field == NULL)) {
355 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
356 return NULL; // failure
357 } else {
358 Class* fields_class = resolved_field->GetDeclaringClass();
359 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700360 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
361 !referring_class->CanAccessMember(fields_class,
362 resolved_field->GetAccessFlags()))) {
363 // The referring class can't access the resolved field, this may occur as a result of a
364 // protected field being made public by a sub-class. Resort to the dex file to determine
365 // the correct class for the access check.
366 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
367 fields_class = class_linker->ResolveType(dex_file,
368 dex_file.GetFieldId(field_idx).class_idx_,
369 referring_class);
370 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
371 ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
372 return NULL; // failure
373 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
374 resolved_field->GetAccessFlags()))) {
375 ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
376 return NULL; // failure
377 }
378 }
379 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700380 ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
381 return NULL; // failure
382 } else {
383 FieldHelper fh(resolved_field);
384 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
385 fh.FieldSize() != expected_size)) {
386 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
387 "Attempted read of %zd-bit %s on field '%s'",
388 expected_size * (32 / sizeof(int32_t)),
389 is_primitive ? "primitive" : "non-primitive",
390 PrettyField(resolved_field, true).c_str());
391 return NULL; // failure
392 } else if (!is_static) {
393 // instance fields must be being accessed on an initialized class
394 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800395 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700396 // If the class is already initializing, we must be inside <clinit>, or
397 // we'd still be waiting for the lock.
398 if (fields_class->IsInitializing()) {
399 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700400 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700401 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800402 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700403 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
404 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800405 }
406 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700407 }
408 }
409}
410
411// Slow path method resolution
412Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
413 Thread* self, bool access_check, InvokeType type) {
414 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
415 bool is_direct = type == kStatic || type == kDirect;
416 Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
417 if (UNLIKELY(resolved_method == NULL)) {
418 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
419 return NULL; // failure
420 } else {
421 if (!access_check) {
422 if (is_direct) {
423 return resolved_method;
424 } else if (type == kInterface) {
425 Method* interface_method =
426 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
427 if (UNLIKELY(interface_method == NULL)) {
428 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
429 resolved_method,
430 this_object);
431 return NULL; // failure
432 } else {
433 return interface_method;
434 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800435 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700436 ObjectArray<Method>* vtable;
437 uint16_t vtable_index = resolved_method->GetMethodIndex();
438 if (type == kSuper) {
439 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
440 } else {
441 vtable = this_object->GetClass()->GetVTable();
442 }
443 // TODO: eliminate bounds check?
444 return vtable->Get(vtable_index);
445 }
446 } else {
447 Class* methods_class = resolved_method->GetDeclaringClass();
448 Class* referring_class = referrer->GetDeclaringClass();
449 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
450 !referring_class->CanAccessMember(methods_class,
451 resolved_method->GetAccessFlags()))) {
452 // The referring class can't access the resolved method, this may occur as a result of a
453 // protected method being made public by implementing an interface that re-declares the
454 // method public. Resort to the dex file to determine the correct class for the access check
455 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
456 methods_class = class_linker->ResolveType(dex_file,
457 dex_file.GetMethodId(method_idx).class_idx_,
458 referring_class);
459 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
460 ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
461 referrer, resolved_method, type);
462 return NULL; // failure
463 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
464 resolved_method->GetAccessFlags()))) {
465 ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
466 return NULL; // failure
467 }
468 }
469 if (is_direct) {
470 return resolved_method;
471 } else if (type == kInterface) {
472 Method* interface_method =
473 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
474 if (UNLIKELY(interface_method == NULL)) {
475 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
476 resolved_method,
477 this_object);
478 return NULL; // failure
479 } else {
480 return interface_method;
481 }
482 } else {
483 ObjectArray<Method>* vtable;
484 uint16_t vtable_index = resolved_method->GetMethodIndex();
485 if (type == kSuper) {
486 Class* super_class = referring_class->GetSuperClass();
487 if (LIKELY(super_class != NULL)) {
488 vtable = referring_class->GetSuperClass()->GetVTable();
489 } else {
490 vtable = NULL;
491 }
492 } else {
493 vtable = this_object->GetClass()->GetVTable();
494 }
495 if (LIKELY(vtable != NULL &&
496 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
497 return vtable->GetWithoutChecks(vtable_index);
498 } else {
499 // Behavior to agree with that of the verifier
500 self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
501 "attempt to invoke %s method '%s' from '%s'"
502 " using incorrect form of method dispatch",
503 (type == kSuper ? "super class" : "virtual"),
504 PrettyMethod(resolved_method).c_str(),
505 PrettyMethod(referrer).c_str());
506 return NULL; // failure
507 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800508 }
509 }
510 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800511}
512
Ian Rogers57b86d42012-03-27 16:05:41 -0700513Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
514 bool can_run_clinit, bool verify_access) {
515 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
516 Class* klass = class_linker->ResolveType(type_idx, referrer);
517 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700518 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700519 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700520 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700521 // Perform access check if necessary.
522 Class* referring_class = referrer->GetDeclaringClass();
523 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
524 ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
525 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700526 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700527 // If we're just implementing const-class, we shouldn't call <clinit>.
528 if (!can_run_clinit) {
529 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700530 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700531 // If we are the <clinit> of this class, just return our storage.
532 //
533 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
534 // running.
535 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
536 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700537 }
Ian Rogers0045a292012-03-31 21:08:41 -0700538 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700539 CHECK(self->IsExceptionPending());
540 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700541 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700542 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
543 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700544}
545
TDYa1275bb86012012-04-11 05:57:28 -0700546void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
547 ScopedLocalRef<jclass> jlr_UTE_class(env,
548 env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
549 if (jlr_UTE_class.get() == NULL) {
550 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
551 } else {
552 jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
553 "(Ljava/lang/Throwable;)V");
554 jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
555 ScopedLocalRef<jthrowable> jlr_UTE(env,
556 reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
557 jexception)));
558 int rc = env->Throw(jlr_UTE.get());
559 if (rc != JNI_OK) {
560 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
561 }
562 }
563 CHECK(self->IsExceptionPending());
564}
565
Shih-wei Liao2d831012011-09-28 22:06:53 -0700566} // namespace art