blob: a3e3cfad7eb8d6b1a023dec09138760faa6675df [file] [log] [blame]
Ian Rogers87e552d2012-08-31 15:54:48 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
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 "common_throws.h"
18
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070021#include "dex_file-inl.h"
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020022#include "dex_instruction-inl.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070023#include "invoke_type.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070024#include "mirror/art_method-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070025#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "mirror/object-inl.h"
27#include "mirror/object_array-inl.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070028#include "object_utils.h"
29#include "thread.h"
Sebastien Hertz2d6ba512013-05-17 11:31:37 +020030#include "verifier/method_verifier.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070031
32#include <sstream>
33
34namespace art {
35
Ian Rogersef7d42f2014-01-06 12:55:46 -080036static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -070037 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers87e552d2012-08-31 15:54:48 -070038 if (referrer != NULL) {
Mathieu Chartierf8322842014-05-16 10:59:25 -070039 std::string location(referrer->GetLocation());
Ian Rogers87e552d2012-08-31 15:54:48 -070040 if (!location.empty()) {
41 os << " (declaration of '" << PrettyDescriptor(referrer)
42 << "' appears in " << location << ")";
43 }
44 }
45}
46
Ian Rogers62d6c772013-02-27 08:32:07 -080047static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
Ian Rogersef7d42f2014-01-06 12:55:46 -080048 mirror::Class* referrer, const char* fmt, va_list* args = NULL)
Ian Rogers62d6c772013-02-27 08:32:07 -080049 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers87e552d2012-08-31 15:54:48 -070050 std::ostringstream msg;
Ian Rogers62d6c772013-02-27 08:32:07 -080051 if (args != NULL) {
52 std::string vmsg;
53 StringAppendV(&vmsg, fmt, *args);
54 msg << vmsg;
55 } else {
56 msg << fmt;
57 }
58 AddReferrerLocation(msg, referrer);
59 Thread* self = Thread::Current();
60 if (throw_location == NULL) {
61 ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
62 self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str());
63 } else {
64 self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -070065 }
66}
67
Andreas Gampe329d1882014-04-08 10:32:19 -070068static void ThrowWrappedException(const ThrowLocation* throw_location,
69 const char* exception_descriptor,
70 mirror::Class* referrer, const char* fmt, va_list* args = NULL)
71 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
72 std::ostringstream msg;
73 if (args != NULL) {
74 std::string vmsg;
75 StringAppendV(&vmsg, fmt, *args);
76 msg << vmsg;
77 } else {
78 msg << fmt;
79 }
80 AddReferrerLocation(msg, referrer);
81 Thread* self = Thread::Current();
82 if (throw_location == NULL) {
83 ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
84 self->ThrowNewWrappedException(computed_throw_location, exception_descriptor, msg.str().c_str());
85 } else {
86 self->ThrowNewWrappedException(*throw_location, exception_descriptor, msg.str().c_str());
87 }
88}
89
Sebastien Hertz56adf602013-07-09 17:27:07 +020090// AbstractMethodError
91
Ian Rogersef7d42f2014-01-06 12:55:46 -080092void ThrowAbstractMethodError(mirror::ArtMethod* method) {
Sebastien Hertz56adf602013-07-09 17:27:07 +020093 ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
94 StringPrintf("abstract method \"%s\"",
95 PrettyMethod(method).c_str()).c_str());
96}
97
Ian Rogers62d6c772013-02-27 08:32:07 -080098// ArithmeticException
99
Sebastien Hertz0a3b8632013-06-26 11:16:01 +0200100void ThrowArithmeticExceptionDivideByZero() {
Ian Rogers62d6c772013-02-27 08:32:07 -0800101 ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero");
102}
103
104// ArrayIndexOutOfBoundsException
105
106void ThrowArrayIndexOutOfBoundsException(int index, int length) {
107 ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL,
108 StringPrintf("length=%d; index=%d", length, index).c_str());
109}
110
111// ArrayStoreException
112
Ian Rogersef7d42f2014-01-06 12:55:46 -0800113void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800114 ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
115 StringPrintf("%s cannot be stored in an array of type %s",
116 PrettyDescriptor(element_class).c_str(),
117 PrettyDescriptor(array_class).c_str()).c_str());
118}
119
120// ClassCastException
121
Ian Rogersef7d42f2014-01-06 12:55:46 -0800122void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800123 ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
124 StringPrintf("%s cannot be cast to %s",
125 PrettyDescriptor(src_type).c_str(),
126 PrettyDescriptor(dest_type).c_str()).c_str());
127}
128
129void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) {
130 ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg);
131}
132
133// ClassCircularityError
134
135void ThrowClassCircularityError(mirror::Class* c) {
136 std::ostringstream msg;
137 msg << PrettyDescriptor(c);
138 ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
139}
140
141// ClassFormatError
142
Ian Rogersef7d42f2014-01-06 12:55:46 -0800143void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800144 va_list args;
145 va_start(args, fmt);
146 ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
147 va_end(args);}
148
Ian Rogers87e552d2012-08-31 15:54:48 -0700149// IllegalAccessError
150
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800151void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700152 std::ostringstream msg;
Ian Rogersb726dcb2012-09-05 08:57:23 -0700153 msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
Ian Rogers87e552d2012-08-31 15:54:48 -0700154 << PrettyDescriptor(accessed) << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800155 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700156}
157
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800158void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800159 mirror::ArtMethod* called,
Ian Rogers87e552d2012-08-31 15:54:48 -0700160 InvokeType type) {
161 std::ostringstream msg;
Ian Rogersb726dcb2012-09-05 08:57:23 -0700162 msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
163 << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
Ian Rogers87e552d2012-08-31 15:54:48 -0700164 << " method " << PrettyMethod(called).c_str();
Ian Rogers62d6c772013-02-27 08:32:07 -0800165 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700166}
167
Brian Carlstromea46f952013-07-30 01:26:50 -0700168void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700169 std::ostringstream msg;
170 msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
171 << PrettyDescriptor(referrer) << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800172 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700173}
174
Brian Carlstromea46f952013-07-30 01:26:50 -0700175void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700176 std::ostringstream msg;
177 msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
178 << PrettyDescriptor(referrer) << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800179 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700180}
181
Ian Rogersef7d42f2014-01-06 12:55:46 -0800182void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
Brian Carlstromea46f952013-07-30 01:26:50 -0700183 mirror::ArtField* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700184 std::ostringstream msg;
185 msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
186 << PrettyMethod(referrer) << "'";
Brian Carlstromea46f952013-07-30 01:26:50 -0700187 ThrowException(NULL, "Ljava/lang/IllegalAccessError;",
188 referrer != NULL ? referrer->GetClass() : NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800189 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700190}
191
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700192void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800193 va_list args;
194 va_start(args, fmt);
195 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
196 va_end(args);
197}
198
Jeff Hao11d5d8f2014-03-26 15:08:20 -0700199// IllegalAccessException
200
201void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) {
202 ThrowException(throw_location, "Ljava/lang/IllegalAccessException;", NULL, msg);
203}
204
Ian Rogers62d6c772013-02-27 08:32:07 -0800205// IllegalArgumentException
206
207void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) {
208 ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg);
209}
210
211
Ian Rogers87e552d2012-08-31 15:54:48 -0700212// IncompatibleClassChangeError
213
214void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
Brian Carlstromea46f952013-07-30 01:26:50 -0700215 mirror::ArtMethod* method,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800216 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700217 std::ostringstream msg;
218 msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
219 << expected_type << " but instead was found to be of type " << found_type;
Ian Rogers62d6c772013-02-27 08:32:07 -0800220 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
221 referrer != NULL ? referrer->GetClass() : NULL,
222 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700223}
224
Ian Rogersef7d42f2014-01-06 12:55:46 -0800225void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800226 mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800227 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700228 // Referrer is calling interface_method on this_object, however, the interface_method isn't
229 // implemented by this_object.
230 CHECK(this_object != NULL);
231 std::ostringstream msg;
232 msg << "Class '" << PrettyDescriptor(this_object->GetClass())
233 << "' does not implement interface '"
234 << PrettyDescriptor(interface_method->GetDeclaringClass())
235 << "' in call to '" << PrettyMethod(interface_method) << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800236 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
237 referrer != NULL ? referrer->GetClass() : NULL,
238 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700239}
240
Ian Rogersef7d42f2014-01-06 12:55:46 -0800241void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
242 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700243 std::ostringstream msg;
244 msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
Ian Rogersb726dcb2012-09-05 08:57:23 -0700245 << (is_static ? "static" : "instance") << " field" << " rather than a "
246 << (is_static ? "instance" : "static") << " field";
Ian Rogers62d6c772013-02-27 08:32:07 -0800247 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
248 msg.str().c_str());
249}
250
Ian Rogersef7d42f2014-01-06 12:55:46 -0800251void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800252 va_list args;
253 va_start(args, fmt);
254 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
255 va_end(args);
256}
257
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700258// IOException
259
260void ThrowIOException(const char* fmt, ...) {
261 va_list args;
262 va_start(args, fmt);
263 ThrowException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
264 va_end(args);
265}
266
Andreas Gampe329d1882014-04-08 10:32:19 -0700267void ThrowWrappedIOException(const char* fmt, ...) {
268 va_list args;
269 va_start(args, fmt);
270 ThrowWrappedException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
271 va_end(args);
272}
273
Ian Rogers62d6c772013-02-27 08:32:07 -0800274// LinkageError
275
Ian Rogersef7d42f2014-01-06 12:55:46 -0800276void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800277 va_list args;
278 va_start(args, fmt);
279 ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
280 va_end(args);
281}
282
283// NegativeArraySizeException
284
285void ThrowNegativeArraySizeException(int size) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700286 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL,
287 StringPrintf("%d", size).c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800288}
289
290void ThrowNegativeArraySizeException(const char* msg) {
291 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg);
292}
293
294// NoSuchFieldError
295
296void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
297 const StringPiece& type, const StringPiece& name)
298 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800299 std::ostringstream msg;
300 msg << "No " << scope << "field " << name << " of type " << type
Mathieu Chartierf8322842014-05-16 10:59:25 -0700301 << " in class " << c->GetDescriptor() << " or its superclasses";
Ian Rogers62d6c772013-02-27 08:32:07 -0800302 ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700303}
304
305// NoSuchMethodError
306
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800307void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
Ian Rogersd91d6d62013-09-25 20:26:14 -0700308 const Signature& signature) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700309 std::ostringstream msg;
Ian Rogers87e552d2012-08-31 15:54:48 -0700310 msg << "No " << type << " method " << name << signature
Mathieu Chartierf8322842014-05-16 10:59:25 -0700311 << " in class " << c->GetDescriptor() << " or its super classes";
Ian Rogers62d6c772013-02-27 08:32:07 -0800312 ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700313}
314
Ian Rogers62d6c772013-02-27 08:32:07 -0800315void ThrowNoSuchMethodError(uint32_t method_idx) {
316 Thread* self = Thread::Current();
317 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
318 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
Ian Rogers4445a7e2012-10-05 17:19:13 -0700319 const DexFile& dex_file = *dex_cache->GetDexFile();
Ian Rogers87e552d2012-08-31 15:54:48 -0700320 std::ostringstream msg;
321 msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
Ian Rogers62d6c772013-02-27 08:32:07 -0800322 ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;",
323 throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str());
324}
325
326// NullPointerException
327
328void ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location,
Brian Carlstromea46f952013-07-30 01:26:50 -0700329 mirror::ArtField* field, bool is_read) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800330 std::ostringstream msg;
331 msg << "Attempt to " << (is_read ? "read from" : "write to")
332 << " field '" << PrettyField(field, true) << "' on a null object reference";
333 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
334}
335
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200336static void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location,
337 uint32_t method_idx,
338 const DexFile& dex_file,
339 InvokeType type)
340 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800341 std::ostringstream msg;
342 msg << "Attempt to invoke " << type << " method '"
343 << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
344 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
345}
346
Brian Carlstromea46f952013-07-30 01:26:50 -0700347void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
348 uint32_t method_idx,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200349 InvokeType type) {
350 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
351 const DexFile& dex_file = *dex_cache->GetDexFile();
352 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx,
353 dex_file, type);
354}
355
356void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
Brian Carlstromea46f952013-07-30 01:26:50 -0700357 mirror::ArtMethod* method,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200358 InvokeType type) {
359 mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
360 const DexFile& dex_file = *dex_cache->GetDexFile();
361 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(),
362 dex_file, type);
363}
364
Ian Rogers62d6c772013-02-27 08:32:07 -0800365void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) {
366 const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem();
367 uint32_t throw_dex_pc = throw_location.GetDexPc();
368 CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
369 const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
Ian Rogers62d6c772013-02-27 08:32:07 -0800370 switch (instr->Opcode()) {
371 case Instruction::INVOKE_DIRECT:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200372 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect);
373 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800374 case Instruction::INVOKE_DIRECT_RANGE:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200375 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect);
Ian Rogers62d6c772013-02-27 08:32:07 -0800376 break;
377 case Instruction::INVOKE_VIRTUAL:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200378 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual);
379 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800380 case Instruction::INVOKE_VIRTUAL_RANGE:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200381 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual);
Ian Rogers62d6c772013-02-27 08:32:07 -0800382 break;
383 case Instruction::INVOKE_INTERFACE:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200384 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface);
385 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800386 case Instruction::INVOKE_INTERFACE_RANGE:
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200387 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface);
Ian Rogers62d6c772013-02-27 08:32:07 -0800388 break;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200389 case Instruction::INVOKE_VIRTUAL_QUICK:
390 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
391 // Since we replaced the method index, we ask the verifier to tell us which
392 // method is invoked at this location.
Brian Carlstromea46f952013-07-30 01:26:50 -0700393 mirror::ArtMethod* method =
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200394 verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(),
395 throw_location.GetDexPc());
396 if (method != NULL) {
397 // NPE with precise message.
398 ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual);
399 } else {
400 // NPE with imprecise message.
401 ThrowNullPointerException(&throw_location,
402 "Attempt to invoke a virtual method on a null object reference");
403 }
404 break;
405 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800406 case Instruction::IGET:
407 case Instruction::IGET_WIDE:
408 case Instruction::IGET_OBJECT:
409 case Instruction::IGET_BOOLEAN:
410 case Instruction::IGET_BYTE:
411 case Instruction::IGET_CHAR:
412 case Instruction::IGET_SHORT: {
Brian Carlstromea46f952013-07-30 01:26:50 -0700413 mirror::ArtField* field =
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200414 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
Ian Rogers62d6c772013-02-27 08:32:07 -0800415 throw_location.GetMethod(), false);
416 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
417 break;
418 }
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200419 case Instruction::IGET_QUICK:
420 case Instruction::IGET_WIDE_QUICK:
421 case Instruction::IGET_OBJECT_QUICK: {
422 // Since we replaced the field index, we ask the verifier to tell us which
423 // field is accessed at this location.
Brian Carlstromea46f952013-07-30 01:26:50 -0700424 mirror::ArtField* field =
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200425 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
426 throw_location.GetDexPc());
427 if (field != NULL) {
428 // NPE with precise message.
429 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
430 } else {
431 // NPE with imprecise message.
432 ThrowNullPointerException(&throw_location,
433 "Attempt to read from a field on a null object reference");
434 }
435 break;
436 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800437 case Instruction::IPUT:
438 case Instruction::IPUT_WIDE:
439 case Instruction::IPUT_OBJECT:
440 case Instruction::IPUT_BOOLEAN:
441 case Instruction::IPUT_BYTE:
442 case Instruction::IPUT_CHAR:
443 case Instruction::IPUT_SHORT: {
Brian Carlstromea46f952013-07-30 01:26:50 -0700444 mirror::ArtField* field =
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200445 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
Ian Rogers62d6c772013-02-27 08:32:07 -0800446 throw_location.GetMethod(), false);
447 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
448 break;
449 }
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200450 case Instruction::IPUT_QUICK:
451 case Instruction::IPUT_WIDE_QUICK:
452 case Instruction::IPUT_OBJECT_QUICK: {
453 // Since we replaced the field index, we ask the verifier to tell us which
454 // field is accessed at this location.
Brian Carlstromea46f952013-07-30 01:26:50 -0700455 mirror::ArtField* field =
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200456 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
457 throw_location.GetDexPc());
458 if (field != NULL) {
459 // NPE with precise message.
460 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
461 } else {
462 // NPE with imprecise message.
463 ThrowNullPointerException(&throw_location,
464 "Attempt to write to a field on a null object reference");
465 }
466 break;
467 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800468 case Instruction::AGET:
469 case Instruction::AGET_WIDE:
470 case Instruction::AGET_OBJECT:
471 case Instruction::AGET_BOOLEAN:
472 case Instruction::AGET_BYTE:
473 case Instruction::AGET_CHAR:
474 case Instruction::AGET_SHORT:
475 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
476 "Attempt to read from null array");
477 break;
478 case Instruction::APUT:
479 case Instruction::APUT_WIDE:
480 case Instruction::APUT_OBJECT:
481 case Instruction::APUT_BOOLEAN:
482 case Instruction::APUT_BYTE:
483 case Instruction::APUT_CHAR:
484 case Instruction::APUT_SHORT:
485 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
486 "Attempt to write to null array");
487 break;
488 case Instruction::ARRAY_LENGTH:
489 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
490 "Attempt to get length of null array");
491 break;
492 default: {
493 // TODO: We should have covered all the cases where we expect a NPE above, this
494 // message/logging is so we can improve any cases we've missed in the future.
495 const DexFile& dex_file =
496 *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile();
497 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
498 StringPrintf("Null pointer exception during instruction '%s'",
499 instr->DumpString(&dex_file).c_str()).c_str());
500 break;
501 }
502 }
503}
504
505void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) {
506 ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg);
507}
508
509// RuntimeException
510
511void ThrowRuntimeException(const char* fmt, ...) {
512 va_list args;
513 va_start(args, fmt);
514 ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args);
515 va_end(args);
516}
517
518// VerifyError
519
Ian Rogersef7d42f2014-01-06 12:55:46 -0800520void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800521 va_list args;
522 va_start(args, fmt);
523 ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
524 va_end(args);
Ian Rogers87e552d2012-08-31 15:54:48 -0700525}
526
527} // namespace art