blob: c3dd702446de5f8b32c7a9aa6889a43e8d8ea8e1 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 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
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
19#include <sys/mman.h>
20#include <zlib.h>
21
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <iomanip>
23
Andreas Gampe46ee31b2016-12-14 10:11:49 -080024#include "android-base/stringprintf.h"
25
Mathieu Chartierc7853442015-03-27 14:35:38 -070026#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070027#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080028#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070029#include "base/to_str.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030#include "class_linker-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070031#include "class_linker.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070032#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070033#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070034#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080035#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/object-inl.h"
38#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070039#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070041#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070042#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070043#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070044#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070045
46namespace art {
47
Andreas Gampe46ee31b2016-12-14 10:11:49 -080048using android::base::StringAppendF;
49using android::base::StringPrintf;
50
Elliott Hughesa2501992011-08-26 19:39:54 -070051/*
52 * ===========================================================================
53 * JNI function helpers
54 * ===========================================================================
55 */
56
Elliott Hughes3f6635a2012-06-19 13:37:49 -070057// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070058#define kFlag_Default 0x0000
59
Elliott Hughes3f6635a2012-06-19 13:37:49 -070060#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
61#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
62#define kFlag_CritGet 0x0002 // This is a critical "get".
63#define kFlag_CritRelease 0x0003 // This is a critical "release".
64#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Elliott Hughes3f6635a2012-06-19 13:37:49 -070066#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
67#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070068
Elliott Hughes3f6635a2012-06-19 13:37:49 -070069#define kFlag_Release 0x0010 // Are we in a non-critical release function?
70#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070071
Elliott Hughes3f6635a2012-06-19 13:37:49 -070072#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070073
Elliott Hughes485cac42011-12-09 17:49:35 -080074#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Alex Light48ffe062015-08-19 15:23:23 -070075
76class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070077/*
78 * Java primitive types:
79 * B - jbyte
80 * C - jchar
81 * D - jdouble
82 * F - jfloat
83 * I - jint
84 * J - jlong
85 * S - jshort
86 * Z - jboolean (shown as true and false)
87 * V - void
88 *
89 * Java reference types:
90 * L - jobject
91 * a - jarray
92 * c - jclass
93 * s - jstring
94 * t - jthrowable
95 *
96 * JNI types:
97 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
98 * f - jfieldID
99 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
100 * m - jmethodID
101 * p - void*
102 * r - jint (for release mode arguments)
103 * u - const char* (Modified UTF-8)
104 * z - jsize (for lengths; use i if negative values are okay)
105 * v - JavaVM*
106 * w - jobjectRefType
107 * E - JNIEnv*
108 * . - no argument; just print "..." (used for varargs JNI calls)
109 *
110 */
111union JniValueType {
112 jarray a;
113 jboolean b;
114 jclass c;
115 jfieldID f;
116 jint i;
117 jmethodID m;
118 const void* p; // Pointer.
119 jint r; // Release mode.
120 jstring s;
121 jthrowable t;
122 const char* u; // Modified UTF-8.
123 JavaVM* v;
124 jobjectRefType w;
125 jsize z;
126 jbyte B;
127 jchar C;
128 jdouble D;
129 JNIEnv* E;
130 jfloat F;
131 jint I;
132 jlong J;
133 jobject L;
134 jshort S;
135 const void* V; // void
136 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700137 const VarArgs* va;
138};
139
140/*
141 * A structure containing all the information needed to validate varargs arguments.
142 *
143 * Note that actually getting the arguments from this structure mutates it so should only be done on
144 * owned copies.
145 */
146class VarArgs {
147 public:
148 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
149 va_copy(vargs_, var);
150 }
151
152 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
153
154 ~VarArgs() {
155 if (type_ == kTypeVaList) {
156 va_end(vargs_);
157 }
158 }
159
160 VarArgs(VarArgs&& other) {
161 m_ = other.m_;
162 cnt_ = other.cnt_;
163 type_ = other.type_;
164 if (other.type_ == kTypeVaList) {
165 va_copy(vargs_, other.vargs_);
166 } else {
167 ptr_ = other.ptr_;
168 }
169 }
170
171 // This method is const because we need to ensure that one only uses the GetValue method on an
172 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
173 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
174 // we want to use one we need to Clone() it.
175 VarArgs Clone() const {
176 if (type_ == kTypeVaList) {
177 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
178 // messed up if the source argument is not the exact type 'va_list'.
179 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
180 } else {
181 return VarArgs(m_, cnt_, ptr_);
182 }
183 }
184
185 jmethodID GetMethodID() const {
186 return m_;
187 }
188
189 JniValueType GetValue(char fmt) {
190 JniValueType o;
191 if (type_ == kTypeVaList) {
192 switch (fmt) {
193 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
194 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
195 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
196 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
197 case 'I': o.I = va_arg(vargs_, jint); break;
198 case 'J': o.J = va_arg(vargs_, jlong); break;
199 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
200 case 'D': o.D = va_arg(vargs_, jdouble); break;
201 case 'L': o.L = va_arg(vargs_, jobject); break;
202 default:
203 LOG(FATAL) << "Illegal type format char " << fmt;
204 UNREACHABLE();
205 }
206 } else {
207 CHECK(type_ == kTypePtr);
208 jvalue v = ptr_[cnt_];
209 cnt_++;
210 switch (fmt) {
211 case 'Z': o.Z = v.z; break;
212 case 'B': o.B = v.b; break;
213 case 'C': o.C = v.c; break;
214 case 'S': o.S = v.s; break;
215 case 'I': o.I = v.i; break;
216 case 'J': o.J = v.j; break;
217 case 'F': o.F = v.f; break;
218 case 'D': o.D = v.d; break;
219 case 'L': o.L = v.l; break;
220 default:
221 LOG(FATAL) << "Illegal type format char " << fmt;
222 UNREACHABLE();
223 }
224 }
225 return o;
226 }
227
228 private:
229 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
230 va_copy(vargs_, var);
231 }
232
233 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
234
235 enum VarArgsType {
236 kTypeVaList,
237 kTypePtr,
238 };
239
240 jmethodID m_;
241 VarArgsType type_;
242 uint32_t cnt_;
243 union {
244 va_list vargs_;
245 const jvalue* ptr_;
246 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700247};
248
Elliott Hughesa2501992011-08-26 19:39:54 -0700249class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800250 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100251 ScopedCheck(int flags, const char* functionName, bool has_method = true)
Ian Rogers68d8b422014-07-17 11:09:10 -0700252 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700253 }
254
Ian Rogers68d8b422014-07-17 11:09:10 -0700255 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700256
Elliott Hughes81ff3182012-03-23 20:35:56 -0700257 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
258 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
259 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
260 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700261 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700262 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700263 AbortF("illegal class name '%s'\n"
264 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
265 class_name);
266 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700267 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700268 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700269 }
270
271 /*
272 * Verify that this instance field ID is valid for this object.
273 *
274 * Assumes "jobj" has already been validated.
275 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700276 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700277 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700278 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700279 if (o == nullptr) {
280 AbortF("field operation on NULL object: %p", java_object);
281 return false;
282 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700283 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700284 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700285 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700286 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700287 java_object);
288 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700289 }
290
Andreas Gampe08883de2016-11-08 13:20:52 -0800291 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800292 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700293 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700294 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800295 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700296 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700297 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700298 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700299 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700300 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700301 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700302 }
303
304 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700305 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700306 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700307 bool CheckNonNull(const void* ptr) {
308 if (UNLIKELY(ptr == nullptr)) {
309 AbortF("non-nullable argument was NULL");
310 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700311 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700312 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700313 }
314
315 /*
316 * Verify that the method's return type matches the type of call.
317 * 'expectedType' will be "L" for all objects, including arrays.
318 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700319 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
320 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700321 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800322 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800323 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700324 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700325 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700326 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700327 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700328 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700329 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700330 bool is_static = (invoke == kStatic);
331 if (is_static != m->IsStatic()) {
332 if (is_static) {
333 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700334 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700335 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700336 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700337 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700338 }
339 return false;
340 }
341 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700342 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700343 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700344 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700345 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700346 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700347 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700348 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700349 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700350 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700351 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700352 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700353 return false;
354 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700355 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
356 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700357 return false;
358 }
359 }
360 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700361 }
362
363 /*
364 * Verify that this static field ID is valid for this class.
365 *
366 * Assumes "java_class" has already been validated.
367 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700368 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700369 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700370 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800371 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800372 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700373 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700374 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700375 if (c != f->GetDeclaringClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700376 AbortF("static jfieldID %p not valid for class %s", fid,
377 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700378 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700379 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700380 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700381 }
382
383 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700384 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700385 *
386 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700387 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700388 * allow bad code in the system though.
389 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700390 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700391 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700392 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700393 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800394 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800395 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700396 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700397 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700398 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700399 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700400 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
401 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700402 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700403 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700404 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700405 }
406
407 /*
408 * Verify that "mid" is appropriate for "jobj".
409 *
410 * Make sure the object is an instance of the method's declaring class.
411 * (Note the mid might point to a declaration in an interface; this
412 * will be handled automatically by the instanceof check.)
413 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700414 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700415 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800416 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800417 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700418 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700419 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700420 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700421 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700422 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700423 return false;
424 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700425 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
426 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700427 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700428 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700429 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700430 }
431
432 /**
433 * The format string is a sequence of the following characters,
434 * and must be followed by arguments of the corresponding types
435 * in the same order.
436 *
437 * Java primitive types:
438 * B - jbyte
439 * C - jchar
440 * D - jdouble
441 * F - jfloat
442 * I - jint
443 * J - jlong
444 * S - jshort
445 * Z - jboolean (shown as true and false)
446 * V - void
447 *
448 * Java reference types:
449 * L - jobject
450 * a - jarray
451 * c - jclass
452 * s - jstring
453 *
454 * JNI types:
455 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
456 * f - jfieldID
457 * m - jmethodID
458 * p - void*
459 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700460 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700461 * z - jsize (for lengths; use i if negative values are okay)
462 * v - JavaVM*
463 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700464 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700465 *
466 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
467 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700468 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700469 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700470 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700471 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700472 // We need to guard some of the invocation interface's calls: a bad caller might
473 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700474 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800475 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
476 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700477 }
478 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700479
Ian Rogersef7d42f2014-01-06 12:55:46 -0800480 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700481 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700482 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700483 for (size_t i = 0; fmt[i] != '\0'; ++i) {
484 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
485 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700486 StringAppendF(&msg, ", ");
487 }
488 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700489
Elliott Hughes485cac42011-12-09 17:49:35 -0800490 if ((flags_ & kFlag_ForceTrace) != 0) {
491 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
492 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700493 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700494 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700495 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
496 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700497 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700498 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
499 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700500 }
501 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700502 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700503 }
504 }
505
506 // We always do the thorough checks on entry, and never on exit...
507 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700508 for (size_t i = 0; fmt[i] != '\0'; ++i) {
509 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
510 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700511 }
512 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700513 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700514 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700515 }
516
Ian Rogers68d8b422014-07-17 11:09:10 -0700517 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
518 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800519 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700520 // We need to guard some of the invocation interface's calls: a bad caller might
521 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
522 Thread* self = Thread::Current();
523 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
524 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700525 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700526 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
527 }
528 }
529 if (should_trace) {
530 std::string msg;
531 for (size_t i = 0; fmt[i] != '\0'; ++i) {
532 TraceNonHeapValue(fmt[i], args[i], &msg);
533 if (fmt[i + 1] != '\0') {
534 StringAppendF(&msg, ", ");
535 }
536 }
537
538 if ((flags_ & kFlag_ForceTrace) != 0) {
539 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
540 } else if (entry) {
541 if (has_method_) {
542 Thread* self = Thread::Current();
543 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700544 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700545 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700546 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
547 indent_ = methodName.size() + 1;
548 } else {
549 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
550 indent_ = 0;
551 }
552 } else {
553 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
554 }
555 }
556
557 // We always do the thorough checks on entry, and never on exit...
558 if (entry) {
559 for (size_t i = 0; fmt[i] != '\0'; ++i) {
560 if (!CheckNonHeapValue(fmt[i], args[i])) {
561 return false;
562 }
563 }
564 }
565 return true;
566 }
567
568 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700569 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700570 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700571 if (method == nullptr) {
572 AbortF("expected non-null method");
573 return false;
574 }
575 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700576 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
577 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700578 AbortF("expected java.lang.reflect.Method or "
579 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700580 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700581 return false;
582 }
583 return true;
584 }
585
Andreas Gampe13b27842016-11-07 16:48:23 -0800586 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
587 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700588 if (method == nullptr) {
589 AbortF("expected non-null constructor");
590 return false;
591 }
592 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700593 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700594 return false;
595 }
596 return true;
597 }
598
599 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700600 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700601 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700602 if (field == nullptr) {
603 AbortF("expected non-null java.lang.reflect.Field");
604 return false;
605 }
606 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700607 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700608 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700609 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700610 return false;
611 }
612 return true;
613 }
614
615 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700616 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700617 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700618 if (!obj->GetClass()->IsThrowableClass()) {
619 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700620 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700621 return false;
622 }
623 return true;
624 }
625
626 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700627 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700628 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700629 if (!c->IsThrowableClass()) {
630 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700631 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700632 return false;
633 }
634 return true;
635 }
636
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700637 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700638 IndirectRefKind found_kind;
639 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700640 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700641 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
642 found_kind = kLocal;
643 }
644 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700645 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700646 }
647 if (obj != nullptr && found_kind != expected_kind) {
648 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700649 GetIndirectRefKindString(expected_kind),
650 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700651 obj);
652 return false;
653 }
654 return true;
655 }
656
657 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700658 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700659 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700660 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700661 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700662 return false;
663 }
664 return true;
665 }
666
667 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700668 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700669 if (!CheckArray(soa, array)) {
670 return false;
671 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700672 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700673 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
674 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700675 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700676 return false;
677 }
678 return true;
679 }
680
681 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
682 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700683 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700684 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
685 return false;
686 }
687 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
688 return false;
689 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800690 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700691 DCHECK(field != nullptr); // Already checked by Check.
692 if (is_static != field->IsStatic()) {
693 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700694 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700695 return false;
696 }
697 if (type != field->GetTypeAsPrimitiveType()) {
698 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700699 field->PrettyField().c_str(),
700 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700701 PrettyDescriptor(type).c_str(), fid);
702 return false;
703 }
704 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700705 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700706 if (o == nullptr || !o->IsClass()) {
707 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700708 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700709 return false;
710 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700711 ObjPtr<mirror::Class> c = o->AsClass();
712 if (c != field->GetDeclaringClass()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700713 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700714 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700715 return false;
716 }
717 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700718 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700719 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
720 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700721 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700722 return false;
723 }
724 }
725 return true;
726 }
727
728 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800729 enum InstanceKind {
730 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700731 kDirectByteBuffer,
732 kObject,
733 kString,
734 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800735 };
736
737 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700738 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800739 * an instance of expectedClass.
740 *
741 * Because we're looking at an object on the GC heap, we have to switch
742 * to "running" mode before doing the checks.
743 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700744 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700745 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800746 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800747 switch (kind) {
748 case kClass:
749 what = "jclass";
750 break;
751 case kDirectByteBuffer:
752 what = "direct ByteBuffer";
753 break;
754 case kObject:
755 what = "jobject";
756 break;
757 case kString:
758 what = "jstring";
759 break;
760 case kThrowable:
761 what = "jthrowable";
762 break;
763 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700764 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800765 }
766
Ian Rogersef7d42f2014-01-06 12:55:46 -0800767 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700768 if (null_ok) {
769 return true;
770 } else {
771 AbortF("%s received NULL %s", function_name_, what);
772 return false;
773 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800774 }
775
Mathieu Chartier0795f232016-09-27 18:43:30 -0700776 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700777 if (obj == nullptr) {
778 // Either java_object is invalid or is a cleared weak.
779 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
780 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700781 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700782 okay = false;
783 } else {
784 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700785 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700786 }
787 if (!okay) {
788 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700789 what,
790 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
791 java_object,
792 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700793 return false;
794 }
795 }
796
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700797 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700798 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700799 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700800 what,
801 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
802 java_object,
803 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800804 return false;
805 }
806
807 bool okay = true;
808 switch (kind) {
809 case kClass:
810 okay = obj->IsClass();
811 break;
812 case kDirectByteBuffer:
813 UNIMPLEMENTED(FATAL);
814 break;
815 case kString:
816 okay = obj->GetClass()->IsStringClass();
817 break;
818 case kThrowable:
819 okay = obj->GetClass()->IsThrowableClass();
820 break;
821 case kObject:
822 break;
823 }
824 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700825 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800826 return false;
827 }
828
829 return true;
830 }
831
Ian Rogers68d8b422014-07-17 11:09:10 -0700832 /*
833 * Verify that the "mode" argument passed to a primitive array Release
834 * function is one of the valid values.
835 */
836 bool CheckReleaseMode(jint mode) {
837 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
838 AbortF("unknown value for release mode: %d", mode);
839 return false;
840 }
841 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700842 }
843
Ian Rogers68d8b422014-07-17 11:09:10 -0700844 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700845 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700846 switch (fmt) {
847 case 'a': // jarray
848 return CheckArray(soa, arg.a);
849 case 'c': // jclass
850 return CheckInstance(soa, kClass, arg.c, false);
851 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800852 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700853 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800854 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700855 case 'r': // release int
856 return CheckReleaseMode(arg.r);
857 case 's': // jstring
858 return CheckInstance(soa, kString, arg.s, false);
859 case 't': // jthrowable
860 return CheckInstance(soa, kThrowable, arg.t, false);
861 case 'E': // JNIEnv*
862 return CheckThread(arg.E);
863 case 'L': // jobject
864 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700865 case '.': // A VarArgs list
866 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700867 default:
868 return CheckNonHeapValue(fmt, arg);
869 }
870 }
871
Alex Light48ffe062015-08-19 15:23:23 -0700872 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700873 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700874 CHECK(args_p != nullptr);
875 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800876 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700877 if (m == nullptr) {
878 return false;
879 }
880 uint32_t len = 0;
881 const char* shorty = m->GetShorty(&len);
882 // Skip the return type
883 CHECK_GE(len, 1u);
884 len--;
885 shorty++;
886 for (uint32_t i = 0; i < len; i++) {
887 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
888 return false;
889 }
890 }
891 return true;
892 }
893
Ian Rogers68d8b422014-07-17 11:09:10 -0700894 bool CheckNonHeapValue(char fmt, JniValueType arg) {
895 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700896 case 'p': // TODO: pointer - null or readable?
897 case 'v': // JavaVM*
898 case 'B': // jbyte
899 case 'C': // jchar
900 case 'D': // jdouble
901 case 'F': // jfloat
902 case 'I': // jint
903 case 'J': // jlong
904 case 'S': // jshort
905 break; // Ignored.
906 case 'b': // jboolean, why two? Fall-through.
907 case 'Z':
908 return CheckBoolean(arg.Z);
909 case 'u': // utf8
910 if ((flags_ & kFlag_Release) != 0) {
911 return CheckNonNull(arg.u);
912 } else {
913 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
914 return CheckUtfString(arg.u, nullable);
915 }
916 case 'w': // jobjectRefType
917 switch (arg.w) {
918 case JNIInvalidRefType:
919 case JNILocalRefType:
920 case JNIGlobalRefType:
921 case JNIWeakGlobalRefType:
922 break;
923 default:
924 AbortF("Unknown reference type");
925 return false;
926 }
927 break;
928 case 'z': // jsize
929 return CheckLengthPositive(arg.z);
930 default:
931 AbortF("unknown format specifier: '%c'", fmt);
932 return false;
933 }
934 return true;
935 }
936
937 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
938 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700939 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700940 switch (fmt) {
941 case 'L': // jobject fall-through.
942 case 'a': // jarray fall-through.
943 case 's': // jstring fall-through.
944 case 't': // jthrowable fall-through.
945 if (arg.L == nullptr) {
946 *msg += "NULL";
947 } else {
948 StringAppendF(msg, "%p", arg.L);
949 }
950 break;
951 case 'c': { // jclass
952 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700953 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700954 if (c == nullptr) {
955 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700956 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700957 StringAppendF(msg, "INVALID POINTER:%p", jc);
958 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700959 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700960 } else {
David Sehr709b0702016-10-13 09:12:37 -0700961 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700962 if (!entry) {
963 StringAppendF(msg, " (%p)", jc);
964 }
965 }
966 break;
967 }
968 case 'f': { // jfieldID
969 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800970 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700971 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700972 if (!entry) {
973 StringAppendF(msg, " (%p)", fid);
974 }
975 break;
976 }
977 case 'm': { // jmethodID
978 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800979 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700980 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700981 if (!entry) {
982 StringAppendF(msg, " (%p)", mid);
983 }
984 break;
985 }
Alex Light48ffe062015-08-19 15:23:23 -0700986 case '.': {
987 const VarArgs* va = arg.va;
988 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800989 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700990 uint32_t len;
991 const char* shorty = m->GetShorty(&len);
992 CHECK_GE(len, 1u);
993 // Skip past return value.
994 len--;
995 shorty++;
996 // Remove the previous ', ' from the message.
997 msg->erase(msg->length() - 2);
998 for (uint32_t i = 0; i < len; i++) {
999 *msg += ", ";
1000 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1001 }
1002 break;
1003 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001004 default:
1005 TraceNonHeapValue(fmt, arg, msg);
1006 break;
1007 }
1008 }
1009
1010 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1011 switch (fmt) {
1012 case 'B': // jbyte
1013 if (arg.B >= 0 && arg.B < 10) {
1014 StringAppendF(msg, "%d", arg.B);
1015 } else {
1016 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1017 }
1018 break;
1019 case 'C': // jchar
1020 if (arg.C < 0x7f && arg.C >= ' ') {
1021 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1022 } else {
1023 StringAppendF(msg, "U+%x", arg.C);
1024 }
1025 break;
1026 case 'F': // jfloat
1027 StringAppendF(msg, "%g", arg.F);
1028 break;
1029 case 'D': // jdouble
1030 StringAppendF(msg, "%g", arg.D);
1031 break;
1032 case 'S': // jshort
1033 StringAppendF(msg, "%d", arg.S);
1034 break;
1035 case 'i': // jint - fall-through.
1036 case 'I': // jint
1037 StringAppendF(msg, "%d", arg.I);
1038 break;
1039 case 'J': // jlong
1040 StringAppendF(msg, "%" PRId64, arg.J);
1041 break;
1042 case 'Z': // jboolean
1043 case 'b': // jboolean (JNI-style)
1044 *msg += arg.b == JNI_TRUE ? "true" : "false";
1045 break;
1046 case 'V': // void
1047 DCHECK(arg.V == nullptr);
1048 *msg += "void";
1049 break;
1050 case 'v': // JavaVM*
1051 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1052 break;
1053 case 'E':
1054 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1055 break;
1056 case 'z': // non-negative jsize
1057 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1058 // We only treat this specially so we can do the non-negative check.
1059 // TODO: maybe this wasn't worth it?
1060 StringAppendF(msg, "%d", arg.z);
1061 break;
1062 case 'p': // void* ("pointer")
1063 if (arg.p == nullptr) {
1064 *msg += "NULL";
1065 } else {
1066 StringAppendF(msg, "(void*) %p", arg.p);
1067 }
1068 break;
1069 case 'r': { // jint (release mode)
1070 jint releaseMode = arg.r;
1071 if (releaseMode == 0) {
1072 *msg += "0";
1073 } else if (releaseMode == JNI_ABORT) {
1074 *msg += "JNI_ABORT";
1075 } else if (releaseMode == JNI_COMMIT) {
1076 *msg += "JNI_COMMIT";
1077 } else {
1078 StringAppendF(msg, "invalid release mode %d", releaseMode);
1079 }
1080 break;
1081 }
1082 case 'u': // const char* (Modified UTF-8)
1083 if (arg.u == nullptr) {
1084 *msg += "NULL";
1085 } else {
1086 StringAppendF(msg, "\"%s\"", arg.u);
1087 }
1088 break;
1089 case 'w': // jobjectRefType
1090 switch (arg.w) {
1091 case JNIInvalidRefType:
1092 *msg += "invalid reference type";
1093 break;
1094 case JNILocalRefType:
1095 *msg += "local ref type";
1096 break;
1097 case JNIGlobalRefType:
1098 *msg += "global ref type";
1099 break;
1100 case JNIWeakGlobalRefType:
1101 *msg += "weak global ref type";
1102 break;
1103 default:
1104 *msg += "unknown ref type";
1105 break;
1106 }
1107 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001108 default:
1109 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1110 }
1111 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001112 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001113 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001114 *
1115 * Since we're dealing with objects, switch to "running" mode.
1116 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001117 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001118 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001119 if (UNLIKELY(java_array == nullptr)) {
1120 AbortF("jarray was NULL");
1121 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001122 }
1123
Mathieu Chartier0795f232016-09-27 18:43:30 -07001124 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001125 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001126 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001127 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001128 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1129 java_array,
1130 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001131 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001132 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001133 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001134 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001135 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001136 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001137 }
1138
Ian Rogers68d8b422014-07-17 11:09:10 -07001139 bool CheckBoolean(jboolean z) {
1140 if (z != JNI_TRUE && z != JNI_FALSE) {
1141 AbortF("unexpected jboolean value: %d", z);
1142 return false;
1143 }
1144 return true;
1145 }
1146
1147 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001148 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001149 AbortF("negative jsize: %d", length);
1150 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001151 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001152 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001153 }
1154
Andreas Gampe08883de2016-11-08 13:20:52 -08001155 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001156 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001157 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001158 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001159 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001160 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001161 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001162 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001163 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001164 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001165 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001166 }
1167 return f;
1168 }
1169
Andreas Gampe13b27842016-11-07 16:48:23 -08001170 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001171 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001172 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001173 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001174 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001175 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001176 // TODO: Better check here.
1177 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001178 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001179 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001180 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001181 }
1182 return m;
1183 }
1184
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001185 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001186 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001187 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001188 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1189 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001190 }
1191
Daniel Erat35e827a2016-05-10 18:07:18 -06001192 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001193 JNIEnvExt* threadEnv = self->GetJniEnv();
1194
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001195 // Verify that the current thread is (a) attached and (b) associated with
1196 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001197 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001198 // Get the thread owning the JNIEnv that's being used.
1199 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001200 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001201 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001202 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001203 }
1204
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001205 // Verify that, if this thread previously made a critical "get" call, we
1206 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001207 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001208 case kFlag_CritOkay: // okay to call this method
1209 break;
1210 case kFlag_CritBad: // not okay to call
1211 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001212 AbortF("thread %s using JNI after critical get",
1213 ToStr<Thread>(*self).c_str());
1214 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001215 }
1216 break;
1217 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001218 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001219 threadEnv->critical++;
1220 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001221 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001222 threadEnv->critical--;
1223 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001224 AbortF("thread %s called too many critical releases",
1225 ToStr<Thread>(*self).c_str());
1226 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001227 }
1228 break;
1229 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001230 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001231 }
1232
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001233 // Verify that, if an exception has been raised, the native code doesn't
1234 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001235 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001236 mirror::Throwable* exception = self->GetException();
1237 AbortF("JNI %s called with pending exception %s",
1238 function_name_,
1239 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001240 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001241 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001242 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001243 }
1244
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001245 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001246 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001247 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001248 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001249 AbortF("non-nullable const char* was NULL");
1250 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001251 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001252 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001253 }
1254
Ian Rogersef7d42f2014-01-06 12:55:46 -08001255 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001256 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001257 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001258 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1259 // practice anyways.
1260 std::ostringstream oss;
1261 oss << std::hex;
1262 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1263 while (*tmp != 0) {
1264 if (tmp == utf8) {
1265 oss << "<";
1266 }
1267 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1268 if (tmp == utf8) {
1269 oss << '>';
1270 }
1271 tmp++;
1272 if (*tmp != 0) {
1273 oss << ' ';
1274 }
1275 }
1276
Ian Rogers68d8b422014-07-17 11:09:10 -07001277 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001278 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001279 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001280 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001281 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001282 }
1283
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001284 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1285 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001286 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001287 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001288 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001289 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001290 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001291 case 0x00:
1292 case 0x01:
1293 case 0x02:
1294 case 0x03:
1295 case 0x04:
1296 case 0x05:
1297 case 0x06:
1298 case 0x07:
1299 // Bit pattern 0xxx. No need for any extra bytes.
1300 break;
1301 case 0x08:
1302 case 0x09:
1303 case 0x0a:
1304 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001305 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001306 *errorKind = "start";
1307 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001308 case 0x0f:
1309 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001310 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001311 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1312 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001313 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1314 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001315 *errorKind = "continuation";
1316 return utf8;
1317 }
1318 } else {
1319 *errorKind = "start";
1320 return utf8;
1321 }
1322
1323 // Fall through to the cases below to consume two more continuation bytes.
1324 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001325 case 0x0e:
1326 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001327 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1328 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001329 *errorKind = "continuation";
1330 return utf8;
1331 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001332
1333 // Fall through to consume one more continuation byte.
1334 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001335 case 0x0c:
1336 case 0x0d:
1337 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001338 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1339 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001340 *errorKind = "continuation";
1341 return utf8;
1342 }
1343 break;
1344 }
1345 }
1346 return 0;
1347 }
1348
Ian Rogers68d8b422014-07-17 11:09:10 -07001349 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1350 va_list args;
1351 va_start(args, fmt);
1352 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1353 va_end(args);
1354 }
1355
1356 // The name of the JNI function being checked.
1357 const char* const function_name_;
1358
1359 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001360 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001361
Ian Rogers68d8b422014-07-17 11:09:10 -07001362 const bool has_method_;
1363
Elliott Hughesa2501992011-08-26 19:39:54 -07001364 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1365};
1366
Elliott Hughesa2501992011-08-26 19:39:54 -07001367/*
1368 * ===========================================================================
1369 * Guarded arrays
1370 * ===========================================================================
1371 */
1372
Elliott Hughesa2501992011-08-26 19:39:54 -07001373/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001374class GuardedCopy {
1375 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001376 /*
1377 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1378 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001379 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001380 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001381 const size_t new_len = LengthIncludingRedZones(len);
1382 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001383
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001384 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001385 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001386 if (!mod_okay) {
1387 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001388 }
1389
Ian Rogers68d8b422014-07-17 11:09:10 -07001390 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001391
Ian Rogers68d8b422014-07-17 11:09:10 -07001392 // Fill begin region with canary pattern.
1393 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1394 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1395 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1396 if (kCanary[j] == '\0') {
1397 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001398 } else {
1399 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001400 }
1401 }
1402
1403 // Copy the data in; note "len" could be zero.
1404 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1405
1406 // Fill end region with canary pattern.
1407 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1408 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1409 if (kCanary[j] == '\0') {
1410 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001411 } else {
1412 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001413 }
1414 }
1415
1416 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001417 }
1418
1419 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001420 * Create a guarded copy of a primitive array. Modifications to the copied
1421 * data are allowed. Returns a pointer to the copied data.
1422 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001423 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1424 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001425 ScopedObjectAccess soa(env);
1426
Mathieu Chartier0795f232016-09-27 18:43:30 -07001427 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001428 size_t component_size = a->GetClass()->GetComponentSize();
1429 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001430 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001431 if (is_copy != nullptr) {
1432 *is_copy = JNI_TRUE;
1433 }
1434 return result;
1435 }
1436
1437 /*
1438 * Perform the array "release" operation, which may or may not copy data
1439 * back into the managed heap, and may or may not release the underlying storage.
1440 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001441 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1442 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1443 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001445 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1446 return nullptr;
1447 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001448 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1449 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001450 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001451 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001452 }
1453 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001454 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001455 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001456 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001457 }
1458
1459
1460 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001461 * Free up the guard buffer, scrub it, and return the original pointer.
1462 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001463 static void* Destroy(void* embedded_buf) {
1464 GuardedCopy* copy = FromEmbedded(embedded_buf);
1465 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1466 size_t len = LengthIncludingRedZones(copy->original_length_);
1467 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001468 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001469 }
1470
1471 /*
1472 * Verify the guard area and, if "modOkay" is false, that the data itself
1473 * has not been altered.
1474 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001475 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001476 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001477 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1478 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1479 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001480 }
1481
1482 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001483 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001484 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1485 }
1486
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001487 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001488 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001489 if (result == MAP_FAILED) {
1490 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1491 }
1492 return reinterpret_cast<uint8_t*>(result);
1493 }
1494
Ian Rogers68d8b422014-07-17 11:09:10 -07001495 static void DebugFree(void* buf, size_t len) {
1496 if (munmap(buf, len) != 0) {
1497 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001498 }
1499 }
1500
Ian Rogers68d8b422014-07-17 11:09:10 -07001501 static size_t LengthIncludingRedZones(size_t len) {
1502 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001503 }
1504
Ian Rogers68d8b422014-07-17 11:09:10 -07001505 // Get the GuardedCopy from the interior pointer.
1506 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1507 return reinterpret_cast<GuardedCopy*>(
1508 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001509 }
1510
Ian Rogers68d8b422014-07-17 11:09:10 -07001511 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1512 return reinterpret_cast<const GuardedCopy*>(
1513 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001514 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001515
1516 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1517 va_list args;
1518 va_start(args, fmt);
1519 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1520 va_end(args);
1521 }
1522
1523 bool CheckHeader(const char* function_name, bool mod_okay) const {
1524 static const uint32_t kMagicCmp = kGuardMagic;
1525
1526 // Before we do anything with "pExtra", check the magic number. We
1527 // do the check with memcmp rather than "==" in case the pointer is
1528 // unaligned. If it points to completely bogus memory we're going
1529 // to crash, but there's no easy way around that.
1530 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1531 uint8_t buf[4];
1532 memcpy(buf, &magic_, 4);
1533 AbortF(function_name,
1534 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1535 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1536 return false;
1537 }
1538
1539 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1540 // told the client that we made a copy, there's no reason they can't alter the buffer.
1541 if (!mod_okay) {
1542 uLong computed_adler =
1543 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1544 if (computed_adler != adler_) {
1545 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1546 computed_adler, adler_, this);
1547 return false;
1548 }
1549 }
1550 return true;
1551 }
1552
1553 bool CheckRedZones(const char* function_name) const {
1554 // Check the begin red zone.
1555 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1556 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1557 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1558 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1559 return false;
1560 }
1561 if (kCanary[j] == '\0') {
1562 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001563 } else {
1564 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001565 }
1566 }
1567
1568 // Check end region.
1569 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1570 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1571 size_t offset_from_buffer_start =
1572 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1573 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1574 offset_from_buffer_start);
1575 return false;
1576 }
1577 if (kCanary[j] == '\0') {
1578 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001579 } else {
1580 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001581 }
1582 }
1583 return true;
1584 }
1585
1586 // Location that canary value will be written before the guarded region.
1587 const char* StartRedZone() const {
1588 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1589 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1590 }
1591
1592 // Return the interior embedded buffer.
1593 const uint8_t* BufferWithinRedZones() const {
1594 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1595 return embedded_buf;
1596 }
1597
1598 // Location that canary value will be written after the guarded region.
1599 const char* EndRedZone() const {
1600 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1601 size_t buf_len = LengthIncludingRedZones(original_length_);
1602 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1603 }
1604
1605 static constexpr size_t kRedZoneSize = 512;
1606 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1607
1608 // Value written before and after the guarded array.
1609 static const char* const kCanary;
1610
1611 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1612
1613 const uint32_t magic_;
1614 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001615 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001616 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001617};
Ian Rogers68d8b422014-07-17 11:09:10 -07001618const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001619
1620/*
1621 * ===========================================================================
1622 * JNI functions
1623 * ===========================================================================
1624 */
1625
1626class CheckJNI {
1627 public:
1628 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001629 ScopedObjectAccess soa(env);
1630 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1631 JniValueType args[1] = {{.E = env }};
1632 if (sc.Check(soa, true, "E", args)) {
1633 JniValueType result;
1634 result.I = baseEnv(env)->GetVersion(env);
1635 if (sc.Check(soa, false, "I", &result)) {
1636 return result.I;
1637 }
1638 }
1639 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001640 }
1641
Ian Rogers68d8b422014-07-17 11:09:10 -07001642 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1643 ScopedObjectAccess soa(env);
1644 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1645 JniValueType args[2] = {{.E = env }, {.p = vm}};
1646 if (sc.Check(soa, true, "Ep", args)) {
1647 JniValueType result;
1648 result.i = baseEnv(env)->GetJavaVM(env, vm);
1649 if (sc.Check(soa, false, "i", &result)) {
1650 return result.i;
1651 }
1652 }
1653 return JNI_ERR;
1654 }
1655
1656 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1657 ScopedObjectAccess soa(env);
1658 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1659 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1660 if (sc.Check(soa, true, "EcpI", args)) {
1661 JniValueType result;
1662 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1663 if (sc.Check(soa, false, "i", &result)) {
1664 return result.i;
1665 }
1666 }
1667 return JNI_ERR;
1668 }
1669
1670 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1671 ScopedObjectAccess soa(env);
1672 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1673 JniValueType args[2] = {{.E = env }, {.c = c}};
1674 if (sc.Check(soa, true, "Ec", args)) {
1675 JniValueType result;
1676 result.i = baseEnv(env)->UnregisterNatives(env, c);
1677 if (sc.Check(soa, false, "i", &result)) {
1678 return result.i;
1679 }
1680 }
1681 return JNI_ERR;
1682 }
1683
1684 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001685 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1686 // know the object is invalid. The spec says that passing invalid objects or even ones that
1687 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001688 ScopedObjectAccess soa(env);
1689 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001690 JniValueType args[2] = {{.E = env }, {.L = obj}};
1691 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001692 JniValueType result;
1693 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1694 if (sc.Check(soa, false, "w", &result)) {
1695 return result.w;
1696 }
1697 }
1698 return JNIInvalidRefType;
1699 }
1700
1701 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1702 jsize bufLen) {
1703 ScopedObjectAccess soa(env);
1704 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1705 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1706 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1707 JniValueType result;
1708 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1709 if (sc.Check(soa, false, "c", &result)) {
1710 return result.c;
1711 }
1712 }
1713 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001714 }
1715
1716 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001717 ScopedObjectAccess soa(env);
1718 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1719 JniValueType args[2] = {{.E = env}, {.u = name}};
1720 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1721 JniValueType result;
1722 result.c = baseEnv(env)->FindClass(env, name);
1723 if (sc.Check(soa, false, "c", &result)) {
1724 return result.c;
1725 }
1726 }
1727 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001728 }
1729
Elliott Hughese84278b2012-03-22 10:06:53 -07001730 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001731 ScopedObjectAccess soa(env);
1732 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1733 JniValueType args[2] = {{.E = env}, {.c = c}};
1734 if (sc.Check(soa, true, "Ec", args)) {
1735 JniValueType result;
1736 result.c = baseEnv(env)->GetSuperclass(env, c);
1737 if (sc.Check(soa, false, "c", &result)) {
1738 return result.c;
1739 }
1740 }
1741 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001742 }
1743
Elliott Hughese84278b2012-03-22 10:06:53 -07001744 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001745 ScopedObjectAccess soa(env);
1746 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1747 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1748 if (sc.Check(soa, true, "Ecc", args)) {
1749 JniValueType result;
1750 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1751 if (sc.Check(soa, false, "b", &result)) {
1752 return result.b;
1753 }
1754 }
1755 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001756 }
1757
1758 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001759 ScopedObjectAccess soa(env);
1760 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1761 JniValueType args[2] = {{.E = env}, {.L = method}};
1762 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1763 JniValueType result;
1764 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1765 if (sc.Check(soa, false, "m", &result)) {
1766 return result.m;
1767 }
1768 }
1769 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001770 }
1771
1772 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001773 ScopedObjectAccess soa(env);
1774 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1775 JniValueType args[2] = {{.E = env}, {.L = field}};
1776 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1777 JniValueType result;
1778 result.f = baseEnv(env)->FromReflectedField(env, field);
1779 if (sc.Check(soa, false, "f", &result)) {
1780 return result.f;
1781 }
1782 }
1783 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001784 }
1785
1786 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001787 ScopedObjectAccess soa(env);
1788 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1789 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1790 if (sc.Check(soa, true, "Ecmb", args)) {
1791 JniValueType result;
1792 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1793 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1794 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1795 return result.L;
1796 }
1797 }
1798 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001799 }
1800
1801 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001802 ScopedObjectAccess soa(env);
1803 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1804 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1805 if (sc.Check(soa, true, "Ecfb", args)) {
1806 JniValueType result;
1807 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1808 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1809 DCHECK(sc.CheckReflectedField(soa, result.L));
1810 return result.L;
1811 }
1812 }
1813 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001814 }
1815
1816 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001817 ScopedObjectAccess soa(env);
1818 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1819 JniValueType args[2] = {{.E = env}, {.t = obj}};
1820 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1821 JniValueType result;
1822 result.i = baseEnv(env)->Throw(env, obj);
1823 if (sc.Check(soa, false, "i", &result)) {
1824 return result.i;
1825 }
1826 }
1827 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001828 }
1829
Elliott Hughese84278b2012-03-22 10:06:53 -07001830 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001831 ScopedObjectAccess soa(env);
1832 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001833 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001834 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1835 JniValueType result;
1836 result.i = baseEnv(env)->ThrowNew(env, c, message);
1837 if (sc.Check(soa, false, "i", &result)) {
1838 return result.i;
1839 }
1840 }
1841 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001842 }
1843
1844 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001845 ScopedObjectAccess soa(env);
1846 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1847 JniValueType args[1] = {{.E = env}};
1848 if (sc.Check(soa, true, "E", args)) {
1849 JniValueType result;
1850 result.t = baseEnv(env)->ExceptionOccurred(env);
1851 if (sc.Check(soa, false, "t", &result)) {
1852 return result.t;
1853 }
1854 }
1855 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001856 }
1857
1858 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001859 ScopedObjectAccess soa(env);
1860 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1861 JniValueType args[1] = {{.E = env}};
1862 if (sc.Check(soa, true, "E", args)) {
1863 JniValueType result;
1864 baseEnv(env)->ExceptionDescribe(env);
1865 result.V = nullptr;
1866 sc.Check(soa, false, "V", &result);
1867 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001868 }
1869
1870 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001871 ScopedObjectAccess soa(env);
1872 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1873 JniValueType args[1] = {{.E = env}};
1874 if (sc.Check(soa, true, "E", args)) {
1875 JniValueType result;
1876 baseEnv(env)->ExceptionClear(env);
1877 result.V = nullptr;
1878 sc.Check(soa, false, "V", &result);
1879 }
1880 }
1881
1882 static jboolean ExceptionCheck(JNIEnv* env) {
1883 ScopedObjectAccess soa(env);
1884 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1885 JniValueType args[1] = {{.E = env}};
1886 if (sc.Check(soa, true, "E", args)) {
1887 JniValueType result;
1888 result.b = baseEnv(env)->ExceptionCheck(env);
1889 if (sc.Check(soa, false, "b", &result)) {
1890 return result.b;
1891 }
1892 }
1893 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001894 }
1895
1896 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001897 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1898 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1899 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001900 ScopedObjectAccess soa(env);
1901 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1902 JniValueType args[2] = {{.E = env}, {.u = msg}};
1903 if (sc.Check(soa, true, "Eu", args)) {
1904 JniValueType result;
1905 baseEnv(env)->FatalError(env, msg);
1906 // Unreachable.
1907 result.V = nullptr;
1908 sc.Check(soa, false, "V", &result);
1909 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001910 }
1911
1912 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001913 ScopedObjectAccess soa(env);
1914 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1915 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1916 if (sc.Check(soa, true, "EI", args)) {
1917 JniValueType result;
1918 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1919 if (sc.Check(soa, false, "i", &result)) {
1920 return result.i;
1921 }
1922 }
1923 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001924 }
1925
1926 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001927 ScopedObjectAccess soa(env);
1928 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1929 JniValueType args[2] = {{.E = env}, {.L = res}};
1930 if (sc.Check(soa, true, "EL", args)) {
1931 JniValueType result;
1932 result.L = baseEnv(env)->PopLocalFrame(env, res);
1933 sc.Check(soa, false, "L", &result);
1934 return result.L;
1935 }
1936 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001937 }
1938
1939 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001940 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001941 }
1942
Ian Rogers68d8b422014-07-17 11:09:10 -07001943 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1944 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001945 }
1946
1947 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001948 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001949 }
1950
Ian Rogers68d8b422014-07-17 11:09:10 -07001951 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1952 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001953 }
1954
Ian Rogers68d8b422014-07-17 11:09:10 -07001955 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1956 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1957 }
1958
1959 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1960 DeleteRef(__FUNCTION__, env, obj, kLocal);
1961 }
1962
1963 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1964 ScopedObjectAccess soa(env);
1965 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1966 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1967 if (sc.Check(soa, true, "EI", args)) {
1968 JniValueType result;
1969 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1970 if (sc.Check(soa, false, "i", &result)) {
1971 return result.i;
1972 }
1973 }
1974 return JNI_ERR;
1975 }
1976
1977 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1978 ScopedObjectAccess soa(env);
1979 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1980 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1981 if (sc.Check(soa, true, "ELL", args)) {
1982 JniValueType result;
1983 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1984 if (sc.Check(soa, false, "b", &result)) {
1985 return result.b;
1986 }
1987 }
1988 return JNI_FALSE;
1989 }
1990
1991 static jobject AllocObject(JNIEnv* env, jclass c) {
1992 ScopedObjectAccess soa(env);
1993 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1994 JniValueType args[2] = {{.E = env}, {.c = c}};
1995 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1996 JniValueType result;
1997 result.L = baseEnv(env)->AllocObject(env, c);
1998 if (sc.Check(soa, false, "L", &result)) {
1999 return result.L;
2000 }
2001 }
2002 return nullptr;
2003 }
2004
2005 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2006 ScopedObjectAccess soa(env);
2007 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002008 VarArgs rest(mid, vargs);
2009 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2010 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002011 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002012 JniValueType result;
2013 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2014 if (sc.Check(soa, false, "L", &result)) {
2015 return result.L;
2016 }
2017 }
2018 return nullptr;
2019 }
2020
2021 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2022 va_list args;
2023 va_start(args, mid);
2024 jobject result = NewObjectV(env, c, mid, args);
2025 va_end(args);
2026 return result;
2027 }
2028
2029 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2030 ScopedObjectAccess soa(env);
2031 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002032 VarArgs rest(mid, vargs);
2033 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2034 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002035 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002036 JniValueType result;
2037 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2038 if (sc.Check(soa, false, "L", &result)) {
2039 return result.L;
2040 }
2041 }
2042 return nullptr;
2043 }
2044
2045 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2046 ScopedObjectAccess soa(env);
2047 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2048 JniValueType args[2] = {{.E = env}, {.L = obj}};
2049 if (sc.Check(soa, true, "EL", args)) {
2050 JniValueType result;
2051 result.c = baseEnv(env)->GetObjectClass(env, obj);
2052 if (sc.Check(soa, false, "c", &result)) {
2053 return result.c;
2054 }
2055 }
2056 return nullptr;
2057 }
2058
2059 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2060 ScopedObjectAccess soa(env);
2061 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2062 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2063 if (sc.Check(soa, true, "ELc", args)) {
2064 JniValueType result;
2065 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2066 if (sc.Check(soa, false, "b", &result)) {
2067 return result.b;
2068 }
2069 }
2070 return JNI_FALSE;
2071 }
2072
2073 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2074 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2075 }
2076
2077 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2078 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2079 }
2080
2081 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2082 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2083 }
2084
2085 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2086 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2087 }
2088
2089#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2090 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2091 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2092 } \
2093 \
2094 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2095 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2096 } \
2097 \
2098 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2099 JniValueType value; \
2100 value.shorty = v; \
2101 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2102 } \
2103 \
2104 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2105 JniValueType value; \
2106 value.shorty = v; \
2107 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2108 }
2109
2110 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2111 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2112 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2113 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2114 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2115 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2116 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2117 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2118 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2119#undef FIELD_ACCESSORS
2120
2121 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2122 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2123 }
2124
2125 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2126 jvalue* vargs) {
2127 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2128 }
2129
2130 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002131 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002132 }
2133
2134 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2135 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2136 }
2137
2138 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2139 va_list vargs) {
2140 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2141 }
2142
2143 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2144 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2145 }
2146
2147 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2148 va_list vargs;
2149 va_start(vargs, mid);
2150 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2151 va_end(vargs);
2152 }
2153
2154 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2155 va_list vargs;
2156 va_start(vargs, mid);
2157 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2158 va_end(vargs);
2159 }
2160
2161 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2162 va_list vargs;
2163 va_start(vargs, mid);
2164 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2165 va_end(vargs);
2166 }
2167
2168#define CALL(rtype, name, ptype, shorty) \
2169 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2170 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2171 } \
2172 \
2173 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2174 jvalue* vargs) { \
2175 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2176 } \
2177 \
2178 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2179 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2180 } \
2181 \
2182 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2183 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2184 } \
2185 \
2186 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2187 va_list vargs) { \
2188 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2189 } \
2190 \
2191 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2192 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2193 } \
2194 \
2195 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2196 va_list vargs; \
2197 va_start(vargs, mid); \
2198 rtype result = \
2199 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2200 va_end(vargs); \
2201 return result; \
2202 } \
2203 \
2204 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2205 ...) { \
2206 va_list vargs; \
2207 va_start(vargs, mid); \
2208 rtype result = \
2209 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2210 va_end(vargs); \
2211 return result; \
2212 } \
2213 \
2214 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2215 va_list vargs; \
2216 va_start(vargs, mid); \
2217 rtype result = \
2218 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2219 va_end(vargs); \
2220 return result; \
2221 }
2222
2223 CALL(jobject, Object, Primitive::kPrimNot, L)
2224 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2225 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2226 CALL(jchar, Char, Primitive::kPrimChar, C)
2227 CALL(jshort, Short, Primitive::kPrimShort, S)
2228 CALL(jint, Int, Primitive::kPrimInt, I)
2229 CALL(jlong, Long, Primitive::kPrimLong, J)
2230 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2231 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2232#undef CALL
2233
2234 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2235 ScopedObjectAccess soa(env);
2236 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2237 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2238 if (sc.Check(soa, true, "Epz", args)) {
2239 JniValueType result;
2240 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2241 if (sc.Check(soa, false, "s", &result)) {
2242 return result.s;
2243 }
2244 }
2245 return nullptr;
2246 }
2247
2248 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2249 ScopedObjectAccess soa(env);
2250 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2251 JniValueType args[2] = {{.E = env}, {.u = chars}};
2252 if (sc.Check(soa, true, "Eu", args)) {
2253 JniValueType result;
2254 // TODO: stale? show pointer and truncate string.
2255 result.s = baseEnv(env)->NewStringUTF(env, chars);
2256 if (sc.Check(soa, false, "s", &result)) {
2257 return result.s;
2258 }
2259 }
2260 return nullptr;
2261 }
2262
2263 static jsize GetStringLength(JNIEnv* env, jstring string) {
2264 ScopedObjectAccess soa(env);
2265 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2266 JniValueType args[2] = {{.E = env}, {.s = string}};
2267 if (sc.Check(soa, true, "Es", args)) {
2268 JniValueType result;
2269 result.z = baseEnv(env)->GetStringLength(env, string);
2270 if (sc.Check(soa, false, "z", &result)) {
2271 return result.z;
2272 }
2273 }
2274 return JNI_ERR;
2275 }
2276
2277 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2278 ScopedObjectAccess soa(env);
2279 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2280 JniValueType args[2] = {{.E = env}, {.s = string}};
2281 if (sc.Check(soa, true, "Es", args)) {
2282 JniValueType result;
2283 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2284 if (sc.Check(soa, false, "z", &result)) {
2285 return result.z;
2286 }
2287 }
2288 return JNI_ERR;
2289 }
2290
2291 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2292 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2293 is_copy, false, false));
2294 }
2295
2296 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2297 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2298 is_copy, true, false));
2299 }
2300
2301 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2302 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2303 is_copy, false, true));
2304 }
2305
2306 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2307 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2308 }
2309
2310 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2311 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2312 }
2313
2314 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2315 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2316 }
2317
2318 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2319 ScopedObjectAccess soa(env);
2320 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2321 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2322 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2323 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2324 if (sc.Check(soa, true, "EsIIp", args)) {
2325 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2326 JniValueType result;
2327 result.V = nullptr;
2328 sc.Check(soa, false, "V", &result);
2329 }
2330 }
2331
2332 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2333 ScopedObjectAccess soa(env);
2334 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2335 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2336 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2337 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2338 if (sc.Check(soa, true, "EsIIp", args)) {
2339 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2340 JniValueType result;
2341 result.V = nullptr;
2342 sc.Check(soa, false, "V", &result);
2343 }
2344 }
2345
2346 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2347 ScopedObjectAccess soa(env);
2348 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2349 JniValueType args[2] = {{.E = env}, {.a = array}};
2350 if (sc.Check(soa, true, "Ea", args)) {
2351 JniValueType result;
2352 result.z = baseEnv(env)->GetArrayLength(env, array);
2353 if (sc.Check(soa, false, "z", &result)) {
2354 return result.z;
2355 }
2356 }
2357 return JNI_ERR;
2358 }
2359
2360 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2361 jobject initial_element) {
2362 ScopedObjectAccess soa(env);
2363 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2364 JniValueType args[4] =
2365 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2366 if (sc.Check(soa, true, "EzcL", args)) {
2367 JniValueType result;
2368 // Note: assignability tests of initial_element are done in the base implementation.
2369 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2370 if (sc.Check(soa, false, "a", &result)) {
2371 return down_cast<jobjectArray>(result.a);
2372 }
2373 }
2374 return nullptr;
2375 }
2376
2377 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2378 ScopedObjectAccess soa(env);
2379 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2380 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2381 if (sc.Check(soa, true, "Eaz", args)) {
2382 JniValueType result;
2383 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2384 if (sc.Check(soa, false, "L", &result)) {
2385 return result.L;
2386 }
2387 }
2388 return nullptr;
2389 }
2390
2391 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2392 ScopedObjectAccess soa(env);
2393 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2394 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2395 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2396 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2397 // in ArrayStoreExceptions.
2398 if (sc.Check(soa, true, "EaIL", args)) {
2399 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2400 JniValueType result;
2401 result.V = nullptr;
2402 sc.Check(soa, false, "V", &result);
2403 }
2404 }
2405
2406 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2407 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2408 Primitive::kPrimBoolean));
2409 }
2410
2411 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2412 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2413 Primitive::kPrimByte));
2414 }
2415
2416 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2417 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2418 Primitive::kPrimChar));
2419 }
2420
2421 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2422 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2423 Primitive::kPrimShort));
2424 }
2425
2426 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2427 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2428 }
2429
2430 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2431 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2432 Primitive::kPrimLong));
2433 }
2434
2435 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2436 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2437 Primitive::kPrimFloat));
2438 }
2439
2440 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2441 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2442 Primitive::kPrimDouble));
2443 }
2444
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002445// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002446#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002447 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2448 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002449 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2450 } \
2451 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002452 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002453 jint mode) { \
2454 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2455 } \
2456 \
2457 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002458 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002459 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2460 } \
2461 \
2462 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2463 const ctype* buf) { \
2464 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2465 }
2466
2467 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2468 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2469 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2470 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2471 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2472 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2473 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2474 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2475#undef PRIMITIVE_ARRAY_FUNCTIONS
2476
2477 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2478 ScopedObjectAccess soa(env);
2479 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2480 JniValueType args[2] = {{.E = env}, {.L = obj}};
2481 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002482 if (obj != nullptr) {
2483 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2484 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002485 JniValueType result;
2486 result.i = baseEnv(env)->MonitorEnter(env, obj);
2487 if (sc.Check(soa, false, "i", &result)) {
2488 return result.i;
2489 }
2490 }
2491 return JNI_ERR;
2492 }
2493
2494 static jint MonitorExit(JNIEnv* env, jobject obj) {
2495 ScopedObjectAccess soa(env);
2496 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2497 JniValueType args[2] = {{.E = env}, {.L = obj}};
2498 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002499 if (obj != nullptr) {
2500 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2501 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002502 JniValueType result;
2503 result.i = baseEnv(env)->MonitorExit(env, obj);
2504 if (sc.Check(soa, false, "i", &result)) {
2505 return result.i;
2506 }
2507 }
2508 return JNI_ERR;
2509 }
2510
2511 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2512 ScopedObjectAccess soa(env);
2513 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2514 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2515 if (sc.Check(soa, true, "Eap", args)) {
2516 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002517 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2518 if (ptr != nullptr && soa.ForceCopy()) {
2519 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002520 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002521 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002522 if (sc.Check(soa, false, "p", &result)) {
2523 return const_cast<void*>(result.p);
2524 }
2525 }
2526 return nullptr;
2527 }
2528
2529 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2530 ScopedObjectAccess soa(env);
2531 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2532 sc.CheckNonNull(carray);
2533 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2534 if (sc.Check(soa, true, "Eapr", args)) {
2535 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002536 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002537 }
2538 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2539 JniValueType result;
2540 result.V = nullptr;
2541 sc.Check(soa, false, "V", &result);
2542 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002543 }
2544
2545 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002546 ScopedObjectAccess soa(env);
2547 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2548 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2549 if (sc.Check(soa, true, "EpJ", args)) {
2550 JniValueType result;
2551 // Note: the validity of address and capacity are checked in the base implementation.
2552 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2553 if (sc.Check(soa, false, "L", &result)) {
2554 return result.L;
2555 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002556 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002557 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002558 }
2559
2560 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002561 ScopedObjectAccess soa(env);
2562 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2563 JniValueType args[2] = {{.E = env}, {.L = buf}};
2564 if (sc.Check(soa, true, "EL", args)) {
2565 JniValueType result;
2566 // Note: this is implemented in the base environment by a GetLongField which will sanity
2567 // check the type of buf in GetLongField above.
2568 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2569 if (sc.Check(soa, false, "p", &result)) {
2570 return const_cast<void*>(result.p);
2571 }
2572 }
2573 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002574 }
2575
2576 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002577 ScopedObjectAccess soa(env);
2578 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2579 JniValueType args[2] = {{.E = env}, {.L = buf}};
2580 if (sc.Check(soa, true, "EL", args)) {
2581 JniValueType result;
2582 // Note: this is implemented in the base environment by a GetIntField which will sanity
2583 // check the type of buf in GetIntField above.
2584 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2585 if (sc.Check(soa, false, "J", &result)) {
2586 return result.J;
2587 }
2588 }
2589 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002590 }
2591
2592 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002593 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2594 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2595 }
2596
2597 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002598 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2599 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002600
2601 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2602 ScopedObjectAccess soa(env);
2603 ScopedCheck sc(kFlag_Default, function_name);
2604 JniValueType args[2] = {{.E = env}, {.L = obj}};
2605 if (sc.Check(soa, true, "EL", args)) {
2606 JniValueType result;
2607 switch (kind) {
2608 case kGlobal:
2609 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2610 break;
2611 case kLocal:
2612 result.L = baseEnv(env)->NewLocalRef(env, obj);
2613 break;
2614 case kWeakGlobal:
2615 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2616 break;
2617 default:
2618 LOG(FATAL) << "Unexpected reference kind: " << kind;
2619 }
2620 if (sc.Check(soa, false, "L", &result)) {
2621 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002622 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002623 return result.L;
2624 }
2625 }
2626 return nullptr;
2627 }
2628
2629 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2630 ScopedObjectAccess soa(env);
2631 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2632 JniValueType args[2] = {{.E = env}, {.L = obj}};
2633 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002634 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002635 JniValueType result;
2636 switch (kind) {
2637 case kGlobal:
2638 baseEnv(env)->DeleteGlobalRef(env, obj);
2639 break;
2640 case kLocal:
2641 baseEnv(env)->DeleteLocalRef(env, obj);
2642 break;
2643 case kWeakGlobal:
2644 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2645 break;
2646 default:
2647 LOG(FATAL) << "Unexpected reference kind: " << kind;
2648 }
2649 result.V = nullptr;
2650 sc.Check(soa, false, "V", &result);
2651 }
2652 }
2653
2654 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2655 const char* name, const char* sig, bool is_static) {
2656 ScopedObjectAccess soa(env);
2657 ScopedCheck sc(kFlag_Default, function_name);
2658 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2659 if (sc.Check(soa, true, "Ecuu", args)) {
2660 JniValueType result;
2661 if (is_static) {
2662 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2663 } else {
2664 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2665 }
2666 if (sc.Check(soa, false, "m", &result)) {
2667 return result.m;
2668 }
2669 }
2670 return nullptr;
2671 }
2672
2673 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2674 const char* name, const char* sig, bool is_static) {
2675 ScopedObjectAccess soa(env);
2676 ScopedCheck sc(kFlag_Default, function_name);
2677 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2678 if (sc.Check(soa, true, "Ecuu", args)) {
2679 JniValueType result;
2680 if (is_static) {
2681 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2682 } else {
2683 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2684 }
2685 if (sc.Check(soa, false, "f", &result)) {
2686 return result.f;
2687 }
2688 }
2689 return nullptr;
2690 }
2691
2692 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2693 bool is_static, Primitive::Type type) {
2694 ScopedObjectAccess soa(env);
2695 ScopedCheck sc(kFlag_Default, function_name);
2696 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2697 JniValueType result;
2698 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2699 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2700 const char* result_check = nullptr;
2701 switch (type) {
2702 case Primitive::kPrimNot:
2703 if (is_static) {
2704 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2705 } else {
2706 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2707 }
2708 result_check = "L";
2709 break;
2710 case Primitive::kPrimBoolean:
2711 if (is_static) {
2712 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2713 } else {
2714 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2715 }
2716 result_check = "Z";
2717 break;
2718 case Primitive::kPrimByte:
2719 if (is_static) {
2720 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2721 } else {
2722 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2723 }
2724 result_check = "B";
2725 break;
2726 case Primitive::kPrimChar:
2727 if (is_static) {
2728 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2729 } else {
2730 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2731 }
2732 result_check = "C";
2733 break;
2734 case Primitive::kPrimShort:
2735 if (is_static) {
2736 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2737 } else {
2738 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2739 }
2740 result_check = "S";
2741 break;
2742 case Primitive::kPrimInt:
2743 if (is_static) {
2744 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2745 } else {
2746 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2747 }
2748 result_check = "I";
2749 break;
2750 case Primitive::kPrimLong:
2751 if (is_static) {
2752 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2753 } else {
2754 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2755 }
2756 result_check = "J";
2757 break;
2758 case Primitive::kPrimFloat:
2759 if (is_static) {
2760 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2761 } else {
2762 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2763 }
2764 result_check = "F";
2765 break;
2766 case Primitive::kPrimDouble:
2767 if (is_static) {
2768 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2769 } else {
2770 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2771 }
2772 result_check = "D";
2773 break;
2774 case Primitive::kPrimVoid:
2775 LOG(FATAL) << "Unexpected type: " << type;
2776 break;
2777 }
2778 if (sc.Check(soa, false, result_check, &result)) {
2779 return result;
2780 }
2781 }
2782 result.J = 0;
2783 return result;
2784 }
2785
2786 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2787 bool is_static, Primitive::Type type, JniValueType value) {
2788 ScopedObjectAccess soa(env);
2789 ScopedCheck sc(kFlag_Default, function_name);
2790 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2791 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2792 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2793 if (sc.Check(soa, true, sig, args) &&
2794 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2795 switch (type) {
2796 case Primitive::kPrimNot:
2797 if (is_static) {
2798 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2799 } else {
2800 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2801 }
2802 break;
2803 case Primitive::kPrimBoolean:
2804 if (is_static) {
2805 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2806 } else {
2807 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2808 }
2809 break;
2810 case Primitive::kPrimByte:
2811 if (is_static) {
2812 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2813 } else {
2814 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2815 }
2816 break;
2817 case Primitive::kPrimChar:
2818 if (is_static) {
2819 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2820 } else {
2821 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2822 }
2823 break;
2824 case Primitive::kPrimShort:
2825 if (is_static) {
2826 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2827 } else {
2828 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2829 }
2830 break;
2831 case Primitive::kPrimInt:
2832 if (is_static) {
2833 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2834 } else {
2835 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2836 }
2837 break;
2838 case Primitive::kPrimLong:
2839 if (is_static) {
2840 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2841 } else {
2842 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2843 }
2844 break;
2845 case Primitive::kPrimFloat:
2846 if (is_static) {
2847 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2848 } else {
2849 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2850 }
2851 break;
2852 case Primitive::kPrimDouble:
2853 if (is_static) {
2854 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2855 } else {
2856 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2857 }
2858 break;
2859 case Primitive::kPrimVoid:
2860 LOG(FATAL) << "Unexpected type: " << type;
2861 break;
2862 }
2863 JniValueType result;
2864 result.V = nullptr;
2865 sc.Check(soa, false, "V", &result);
2866 }
2867 }
2868
2869 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002870 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002871 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002872 bool checked;
2873 switch (invoke) {
2874 case kVirtual: {
2875 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002876 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2877 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002878 break;
2879 }
2880 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002881 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2882 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002883 break;
2884 }
2885 case kStatic: {
2886 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002887 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2888 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002889 break;
2890 }
2891 default:
2892 LOG(FATAL) << "Unexpected invoke: " << invoke;
2893 checked = false;
2894 break;
2895 }
2896 return checked;
2897 }
2898
2899 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2900 jmethodID mid, jvalue* vargs, Primitive::Type type,
2901 InvokeType invoke) {
2902 ScopedObjectAccess soa(env);
2903 ScopedCheck sc(kFlag_Default, function_name);
2904 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002905 VarArgs rest(mid, vargs);
2906 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002907 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2908 const char* result_check;
2909 switch (type) {
2910 case Primitive::kPrimNot:
2911 result_check = "L";
2912 switch (invoke) {
2913 case kVirtual:
2914 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2915 break;
2916 case kDirect:
2917 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2918 break;
2919 case kStatic:
2920 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2921 break;
2922 default:
2923 break;
2924 }
2925 break;
2926 case Primitive::kPrimBoolean:
2927 result_check = "Z";
2928 switch (invoke) {
2929 case kVirtual:
2930 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2931 break;
2932 case kDirect:
2933 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2934 break;
2935 case kStatic:
2936 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2937 break;
2938 default:
2939 break;
2940 }
2941 break;
2942 case Primitive::kPrimByte:
2943 result_check = "B";
2944 switch (invoke) {
2945 case kVirtual:
2946 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2947 break;
2948 case kDirect:
2949 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2950 break;
2951 case kStatic:
2952 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2953 break;
2954 default:
2955 break;
2956 }
2957 break;
2958 case Primitive::kPrimChar:
2959 result_check = "C";
2960 switch (invoke) {
2961 case kVirtual:
2962 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2963 break;
2964 case kDirect:
2965 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2966 break;
2967 case kStatic:
2968 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2969 break;
2970 default:
2971 break;
2972 }
2973 break;
2974 case Primitive::kPrimShort:
2975 result_check = "S";
2976 switch (invoke) {
2977 case kVirtual:
2978 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2979 break;
2980 case kDirect:
2981 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2982 break;
2983 case kStatic:
2984 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2985 break;
2986 default:
2987 break;
2988 }
2989 break;
2990 case Primitive::kPrimInt:
2991 result_check = "I";
2992 switch (invoke) {
2993 case kVirtual:
2994 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2995 break;
2996 case kDirect:
2997 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2998 break;
2999 case kStatic:
3000 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3001 break;
3002 default:
3003 break;
3004 }
3005 break;
3006 case Primitive::kPrimLong:
3007 result_check = "J";
3008 switch (invoke) {
3009 case kVirtual:
3010 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3011 break;
3012 case kDirect:
3013 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3014 break;
3015 case kStatic:
3016 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3017 break;
3018 default:
3019 break;
3020 }
3021 break;
3022 case Primitive::kPrimFloat:
3023 result_check = "F";
3024 switch (invoke) {
3025 case kVirtual:
3026 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3027 break;
3028 case kDirect:
3029 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3030 break;
3031 case kStatic:
3032 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3033 break;
3034 default:
3035 break;
3036 }
3037 break;
3038 case Primitive::kPrimDouble:
3039 result_check = "D";
3040 switch (invoke) {
3041 case kVirtual:
3042 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3043 break;
3044 case kDirect:
3045 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3046 break;
3047 case kStatic:
3048 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3049 break;
3050 default:
3051 break;
3052 }
3053 break;
3054 case Primitive::kPrimVoid:
3055 result_check = "V";
3056 result.V = nullptr;
3057 switch (invoke) {
3058 case kVirtual:
3059 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3060 break;
3061 case kDirect:
3062 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3063 break;
3064 case kStatic:
3065 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3066 break;
3067 default:
3068 LOG(FATAL) << "Unexpected invoke: " << invoke;
3069 }
3070 break;
3071 default:
3072 LOG(FATAL) << "Unexpected return type: " << type;
3073 result_check = nullptr;
3074 }
3075 if (sc.Check(soa, false, result_check, &result)) {
3076 return result;
3077 }
3078 }
3079 result.J = 0;
3080 return result;
3081 }
3082
3083 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3084 jmethodID mid, va_list vargs, Primitive::Type type,
3085 InvokeType invoke) {
3086 ScopedObjectAccess soa(env);
3087 ScopedCheck sc(kFlag_Default, function_name);
3088 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003089 VarArgs rest(mid, vargs);
3090 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003091 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3092 const char* result_check;
3093 switch (type) {
3094 case Primitive::kPrimNot:
3095 result_check = "L";
3096 switch (invoke) {
3097 case kVirtual:
3098 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3099 break;
3100 case kDirect:
3101 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3102 break;
3103 case kStatic:
3104 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3105 break;
3106 default:
3107 LOG(FATAL) << "Unexpected invoke: " << invoke;
3108 }
3109 break;
3110 case Primitive::kPrimBoolean:
3111 result_check = "Z";
3112 switch (invoke) {
3113 case kVirtual:
3114 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3115 break;
3116 case kDirect:
3117 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3118 break;
3119 case kStatic:
3120 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3121 break;
3122 default:
3123 LOG(FATAL) << "Unexpected invoke: " << invoke;
3124 }
3125 break;
3126 case Primitive::kPrimByte:
3127 result_check = "B";
3128 switch (invoke) {
3129 case kVirtual:
3130 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3131 break;
3132 case kDirect:
3133 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3134 break;
3135 case kStatic:
3136 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3137 break;
3138 default:
3139 LOG(FATAL) << "Unexpected invoke: " << invoke;
3140 }
3141 break;
3142 case Primitive::kPrimChar:
3143 result_check = "C";
3144 switch (invoke) {
3145 case kVirtual:
3146 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3147 break;
3148 case kDirect:
3149 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3150 break;
3151 case kStatic:
3152 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3153 break;
3154 default:
3155 LOG(FATAL) << "Unexpected invoke: " << invoke;
3156 }
3157 break;
3158 case Primitive::kPrimShort:
3159 result_check = "S";
3160 switch (invoke) {
3161 case kVirtual:
3162 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3163 break;
3164 case kDirect:
3165 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3166 break;
3167 case kStatic:
3168 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3169 break;
3170 default:
3171 LOG(FATAL) << "Unexpected invoke: " << invoke;
3172 }
3173 break;
3174 case Primitive::kPrimInt:
3175 result_check = "I";
3176 switch (invoke) {
3177 case kVirtual:
3178 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3179 break;
3180 case kDirect:
3181 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3182 break;
3183 case kStatic:
3184 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3185 break;
3186 default:
3187 LOG(FATAL) << "Unexpected invoke: " << invoke;
3188 }
3189 break;
3190 case Primitive::kPrimLong:
3191 result_check = "J";
3192 switch (invoke) {
3193 case kVirtual:
3194 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3195 break;
3196 case kDirect:
3197 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3198 break;
3199 case kStatic:
3200 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3201 break;
3202 default:
3203 LOG(FATAL) << "Unexpected invoke: " << invoke;
3204 }
3205 break;
3206 case Primitive::kPrimFloat:
3207 result_check = "F";
3208 switch (invoke) {
3209 case kVirtual:
3210 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3211 break;
3212 case kDirect:
3213 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3214 break;
3215 case kStatic:
3216 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3217 break;
3218 default:
3219 LOG(FATAL) << "Unexpected invoke: " << invoke;
3220 }
3221 break;
3222 case Primitive::kPrimDouble:
3223 result_check = "D";
3224 switch (invoke) {
3225 case kVirtual:
3226 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3227 break;
3228 case kDirect:
3229 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3230 break;
3231 case kStatic:
3232 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3233 break;
3234 default:
3235 LOG(FATAL) << "Unexpected invoke: " << invoke;
3236 }
3237 break;
3238 case Primitive::kPrimVoid:
3239 result_check = "V";
3240 result.V = nullptr;
3241 switch (invoke) {
3242 case kVirtual:
3243 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3244 break;
3245 case kDirect:
3246 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3247 break;
3248 case kStatic:
3249 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3250 break;
3251 default:
3252 LOG(FATAL) << "Unexpected invoke: " << invoke;
3253 }
3254 break;
3255 default:
3256 LOG(FATAL) << "Unexpected return type: " << type;
3257 result_check = nullptr;
3258 }
3259 if (sc.Check(soa, false, result_check, &result)) {
3260 return result;
3261 }
3262 }
3263 result.J = 0;
3264 return result;
3265 }
3266
3267 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3268 jboolean* is_copy, bool utf, bool critical) {
3269 ScopedObjectAccess soa(env);
3270 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3271 ScopedCheck sc(flags, function_name);
3272 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3273 if (sc.Check(soa, true, "Esp", args)) {
3274 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003275 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003276 if (utf) {
3277 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003278 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3279 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003280 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003281 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3282 baseEnv(env)->GetStringChars(env, string, is_copy));
3283 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003284 }
3285 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003286 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003287 if (utf) {
3288 size_t length_in_bytes = strlen(result.u) + 1;
3289 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003290 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003291 } else {
3292 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3293 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003294 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003295 }
3296 if (is_copy != nullptr) {
3297 *is_copy = JNI_TRUE;
3298 }
3299 }
3300 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3301 return utf ? result.u : result.p;
3302 }
3303 }
3304 return nullptr;
3305 }
3306
3307 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3308 const void* chars, bool utf, bool critical) {
3309 ScopedObjectAccess soa(env);
3310 int flags = kFlag_ExcepOkay | kFlag_Release;
3311 if (critical) {
3312 flags |= kFlag_CritRelease;
3313 }
3314 ScopedCheck sc(flags, function_name);
3315 sc.CheckNonNull(chars);
3316 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3317 if (force_copy_ok && soa.ForceCopy()) {
3318 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3319 }
3320 if (force_copy_ok) {
3321 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3322 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3323 if (utf) {
3324 CHECK(!critical);
3325 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3326 } else {
3327 if (critical) {
3328 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3329 } else {
3330 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3331 }
3332 }
3333 JniValueType result;
3334 sc.Check(soa, false, "V", &result);
3335 }
3336 }
3337 }
3338
3339 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3340 Primitive::Type type) {
3341 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003342 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003343 JniValueType args[2] = {{.E = env}, {.z = length}};
3344 if (sc.Check(soa, true, "Ez", args)) {
3345 JniValueType result;
3346 switch (type) {
3347 case Primitive::kPrimBoolean:
3348 result.a = baseEnv(env)->NewBooleanArray(env, length);
3349 break;
3350 case Primitive::kPrimByte:
3351 result.a = baseEnv(env)->NewByteArray(env, length);
3352 break;
3353 case Primitive::kPrimChar:
3354 result.a = baseEnv(env)->NewCharArray(env, length);
3355 break;
3356 case Primitive::kPrimShort:
3357 result.a = baseEnv(env)->NewShortArray(env, length);
3358 break;
3359 case Primitive::kPrimInt:
3360 result.a = baseEnv(env)->NewIntArray(env, length);
3361 break;
3362 case Primitive::kPrimLong:
3363 result.a = baseEnv(env)->NewLongArray(env, length);
3364 break;
3365 case Primitive::kPrimFloat:
3366 result.a = baseEnv(env)->NewFloatArray(env, length);
3367 break;
3368 case Primitive::kPrimDouble:
3369 result.a = baseEnv(env)->NewDoubleArray(env, length);
3370 break;
3371 default:
3372 LOG(FATAL) << "Unexpected primitive type: " << type;
3373 }
3374 if (sc.Check(soa, false, "a", &result)) {
3375 return result.a;
3376 }
3377 }
3378 return nullptr;
3379 }
3380
3381 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3382 JNIEnv* env, jarray array, jboolean* is_copy) {
3383 ScopedObjectAccess soa(env);
3384 ScopedCheck sc(kFlag_Default, function_name);
3385 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3386 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3387 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003388 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003389 switch (type) {
3390 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003391 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3392 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003393 break;
3394 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003395 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003396 break;
3397 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003398 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003399 break;
3400 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003401 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003402 break;
3403 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003404 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003405 break;
3406 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003407 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003408 break;
3409 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003410 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003411 break;
3412 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003413 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003414 break;
3415 default:
3416 LOG(FATAL) << "Unexpected primitive type: " << type;
3417 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003418 if (ptr != nullptr && soa.ForceCopy()) {
3419 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003420 if (is_copy != nullptr) {
3421 *is_copy = JNI_TRUE;
3422 }
3423 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003424 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003425 if (sc.Check(soa, false, "p", &result)) {
3426 return const_cast<void*>(result.p);
3427 }
3428 }
3429 return nullptr;
3430 }
3431
3432 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3433 JNIEnv* env, jarray array, void* elems, jint mode) {
3434 ScopedObjectAccess soa(env);
3435 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3436 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3437 if (soa.ForceCopy()) {
3438 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3439 }
3440 if (!soa.ForceCopy() || elems != nullptr) {
3441 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3442 if (sc.Check(soa, true, "Eapr", args)) {
3443 switch (type) {
3444 case Primitive::kPrimBoolean:
3445 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3446 reinterpret_cast<jboolean*>(elems), mode);
3447 break;
3448 case Primitive::kPrimByte:
3449 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3450 reinterpret_cast<jbyte*>(elems), mode);
3451 break;
3452 case Primitive::kPrimChar:
3453 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3454 reinterpret_cast<jchar*>(elems), mode);
3455 break;
3456 case Primitive::kPrimShort:
3457 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3458 reinterpret_cast<jshort*>(elems), mode);
3459 break;
3460 case Primitive::kPrimInt:
3461 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3462 reinterpret_cast<jint*>(elems), mode);
3463 break;
3464 case Primitive::kPrimLong:
3465 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3466 reinterpret_cast<jlong*>(elems), mode);
3467 break;
3468 case Primitive::kPrimFloat:
3469 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3470 reinterpret_cast<jfloat*>(elems), mode);
3471 break;
3472 case Primitive::kPrimDouble:
3473 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3474 reinterpret_cast<jdouble*>(elems), mode);
3475 break;
3476 default:
3477 LOG(FATAL) << "Unexpected primitive type: " << type;
3478 }
3479 JniValueType result;
3480 result.V = nullptr;
3481 sc.Check(soa, false, "V", &result);
3482 }
3483 }
3484 }
3485 }
3486
3487 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3488 jarray array, jsize start, jsize len, void* buf) {
3489 ScopedObjectAccess soa(env);
3490 ScopedCheck sc(kFlag_Default, function_name);
3491 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3492 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3493 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3494 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3495 switch (type) {
3496 case Primitive::kPrimBoolean:
3497 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3498 reinterpret_cast<jboolean*>(buf));
3499 break;
3500 case Primitive::kPrimByte:
3501 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3502 reinterpret_cast<jbyte*>(buf));
3503 break;
3504 case Primitive::kPrimChar:
3505 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3506 reinterpret_cast<jchar*>(buf));
3507 break;
3508 case Primitive::kPrimShort:
3509 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3510 reinterpret_cast<jshort*>(buf));
3511 break;
3512 case Primitive::kPrimInt:
3513 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3514 reinterpret_cast<jint*>(buf));
3515 break;
3516 case Primitive::kPrimLong:
3517 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3518 reinterpret_cast<jlong*>(buf));
3519 break;
3520 case Primitive::kPrimFloat:
3521 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3522 reinterpret_cast<jfloat*>(buf));
3523 break;
3524 case Primitive::kPrimDouble:
3525 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3526 reinterpret_cast<jdouble*>(buf));
3527 break;
3528 default:
3529 LOG(FATAL) << "Unexpected primitive type: " << type;
3530 }
3531 JniValueType result;
3532 result.V = nullptr;
3533 sc.Check(soa, false, "V", &result);
3534 }
3535 }
3536
3537 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3538 jarray array, jsize start, jsize len, const void* buf) {
3539 ScopedObjectAccess soa(env);
3540 ScopedCheck sc(kFlag_Default, function_name);
3541 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3542 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3543 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3544 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3545 switch (type) {
3546 case Primitive::kPrimBoolean:
3547 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3548 reinterpret_cast<const jboolean*>(buf));
3549 break;
3550 case Primitive::kPrimByte:
3551 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3552 reinterpret_cast<const jbyte*>(buf));
3553 break;
3554 case Primitive::kPrimChar:
3555 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3556 reinterpret_cast<const jchar*>(buf));
3557 break;
3558 case Primitive::kPrimShort:
3559 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3560 reinterpret_cast<const jshort*>(buf));
3561 break;
3562 case Primitive::kPrimInt:
3563 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3564 reinterpret_cast<const jint*>(buf));
3565 break;
3566 case Primitive::kPrimLong:
3567 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3568 reinterpret_cast<const jlong*>(buf));
3569 break;
3570 case Primitive::kPrimFloat:
3571 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3572 reinterpret_cast<const jfloat*>(buf));
3573 break;
3574 case Primitive::kPrimDouble:
3575 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3576 reinterpret_cast<const jdouble*>(buf));
3577 break;
3578 default:
3579 LOG(FATAL) << "Unexpected primitive type: " << type;
3580 }
3581 JniValueType result;
3582 result.V = nullptr;
3583 sc.Check(soa, false, "V", &result);
3584 }
3585 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003586};
3587
3588const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003589 nullptr, // reserved0.
3590 nullptr, // reserved1.
3591 nullptr, // reserved2.
3592 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003593 CheckJNI::GetVersion,
3594 CheckJNI::DefineClass,
3595 CheckJNI::FindClass,
3596 CheckJNI::FromReflectedMethod,
3597 CheckJNI::FromReflectedField,
3598 CheckJNI::ToReflectedMethod,
3599 CheckJNI::GetSuperclass,
3600 CheckJNI::IsAssignableFrom,
3601 CheckJNI::ToReflectedField,
3602 CheckJNI::Throw,
3603 CheckJNI::ThrowNew,
3604 CheckJNI::ExceptionOccurred,
3605 CheckJNI::ExceptionDescribe,
3606 CheckJNI::ExceptionClear,
3607 CheckJNI::FatalError,
3608 CheckJNI::PushLocalFrame,
3609 CheckJNI::PopLocalFrame,
3610 CheckJNI::NewGlobalRef,
3611 CheckJNI::DeleteGlobalRef,
3612 CheckJNI::DeleteLocalRef,
3613 CheckJNI::IsSameObject,
3614 CheckJNI::NewLocalRef,
3615 CheckJNI::EnsureLocalCapacity,
3616 CheckJNI::AllocObject,
3617 CheckJNI::NewObject,
3618 CheckJNI::NewObjectV,
3619 CheckJNI::NewObjectA,
3620 CheckJNI::GetObjectClass,
3621 CheckJNI::IsInstanceOf,
3622 CheckJNI::GetMethodID,
3623 CheckJNI::CallObjectMethod,
3624 CheckJNI::CallObjectMethodV,
3625 CheckJNI::CallObjectMethodA,
3626 CheckJNI::CallBooleanMethod,
3627 CheckJNI::CallBooleanMethodV,
3628 CheckJNI::CallBooleanMethodA,
3629 CheckJNI::CallByteMethod,
3630 CheckJNI::CallByteMethodV,
3631 CheckJNI::CallByteMethodA,
3632 CheckJNI::CallCharMethod,
3633 CheckJNI::CallCharMethodV,
3634 CheckJNI::CallCharMethodA,
3635 CheckJNI::CallShortMethod,
3636 CheckJNI::CallShortMethodV,
3637 CheckJNI::CallShortMethodA,
3638 CheckJNI::CallIntMethod,
3639 CheckJNI::CallIntMethodV,
3640 CheckJNI::CallIntMethodA,
3641 CheckJNI::CallLongMethod,
3642 CheckJNI::CallLongMethodV,
3643 CheckJNI::CallLongMethodA,
3644 CheckJNI::CallFloatMethod,
3645 CheckJNI::CallFloatMethodV,
3646 CheckJNI::CallFloatMethodA,
3647 CheckJNI::CallDoubleMethod,
3648 CheckJNI::CallDoubleMethodV,
3649 CheckJNI::CallDoubleMethodA,
3650 CheckJNI::CallVoidMethod,
3651 CheckJNI::CallVoidMethodV,
3652 CheckJNI::CallVoidMethodA,
3653 CheckJNI::CallNonvirtualObjectMethod,
3654 CheckJNI::CallNonvirtualObjectMethodV,
3655 CheckJNI::CallNonvirtualObjectMethodA,
3656 CheckJNI::CallNonvirtualBooleanMethod,
3657 CheckJNI::CallNonvirtualBooleanMethodV,
3658 CheckJNI::CallNonvirtualBooleanMethodA,
3659 CheckJNI::CallNonvirtualByteMethod,
3660 CheckJNI::CallNonvirtualByteMethodV,
3661 CheckJNI::CallNonvirtualByteMethodA,
3662 CheckJNI::CallNonvirtualCharMethod,
3663 CheckJNI::CallNonvirtualCharMethodV,
3664 CheckJNI::CallNonvirtualCharMethodA,
3665 CheckJNI::CallNonvirtualShortMethod,
3666 CheckJNI::CallNonvirtualShortMethodV,
3667 CheckJNI::CallNonvirtualShortMethodA,
3668 CheckJNI::CallNonvirtualIntMethod,
3669 CheckJNI::CallNonvirtualIntMethodV,
3670 CheckJNI::CallNonvirtualIntMethodA,
3671 CheckJNI::CallNonvirtualLongMethod,
3672 CheckJNI::CallNonvirtualLongMethodV,
3673 CheckJNI::CallNonvirtualLongMethodA,
3674 CheckJNI::CallNonvirtualFloatMethod,
3675 CheckJNI::CallNonvirtualFloatMethodV,
3676 CheckJNI::CallNonvirtualFloatMethodA,
3677 CheckJNI::CallNonvirtualDoubleMethod,
3678 CheckJNI::CallNonvirtualDoubleMethodV,
3679 CheckJNI::CallNonvirtualDoubleMethodA,
3680 CheckJNI::CallNonvirtualVoidMethod,
3681 CheckJNI::CallNonvirtualVoidMethodV,
3682 CheckJNI::CallNonvirtualVoidMethodA,
3683 CheckJNI::GetFieldID,
3684 CheckJNI::GetObjectField,
3685 CheckJNI::GetBooleanField,
3686 CheckJNI::GetByteField,
3687 CheckJNI::GetCharField,
3688 CheckJNI::GetShortField,
3689 CheckJNI::GetIntField,
3690 CheckJNI::GetLongField,
3691 CheckJNI::GetFloatField,
3692 CheckJNI::GetDoubleField,
3693 CheckJNI::SetObjectField,
3694 CheckJNI::SetBooleanField,
3695 CheckJNI::SetByteField,
3696 CheckJNI::SetCharField,
3697 CheckJNI::SetShortField,
3698 CheckJNI::SetIntField,
3699 CheckJNI::SetLongField,
3700 CheckJNI::SetFloatField,
3701 CheckJNI::SetDoubleField,
3702 CheckJNI::GetStaticMethodID,
3703 CheckJNI::CallStaticObjectMethod,
3704 CheckJNI::CallStaticObjectMethodV,
3705 CheckJNI::CallStaticObjectMethodA,
3706 CheckJNI::CallStaticBooleanMethod,
3707 CheckJNI::CallStaticBooleanMethodV,
3708 CheckJNI::CallStaticBooleanMethodA,
3709 CheckJNI::CallStaticByteMethod,
3710 CheckJNI::CallStaticByteMethodV,
3711 CheckJNI::CallStaticByteMethodA,
3712 CheckJNI::CallStaticCharMethod,
3713 CheckJNI::CallStaticCharMethodV,
3714 CheckJNI::CallStaticCharMethodA,
3715 CheckJNI::CallStaticShortMethod,
3716 CheckJNI::CallStaticShortMethodV,
3717 CheckJNI::CallStaticShortMethodA,
3718 CheckJNI::CallStaticIntMethod,
3719 CheckJNI::CallStaticIntMethodV,
3720 CheckJNI::CallStaticIntMethodA,
3721 CheckJNI::CallStaticLongMethod,
3722 CheckJNI::CallStaticLongMethodV,
3723 CheckJNI::CallStaticLongMethodA,
3724 CheckJNI::CallStaticFloatMethod,
3725 CheckJNI::CallStaticFloatMethodV,
3726 CheckJNI::CallStaticFloatMethodA,
3727 CheckJNI::CallStaticDoubleMethod,
3728 CheckJNI::CallStaticDoubleMethodV,
3729 CheckJNI::CallStaticDoubleMethodA,
3730 CheckJNI::CallStaticVoidMethod,
3731 CheckJNI::CallStaticVoidMethodV,
3732 CheckJNI::CallStaticVoidMethodA,
3733 CheckJNI::GetStaticFieldID,
3734 CheckJNI::GetStaticObjectField,
3735 CheckJNI::GetStaticBooleanField,
3736 CheckJNI::GetStaticByteField,
3737 CheckJNI::GetStaticCharField,
3738 CheckJNI::GetStaticShortField,
3739 CheckJNI::GetStaticIntField,
3740 CheckJNI::GetStaticLongField,
3741 CheckJNI::GetStaticFloatField,
3742 CheckJNI::GetStaticDoubleField,
3743 CheckJNI::SetStaticObjectField,
3744 CheckJNI::SetStaticBooleanField,
3745 CheckJNI::SetStaticByteField,
3746 CheckJNI::SetStaticCharField,
3747 CheckJNI::SetStaticShortField,
3748 CheckJNI::SetStaticIntField,
3749 CheckJNI::SetStaticLongField,
3750 CheckJNI::SetStaticFloatField,
3751 CheckJNI::SetStaticDoubleField,
3752 CheckJNI::NewString,
3753 CheckJNI::GetStringLength,
3754 CheckJNI::GetStringChars,
3755 CheckJNI::ReleaseStringChars,
3756 CheckJNI::NewStringUTF,
3757 CheckJNI::GetStringUTFLength,
3758 CheckJNI::GetStringUTFChars,
3759 CheckJNI::ReleaseStringUTFChars,
3760 CheckJNI::GetArrayLength,
3761 CheckJNI::NewObjectArray,
3762 CheckJNI::GetObjectArrayElement,
3763 CheckJNI::SetObjectArrayElement,
3764 CheckJNI::NewBooleanArray,
3765 CheckJNI::NewByteArray,
3766 CheckJNI::NewCharArray,
3767 CheckJNI::NewShortArray,
3768 CheckJNI::NewIntArray,
3769 CheckJNI::NewLongArray,
3770 CheckJNI::NewFloatArray,
3771 CheckJNI::NewDoubleArray,
3772 CheckJNI::GetBooleanArrayElements,
3773 CheckJNI::GetByteArrayElements,
3774 CheckJNI::GetCharArrayElements,
3775 CheckJNI::GetShortArrayElements,
3776 CheckJNI::GetIntArrayElements,
3777 CheckJNI::GetLongArrayElements,
3778 CheckJNI::GetFloatArrayElements,
3779 CheckJNI::GetDoubleArrayElements,
3780 CheckJNI::ReleaseBooleanArrayElements,
3781 CheckJNI::ReleaseByteArrayElements,
3782 CheckJNI::ReleaseCharArrayElements,
3783 CheckJNI::ReleaseShortArrayElements,
3784 CheckJNI::ReleaseIntArrayElements,
3785 CheckJNI::ReleaseLongArrayElements,
3786 CheckJNI::ReleaseFloatArrayElements,
3787 CheckJNI::ReleaseDoubleArrayElements,
3788 CheckJNI::GetBooleanArrayRegion,
3789 CheckJNI::GetByteArrayRegion,
3790 CheckJNI::GetCharArrayRegion,
3791 CheckJNI::GetShortArrayRegion,
3792 CheckJNI::GetIntArrayRegion,
3793 CheckJNI::GetLongArrayRegion,
3794 CheckJNI::GetFloatArrayRegion,
3795 CheckJNI::GetDoubleArrayRegion,
3796 CheckJNI::SetBooleanArrayRegion,
3797 CheckJNI::SetByteArrayRegion,
3798 CheckJNI::SetCharArrayRegion,
3799 CheckJNI::SetShortArrayRegion,
3800 CheckJNI::SetIntArrayRegion,
3801 CheckJNI::SetLongArrayRegion,
3802 CheckJNI::SetFloatArrayRegion,
3803 CheckJNI::SetDoubleArrayRegion,
3804 CheckJNI::RegisterNatives,
3805 CheckJNI::UnregisterNatives,
3806 CheckJNI::MonitorEnter,
3807 CheckJNI::MonitorExit,
3808 CheckJNI::GetJavaVM,
3809 CheckJNI::GetStringRegion,
3810 CheckJNI::GetStringUTFRegion,
3811 CheckJNI::GetPrimitiveArrayCritical,
3812 CheckJNI::ReleasePrimitiveArrayCritical,
3813 CheckJNI::GetStringCritical,
3814 CheckJNI::ReleaseStringCritical,
3815 CheckJNI::NewWeakGlobalRef,
3816 CheckJNI::DeleteWeakGlobalRef,
3817 CheckJNI::ExceptionCheck,
3818 CheckJNI::NewDirectByteBuffer,
3819 CheckJNI::GetDirectBufferAddress,
3820 CheckJNI::GetDirectBufferCapacity,
3821 CheckJNI::GetObjectRefType,
3822};
3823
3824const JNINativeInterface* GetCheckJniNativeInterface() {
3825 return &gCheckNativeInterface;
3826}
3827
3828class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003829 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003830 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003831 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3832 JniValueType args[1] = {{.v = vm}};
3833 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3834 JniValueType result;
3835 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003836 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3837 // which will delete the JavaVMExt.
3838 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003839 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003840 }
3841
3842 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003843 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3844 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3845 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3846 JniValueType result;
3847 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3848 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3849 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003850 }
3851
3852 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003853 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3854 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3855 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3856 JniValueType result;
3857 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3858 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3859 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003860 }
3861
3862 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003863 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3864 JniValueType args[1] = {{.v = vm}};
3865 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3866 JniValueType result;
3867 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3868 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3869 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003870 }
3871
Ian Rogers68d8b422014-07-17 11:09:10 -07003872 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3873 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3874 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3875 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3876 JniValueType result;
3877 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3878 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3879 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003880 }
3881
3882 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003883 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3884 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003885 }
3886};
3887
3888const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003889 nullptr, // reserved0
3890 nullptr, // reserved1
3891 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003892 CheckJII::DestroyJavaVM,
3893 CheckJII::AttachCurrentThread,
3894 CheckJII::DetachCurrentThread,
3895 CheckJII::GetEnv,
3896 CheckJII::AttachCurrentThreadAsDaemon
3897};
3898
3899const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3900 return &gCheckInvokeInterface;
3901}
3902
3903} // namespace art