blob: 36de2215491c8effdf3e01a283b706ed27d2a8f2 [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
Ian Rogers22d5e732014-07-15 22:23:51 -070019#include <sstream>
20
Elliott Hughes07ed66b2012-12-12 18:34:25 -080021#include "base/logging.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080022#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070023#include "dex_file-inl.h"
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +020024#include "dex_instruction-inl.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070025#include "invoke_type.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070026#include "mirror/art_method-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070027#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028#include "mirror/object-inl.h"
29#include "mirror/object_array-inl.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070030#include "thread.h"
Sebastien Hertz2d6ba512013-05-17 11:31:37 +020031#include "verifier/method_verifier.h"
Ian Rogers87e552d2012-08-31 15:54:48 -070032
Ian Rogers87e552d2012-08-31 15:54:48 -070033namespace art {
34
Ian Rogersef7d42f2014-01-06 12:55:46 -080035static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
Ian Rogersb726dcb2012-09-05 08:57:23 -070036 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers87e552d2012-08-31 15:54:48 -070037 if (referrer != NULL) {
Mathieu Chartierf8322842014-05-16 10:59:25 -070038 std::string location(referrer->GetLocation());
Ian Rogers87e552d2012-08-31 15:54:48 -070039 if (!location.empty()) {
40 os << " (declaration of '" << PrettyDescriptor(referrer)
41 << "' appears in " << location << ")";
42 }
43 }
44}
45
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000046static void ThrowException(const char* exception_descriptor,
Ian Rogersef7d42f2014-01-06 12:55:46 -080047 mirror::Class* referrer, const char* fmt, va_list* args = NULL)
Ian Rogers62d6c772013-02-27 08:32:07 -080048 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers87e552d2012-08-31 15:54:48 -070049 std::ostringstream msg;
Ian Rogers62d6c772013-02-27 08:32:07 -080050 if (args != NULL) {
51 std::string vmsg;
52 StringAppendV(&vmsg, fmt, *args);
53 msg << vmsg;
54 } else {
55 msg << fmt;
56 }
57 AddReferrerLocation(msg, referrer);
58 Thread* self = Thread::Current();
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000059 self->ThrowNewException(exception_descriptor, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -070060}
61
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000062static void ThrowWrappedException(const char* exception_descriptor,
Andreas Gampe329d1882014-04-08 10:32:19 -070063 mirror::Class* referrer, const char* fmt, va_list* args = NULL)
64 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
65 std::ostringstream msg;
66 if (args != NULL) {
67 std::string vmsg;
68 StringAppendV(&vmsg, fmt, *args);
69 msg << vmsg;
70 } else {
71 msg << fmt;
72 }
73 AddReferrerLocation(msg, referrer);
74 Thread* self = Thread::Current();
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000075 self->ThrowNewWrappedException(exception_descriptor, msg.str().c_str());
Andreas Gampe329d1882014-04-08 10:32:19 -070076}
77
Sebastien Hertz56adf602013-07-09 17:27:07 +020078// AbstractMethodError
79
Ian Rogersef7d42f2014-01-06 12:55:46 -080080void ThrowAbstractMethodError(mirror::ArtMethod* method) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000081 ThrowException("Ljava/lang/AbstractMethodError;", NULL,
Sebastien Hertz56adf602013-07-09 17:27:07 +020082 StringPrintf("abstract method \"%s\"",
83 PrettyMethod(method).c_str()).c_str());
84}
85
Ian Rogers62d6c772013-02-27 08:32:07 -080086// ArithmeticException
87
Sebastien Hertz0a3b8632013-06-26 11:16:01 +020088void ThrowArithmeticExceptionDivideByZero() {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000089 ThrowException("Ljava/lang/ArithmeticException;", NULL, "divide by zero");
Ian Rogers62d6c772013-02-27 08:32:07 -080090}
91
92// ArrayIndexOutOfBoundsException
93
94void ThrowArrayIndexOutOfBoundsException(int index, int length) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000095 ThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -080096 StringPrintf("length=%d; index=%d", length, index).c_str());
97}
98
99// ArrayStoreException
100
Ian Rogersef7d42f2014-01-06 12:55:46 -0800101void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000102 ThrowException("Ljava/lang/ArrayStoreException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800103 StringPrintf("%s cannot be stored in an array of type %s",
104 PrettyDescriptor(element_class).c_str(),
105 PrettyDescriptor(array_class).c_str()).c_str());
106}
107
108// ClassCastException
109
Ian Rogersef7d42f2014-01-06 12:55:46 -0800110void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000111 ThrowException("Ljava/lang/ClassCastException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800112 StringPrintf("%s cannot be cast to %s",
113 PrettyDescriptor(src_type).c_str(),
114 PrettyDescriptor(dest_type).c_str()).c_str());
115}
116
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000117void ThrowClassCastException(const char* msg) {
118 ThrowException("Ljava/lang/ClassCastException;", NULL, msg);
Ian Rogers62d6c772013-02-27 08:32:07 -0800119}
120
121// ClassCircularityError
122
123void ThrowClassCircularityError(mirror::Class* c) {
124 std::ostringstream msg;
125 msg << PrettyDescriptor(c);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000126 ThrowException("Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800127}
128
129// ClassFormatError
130
Ian Rogersef7d42f2014-01-06 12:55:46 -0800131void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800132 va_list args;
133 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000134 ThrowException("Ljava/lang/ClassFormatError;", referrer, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800135 va_end(args);}
136
Ian Rogers87e552d2012-08-31 15:54:48 -0700137// IllegalAccessError
138
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800139void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700140 std::ostringstream msg;
Ian Rogersb726dcb2012-09-05 08:57:23 -0700141 msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
Ian Rogers87e552d2012-08-31 15:54:48 -0700142 << PrettyDescriptor(accessed) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000143 ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700144}
145
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800146void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800147 mirror::ArtMethod* called,
Ian Rogers87e552d2012-08-31 15:54:48 -0700148 InvokeType type) {
149 std::ostringstream msg;
Ian Rogersb726dcb2012-09-05 08:57:23 -0700150 msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
151 << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
Ian Rogers87e552d2012-08-31 15:54:48 -0700152 << " method " << PrettyMethod(called).c_str();
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000153 ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700154}
155
Brian Carlstromea46f952013-07-30 01:26:50 -0700156void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700157 std::ostringstream msg;
158 msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
159 << PrettyDescriptor(referrer) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000160 ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700161}
162
Brian Carlstromea46f952013-07-30 01:26:50 -0700163void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700164 std::ostringstream msg;
165 msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
166 << PrettyDescriptor(referrer) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000167 ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700168}
169
Ian Rogersef7d42f2014-01-06 12:55:46 -0800170void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
Brian Carlstromea46f952013-07-30 01:26:50 -0700171 mirror::ArtField* accessed) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700172 std::ostringstream msg;
173 msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
174 << PrettyMethod(referrer) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000175 ThrowException("Ljava/lang/IllegalAccessError;",
Brian Carlstromea46f952013-07-30 01:26:50 -0700176 referrer != NULL ? referrer->GetClass() : NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800177 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700178}
179
Brian Carlstrom2ce745c2013-07-17 17:44:30 -0700180void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800181 va_list args;
182 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000183 ThrowException("Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800184 va_end(args);
185}
186
Jeff Hao11d5d8f2014-03-26 15:08:20 -0700187// IllegalAccessException
188
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000189void ThrowIllegalAccessException(const char* msg) {
190 ThrowException("Ljava/lang/IllegalAccessException;", NULL, msg);
Jeff Hao11d5d8f2014-03-26 15:08:20 -0700191}
192
Ian Rogers62d6c772013-02-27 08:32:07 -0800193// IllegalArgumentException
194
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000195void ThrowIllegalArgumentException(const char* msg) {
196 ThrowException("Ljava/lang/IllegalArgumentException;", NULL, msg);
Ian Rogers62d6c772013-02-27 08:32:07 -0800197}
198
199
Ian Rogers87e552d2012-08-31 15:54:48 -0700200// IncompatibleClassChangeError
201
202void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
Brian Carlstromea46f952013-07-30 01:26:50 -0700203 mirror::ArtMethod* method,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800204 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700205 std::ostringstream msg;
206 msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
207 << expected_type << " but instead was found to be of type " << found_type;
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000208 ThrowException("Ljava/lang/IncompatibleClassChangeError;",
Ian Rogers62d6c772013-02-27 08:32:07 -0800209 referrer != NULL ? referrer->GetClass() : NULL,
210 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700211}
212
Ian Rogersef7d42f2014-01-06 12:55:46 -0800213void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800214 mirror::Object* this_object,
Ian Rogersef7d42f2014-01-06 12:55:46 -0800215 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700216 // Referrer is calling interface_method on this_object, however, the interface_method isn't
217 // implemented by this_object.
218 CHECK(this_object != NULL);
219 std::ostringstream msg;
220 msg << "Class '" << PrettyDescriptor(this_object->GetClass())
221 << "' does not implement interface '"
222 << PrettyDescriptor(interface_method->GetDeclaringClass())
223 << "' in call to '" << PrettyMethod(interface_method) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000224 ThrowException("Ljava/lang/IncompatibleClassChangeError;",
Ian Rogers62d6c772013-02-27 08:32:07 -0800225 referrer != NULL ? referrer->GetClass() : NULL,
226 msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700227}
228
Ian Rogersef7d42f2014-01-06 12:55:46 -0800229void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
230 mirror::ArtMethod* referrer) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700231 std::ostringstream msg;
232 msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
Ian Rogersb726dcb2012-09-05 08:57:23 -0700233 << (is_static ? "static" : "instance") << " field" << " rather than a "
234 << (is_static ? "instance" : "static") << " field";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000235 ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
Ian Rogers62d6c772013-02-27 08:32:07 -0800236 msg.str().c_str());
237}
238
Ian Rogersef7d42f2014-01-06 12:55:46 -0800239void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800240 va_list args;
241 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000242 ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800243 va_end(args);
244}
245
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700246// IOException
247
248void ThrowIOException(const char* fmt, ...) {
249 va_list args;
250 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000251 ThrowException("Ljava/io/IOException;", NULL, fmt, &args);
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700252 va_end(args);
253}
254
Andreas Gampe329d1882014-04-08 10:32:19 -0700255void ThrowWrappedIOException(const char* fmt, ...) {
256 va_list args;
257 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000258 ThrowWrappedException("Ljava/io/IOException;", NULL, fmt, &args);
Andreas Gampe329d1882014-04-08 10:32:19 -0700259 va_end(args);
260}
261
Ian Rogers62d6c772013-02-27 08:32:07 -0800262// LinkageError
263
Ian Rogersef7d42f2014-01-06 12:55:46 -0800264void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800265 va_list args;
266 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000267 ThrowException("Ljava/lang/LinkageError;", referrer, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800268 va_end(args);
269}
270
271// NegativeArraySizeException
272
273void ThrowNegativeArraySizeException(int size) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000274 ThrowException("Ljava/lang/NegativeArraySizeException;", NULL,
Brian Carlstromea46f952013-07-30 01:26:50 -0700275 StringPrintf("%d", size).c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800276}
277
278void ThrowNegativeArraySizeException(const char* msg) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000279 ThrowException("Ljava/lang/NegativeArraySizeException;", NULL, msg);
Ian Rogers62d6c772013-02-27 08:32:07 -0800280}
281
282// NoSuchFieldError
283
284void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
285 const StringPiece& type, const StringPiece& name)
286 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800287 std::ostringstream msg;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700288 std::string temp;
Ian Rogers62d6c772013-02-27 08:32:07 -0800289 msg << "No " << scope << "field " << name << " of type " << type
Ian Rogers1ff3c982014-08-12 02:30:58 -0700290 << " in class " << c->GetDescriptor(&temp) << " or its superclasses";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000291 ThrowException("Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700292}
293
294// NoSuchMethodError
295
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800296void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
Ian Rogersd91d6d62013-09-25 20:26:14 -0700297 const Signature& signature) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700298 std::ostringstream msg;
Ian Rogers1ff3c982014-08-12 02:30:58 -0700299 std::string temp;
Ian Rogers87e552d2012-08-31 15:54:48 -0700300 msg << "No " << type << " method " << name << signature
Ian Rogers1ff3c982014-08-12 02:30:58 -0700301 << " in class " << c->GetDescriptor(&temp) << " or its super classes";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000302 ThrowException("Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
Ian Rogers87e552d2012-08-31 15:54:48 -0700303}
304
Ian Rogers62d6c772013-02-27 08:32:07 -0800305void ThrowNoSuchMethodError(uint32_t method_idx) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000306 mirror::ArtMethod* method = Thread::Current()->GetCurrentMethod(nullptr);
307 mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
Ian Rogers4445a7e2012-10-05 17:19:13 -0700308 const DexFile& dex_file = *dex_cache->GetDexFile();
Ian Rogers87e552d2012-08-31 15:54:48 -0700309 std::ostringstream msg;
310 msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000311 ThrowException("Ljava/lang/NoSuchMethodError;",
312 method->GetDeclaringClass(), msg.str().c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800313}
314
315// NullPointerException
316
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000317void ThrowNullPointerExceptionForFieldAccess(mirror::ArtField* field, bool is_read) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800318 std::ostringstream msg;
319 msg << "Attempt to " << (is_read ? "read from" : "write to")
320 << " field '" << PrettyField(field, true) << "' on a null object reference";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000321 ThrowException("Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800322}
323
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000324static void ThrowNullPointerExceptionForMethodAccessImpl(uint32_t method_idx,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200325 const DexFile& dex_file,
326 InvokeType type)
327 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800328 std::ostringstream msg;
329 msg << "Attempt to invoke " << type << " method '"
330 << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000331 ThrowException("Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800332}
333
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000334void ThrowNullPointerExceptionForMethodAccess(uint32_t method_idx,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200335 InvokeType type) {
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000336 mirror::DexCache* dex_cache =
337 Thread::Current()->GetCurrentMethod(nullptr)->GetDeclaringClass()->GetDexCache();
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200338 const DexFile& dex_file = *dex_cache->GetDexFile();
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000339 ThrowNullPointerExceptionForMethodAccessImpl(method_idx, dex_file, type);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200340}
341
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000342void ThrowNullPointerExceptionForMethodAccess(mirror::ArtMethod* method,
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200343 InvokeType type) {
344 mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
345 const DexFile& dex_file = *dex_cache->GetDexFile();
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000346 ThrowNullPointerExceptionForMethodAccessImpl(method->GetDexMethodIndex(),
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200347 dex_file, type);
348}
349
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000350void ThrowNullPointerExceptionFromDexPC() {
351 uint32_t throw_dex_pc;
352 mirror::ArtMethod* method = Thread::Current()->GetCurrentMethod(&throw_dex_pc);
353 const DexFile::CodeItem* code = method->GetCodeItem();
Ian Rogers62d6c772013-02-27 08:32:07 -0800354 CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
355 const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
Ian Rogers62d6c772013-02-27 08:32:07 -0800356 switch (instr->Opcode()) {
357 case Instruction::INVOKE_DIRECT:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000358 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kDirect);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200359 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800360 case Instruction::INVOKE_DIRECT_RANGE:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000361 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kDirect);
Ian Rogers62d6c772013-02-27 08:32:07 -0800362 break;
363 case Instruction::INVOKE_VIRTUAL:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000364 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kVirtual);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200365 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800366 case Instruction::INVOKE_VIRTUAL_RANGE:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000367 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kVirtual);
Ian Rogers62d6c772013-02-27 08:32:07 -0800368 break;
369 case Instruction::INVOKE_INTERFACE:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000370 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kInterface);
Sebastien Hertz75b2a4a2013-05-21 09:25:10 +0200371 break;
Ian Rogers62d6c772013-02-27 08:32:07 -0800372 case Instruction::INVOKE_INTERFACE_RANGE:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000373 ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kInterface);
Ian Rogers62d6c772013-02-27 08:32:07 -0800374 break;
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200375 case Instruction::INVOKE_VIRTUAL_QUICK:
376 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
377 // Since we replaced the method index, we ask the verifier to tell us which
378 // method is invoked at this location.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000379 mirror::ArtMethod* invoked_method =
380 verifier::MethodVerifier::FindInvokedMethodAtDexPc(method, throw_dex_pc);
381 if (invoked_method != NULL) {
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200382 // NPE with precise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000383 ThrowNullPointerExceptionForMethodAccess(invoked_method, kVirtual);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200384 } else {
385 // NPE with imprecise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000386 ThrowNullPointerException("Attempt to invoke a virtual method on a null object reference");
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200387 }
388 break;
389 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800390 case Instruction::IGET:
391 case Instruction::IGET_WIDE:
392 case Instruction::IGET_OBJECT:
393 case Instruction::IGET_BOOLEAN:
394 case Instruction::IGET_BYTE:
395 case Instruction::IGET_CHAR:
396 case Instruction::IGET_SHORT: {
Brian Carlstromea46f952013-07-30 01:26:50 -0700397 mirror::ArtField* field =
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000398 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
399 ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
Ian Rogers62d6c772013-02-27 08:32:07 -0800400 break;
401 }
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200402 case Instruction::IGET_QUICK:
Mathieu Chartierffc605c2014-12-10 10:35:44 -0800403 case Instruction::IGET_BOOLEAN_QUICK:
404 case Instruction::IGET_BYTE_QUICK:
405 case Instruction::IGET_CHAR_QUICK:
406 case Instruction::IGET_SHORT_QUICK:
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200407 case Instruction::IGET_WIDE_QUICK:
408 case Instruction::IGET_OBJECT_QUICK: {
409 // Since we replaced the field index, we ask the verifier to tell us which
410 // field is accessed at this location.
Brian Carlstromea46f952013-07-30 01:26:50 -0700411 mirror::ArtField* field =
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000412 verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200413 if (field != NULL) {
414 // NPE with precise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000415 ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200416 } else {
417 // NPE with imprecise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000418 ThrowNullPointerException("Attempt to read from a field on a null object reference");
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200419 }
420 break;
421 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800422 case Instruction::IPUT:
423 case Instruction::IPUT_WIDE:
424 case Instruction::IPUT_OBJECT:
425 case Instruction::IPUT_BOOLEAN:
426 case Instruction::IPUT_BYTE:
427 case Instruction::IPUT_CHAR:
428 case Instruction::IPUT_SHORT: {
Brian Carlstromea46f952013-07-30 01:26:50 -0700429 mirror::ArtField* field =
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000430 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
431 ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
Ian Rogers62d6c772013-02-27 08:32:07 -0800432 break;
433 }
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200434 case Instruction::IPUT_QUICK:
Fred Shih37f05ef2014-07-16 18:38:08 -0700435 case Instruction::IPUT_BOOLEAN_QUICK:
436 case Instruction::IPUT_BYTE_QUICK:
437 case Instruction::IPUT_CHAR_QUICK:
438 case Instruction::IPUT_SHORT_QUICK:
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200439 case Instruction::IPUT_WIDE_QUICK:
440 case Instruction::IPUT_OBJECT_QUICK: {
441 // Since we replaced the field index, we ask the verifier to tell us which
442 // field is accessed at this location.
Brian Carlstromea46f952013-07-30 01:26:50 -0700443 mirror::ArtField* field =
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000444 verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200445 if (field != NULL) {
446 // NPE with precise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000447 ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200448 } else {
449 // NPE with imprecise message.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000450 ThrowNullPointerException("Attempt to write to a field on a null object reference");
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200451 }
452 break;
453 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800454 case Instruction::AGET:
455 case Instruction::AGET_WIDE:
456 case Instruction::AGET_OBJECT:
457 case Instruction::AGET_BOOLEAN:
458 case Instruction::AGET_BYTE:
459 case Instruction::AGET_CHAR:
460 case Instruction::AGET_SHORT:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000461 ThrowException("Ljava/lang/NullPointerException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800462 "Attempt to read from null array");
463 break;
464 case Instruction::APUT:
465 case Instruction::APUT_WIDE:
466 case Instruction::APUT_OBJECT:
467 case Instruction::APUT_BOOLEAN:
468 case Instruction::APUT_BYTE:
469 case Instruction::APUT_CHAR:
470 case Instruction::APUT_SHORT:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000471 ThrowException("Ljava/lang/NullPointerException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800472 "Attempt to write to null array");
473 break;
474 case Instruction::ARRAY_LENGTH:
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000475 ThrowException("Ljava/lang/NullPointerException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800476 "Attempt to get length of null array");
477 break;
478 default: {
479 // TODO: We should have covered all the cases where we expect a NPE above, this
480 // message/logging is so we can improve any cases we've missed in the future.
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000481 const DexFile* dex_file =
482 method->GetDeclaringClass()->GetDexCache()->GetDexFile();
483 ThrowException("Ljava/lang/NullPointerException;", NULL,
Ian Rogers62d6c772013-02-27 08:32:07 -0800484 StringPrintf("Null pointer exception during instruction '%s'",
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000485 instr->DumpString(dex_file).c_str()).c_str());
Ian Rogers62d6c772013-02-27 08:32:07 -0800486 break;
487 }
488 }
489}
490
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000491void ThrowNullPointerException(const char* msg) {
492 ThrowException("Ljava/lang/NullPointerException;", NULL, msg);
Ian Rogers62d6c772013-02-27 08:32:07 -0800493}
494
495// RuntimeException
496
497void ThrowRuntimeException(const char* fmt, ...) {
498 va_list args;
499 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000500 ThrowException("Ljava/lang/RuntimeException;", NULL, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800501 va_end(args);
502}
503
504// VerifyError
505
Ian Rogersef7d42f2014-01-06 12:55:46 -0800506void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800507 va_list args;
508 va_start(args, fmt);
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +0000509 ThrowException("Ljava/lang/VerifyError;", referrer, fmt, &args);
Ian Rogers62d6c772013-02-27 08:32:07 -0800510 va_end(args);
Ian Rogers87e552d2012-08-31 15:54:48 -0700511}
512
513} // namespace art