blob: a1ce30b3fc1f28abd8907f39f00126851b1b3420 [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
Andreas Gampeef4afe92015-07-27 21:03:25 -070019#include <iomanip>
Elliott Hughesa2501992011-08-26 19:39:54 -070020#include <sys/mman.h>
21#include <zlib.h>
22
Mathieu Chartierc7853442015-03-27 14:35:38 -070023#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070024#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080025#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070026#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070027#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070029#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070030#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070031#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080032#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/object-inl.h"
35#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070036#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070038#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070039#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070040#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070041#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070042
43namespace art {
44
Elliott Hughesa2501992011-08-26 19:39:54 -070045/*
46 * ===========================================================================
47 * JNI function helpers
48 * ===========================================================================
49 */
50
Elliott Hughes3f6635a2012-06-19 13:37:49 -070051// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070052#define kFlag_Default 0x0000
53
Elliott Hughes3f6635a2012-06-19 13:37:49 -070054#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
55#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
56#define kFlag_CritGet 0x0002 // This is a critical "get".
57#define kFlag_CritRelease 0x0003 // This is a critical "release".
58#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070059
Elliott Hughes3f6635a2012-06-19 13:37:49 -070060#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
61#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070062
Elliott Hughes3f6635a2012-06-19 13:37:49 -070063#define kFlag_Release 0x0010 // Are we in a non-critical release function?
64#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Elliott Hughes3f6635a2012-06-19 13:37:49 -070066#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070067
Elliott Hughes485cac42011-12-09 17:49:35 -080068#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 -070069
70class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070071/*
72 * Java primitive types:
73 * B - jbyte
74 * C - jchar
75 * D - jdouble
76 * F - jfloat
77 * I - jint
78 * J - jlong
79 * S - jshort
80 * Z - jboolean (shown as true and false)
81 * V - void
82 *
83 * Java reference types:
84 * L - jobject
85 * a - jarray
86 * c - jclass
87 * s - jstring
88 * t - jthrowable
89 *
90 * JNI types:
91 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
92 * f - jfieldID
93 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
94 * m - jmethodID
95 * p - void*
96 * r - jint (for release mode arguments)
97 * u - const char* (Modified UTF-8)
98 * z - jsize (for lengths; use i if negative values are okay)
99 * v - JavaVM*
100 * w - jobjectRefType
101 * E - JNIEnv*
102 * . - no argument; just print "..." (used for varargs JNI calls)
103 *
104 */
105union JniValueType {
106 jarray a;
107 jboolean b;
108 jclass c;
109 jfieldID f;
110 jint i;
111 jmethodID m;
112 const void* p; // Pointer.
113 jint r; // Release mode.
114 jstring s;
115 jthrowable t;
116 const char* u; // Modified UTF-8.
117 JavaVM* v;
118 jobjectRefType w;
119 jsize z;
120 jbyte B;
121 jchar C;
122 jdouble D;
123 JNIEnv* E;
124 jfloat F;
125 jint I;
126 jlong J;
127 jobject L;
128 jshort S;
129 const void* V; // void
130 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700131 const VarArgs* va;
132};
133
134/*
135 * A structure containing all the information needed to validate varargs arguments.
136 *
137 * Note that actually getting the arguments from this structure mutates it so should only be done on
138 * owned copies.
139 */
140class VarArgs {
141 public:
142 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
143 va_copy(vargs_, var);
144 }
145
146 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
147
148 ~VarArgs() {
149 if (type_ == kTypeVaList) {
150 va_end(vargs_);
151 }
152 }
153
154 VarArgs(VarArgs&& other) {
155 m_ = other.m_;
156 cnt_ = other.cnt_;
157 type_ = other.type_;
158 if (other.type_ == kTypeVaList) {
159 va_copy(vargs_, other.vargs_);
160 } else {
161 ptr_ = other.ptr_;
162 }
163 }
164
165 // This method is const because we need to ensure that one only uses the GetValue method on an
166 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
167 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
168 // we want to use one we need to Clone() it.
169 VarArgs Clone() const {
170 if (type_ == kTypeVaList) {
171 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
172 // messed up if the source argument is not the exact type 'va_list'.
173 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
174 } else {
175 return VarArgs(m_, cnt_, ptr_);
176 }
177 }
178
179 jmethodID GetMethodID() const {
180 return m_;
181 }
182
183 JniValueType GetValue(char fmt) {
184 JniValueType o;
185 if (type_ == kTypeVaList) {
186 switch (fmt) {
187 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
188 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
189 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
190 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
191 case 'I': o.I = va_arg(vargs_, jint); break;
192 case 'J': o.J = va_arg(vargs_, jlong); break;
193 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
194 case 'D': o.D = va_arg(vargs_, jdouble); break;
195 case 'L': o.L = va_arg(vargs_, jobject); break;
196 default:
197 LOG(FATAL) << "Illegal type format char " << fmt;
198 UNREACHABLE();
199 }
200 } else {
201 CHECK(type_ == kTypePtr);
202 jvalue v = ptr_[cnt_];
203 cnt_++;
204 switch (fmt) {
205 case 'Z': o.Z = v.z; break;
206 case 'B': o.B = v.b; break;
207 case 'C': o.C = v.c; break;
208 case 'S': o.S = v.s; break;
209 case 'I': o.I = v.i; break;
210 case 'J': o.J = v.j; break;
211 case 'F': o.F = v.f; break;
212 case 'D': o.D = v.d; break;
213 case 'L': o.L = v.l; break;
214 default:
215 LOG(FATAL) << "Illegal type format char " << fmt;
216 UNREACHABLE();
217 }
218 }
219 return o;
220 }
221
222 private:
223 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
224 va_copy(vargs_, var);
225 }
226
227 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
228
229 enum VarArgsType {
230 kTypeVaList,
231 kTypePtr,
232 };
233
234 jmethodID m_;
235 VarArgsType type_;
236 uint32_t cnt_;
237 union {
238 va_list vargs_;
239 const jvalue* ptr_;
240 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700241};
242
Elliott Hughesa2501992011-08-26 19:39:54 -0700243class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800244 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100245 ScopedCheck(int flags, const char* functionName, bool has_method = true)
Ian Rogers68d8b422014-07-17 11:09:10 -0700246 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700247 }
248
Ian Rogers68d8b422014-07-17 11:09:10 -0700249 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700250
Elliott Hughes81ff3182012-03-23 20:35:56 -0700251 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
252 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
253 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
254 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700255 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700256 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700257 AbortF("illegal class name '%s'\n"
258 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
259 class_name);
260 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700261 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700262 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700263 }
264
265 /*
266 * Verify that this instance field ID is valid for this object.
267 *
268 * Assumes "jobj" has already been validated.
269 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700270 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700271 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700272 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700273 if (o == nullptr) {
274 AbortF("field operation on NULL object: %p", java_object);
275 return false;
276 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700277 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700278 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700279 AbortF("field operation on invalid %s: %p",
280 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
281 java_object);
282 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700283 }
284
Mathieu Chartierc7853442015-03-27 14:35:38 -0700285 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800286 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700287 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700288 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800289 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700290 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700291 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700292 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700293 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700294 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700295 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700296 }
297
298 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700299 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700300 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700301 bool CheckNonNull(const void* ptr) {
302 if (UNLIKELY(ptr == nullptr)) {
303 AbortF("non-nullable argument was NULL");
304 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700306 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700307 }
308
309 /*
310 * Verify that the method's return type matches the type of call.
311 * 'expectedType' will be "L" for all objects, including arrays.
312 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700313 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
314 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700315 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700316 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800317 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700318 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700319 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700320 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700321 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700322 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700323 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700324 bool is_static = (invoke == kStatic);
325 if (is_static != m->IsStatic()) {
326 if (is_static) {
327 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700328 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700329 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700330 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700331 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700332 }
333 return false;
334 }
335 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700336 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700337 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700338 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700339 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700340 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700341 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700342 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700344 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700345 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700346 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700347 return false;
348 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700349 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
350 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 return false;
352 }
353 }
354 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700355 }
356
357 /*
358 * Verify that this static field ID is valid for this class.
359 *
360 * Assumes "java_class" has already been validated.
361 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700362 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700363 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700364 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700365 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800366 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700367 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700368 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700369 if (c != f->GetDeclaringClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700370 AbortF("static jfieldID %p not valid for class %s", fid,
371 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700372 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700373 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700374 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700375 }
376
377 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700378 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700379 *
380 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700381 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700382 * allow bad code in the system though.
383 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700384 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700385 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700386 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700387 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700388 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800389 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700390 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700391 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700392 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700393 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700394 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
395 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700396 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700397 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700398 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700399 }
400
401 /*
402 * Verify that "mid" is appropriate for "jobj".
403 *
404 * Make sure the object is an instance of the method's declaring class.
405 * (Note the mid might point to a declaration in an interface; this
406 * will be handled automatically by the instanceof check.)
407 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700408 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700409 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700410 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800411 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700412 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700413 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700414 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700415 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700416 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700417 return false;
418 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700419 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
420 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700421 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700422 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700423 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700424 }
425
426 /**
427 * The format string is a sequence of the following characters,
428 * and must be followed by arguments of the corresponding types
429 * in the same order.
430 *
431 * Java primitive types:
432 * B - jbyte
433 * C - jchar
434 * D - jdouble
435 * F - jfloat
436 * I - jint
437 * J - jlong
438 * S - jshort
439 * Z - jboolean (shown as true and false)
440 * V - void
441 *
442 * Java reference types:
443 * L - jobject
444 * a - jarray
445 * c - jclass
446 * s - jstring
447 *
448 * JNI types:
449 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
450 * f - jfieldID
451 * m - jmethodID
452 * p - void*
453 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700454 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 * z - jsize (for lengths; use i if negative values are okay)
456 * v - JavaVM*
457 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700458 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700459 *
460 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
461 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700462 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700463 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700464 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700465 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700466 // We need to guard some of the invocation interface's calls: a bad caller might
467 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700468 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800469 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
470 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700471 }
472 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700473
Ian Rogersef7d42f2014-01-06 12:55:46 -0800474 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700475 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700476 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700477 for (size_t i = 0; fmt[i] != '\0'; ++i) {
478 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
479 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700480 StringAppendF(&msg, ", ");
481 }
482 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700483
Elliott Hughes485cac42011-12-09 17:49:35 -0800484 if ((flags_ & kFlag_ForceTrace) != 0) {
485 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
486 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700487 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700488 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700489 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
490 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700491 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700492 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
493 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700494 }
495 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700496 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700497 }
498 }
499
500 // We always do the thorough checks on entry, and never on exit...
501 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700502 for (size_t i = 0; fmt[i] != '\0'; ++i) {
503 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
504 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700505 }
506 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700507 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700508 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700509 }
510
Ian Rogers68d8b422014-07-17 11:09:10 -0700511 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
512 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800513 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700514 // We need to guard some of the invocation interface's calls: a bad caller might
515 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
516 Thread* self = Thread::Current();
517 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
518 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700519 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700520 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
521 }
522 }
523 if (should_trace) {
524 std::string msg;
525 for (size_t i = 0; fmt[i] != '\0'; ++i) {
526 TraceNonHeapValue(fmt[i], args[i], &msg);
527 if (fmt[i + 1] != '\0') {
528 StringAppendF(&msg, ", ");
529 }
530 }
531
532 if ((flags_ & kFlag_ForceTrace) != 0) {
533 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
534 } else if (entry) {
535 if (has_method_) {
536 Thread* self = Thread::Current();
537 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700538 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700539 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700540 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
541 indent_ = methodName.size() + 1;
542 } else {
543 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
544 indent_ = 0;
545 }
546 } else {
547 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
548 }
549 }
550
551 // We always do the thorough checks on entry, and never on exit...
552 if (entry) {
553 for (size_t i = 0; fmt[i] != '\0'; ++i) {
554 if (!CheckNonHeapValue(fmt[i], args[i])) {
555 return false;
556 }
557 }
558 }
559 return true;
560 }
561
562 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700563 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700564 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700565 if (method == nullptr) {
566 AbortF("expected non-null method");
567 return false;
568 }
569 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700570 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
571 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700572 AbortF("expected java.lang.reflect.Method or "
573 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700574 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700575 return false;
576 }
577 return true;
578 }
579
580 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700581 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700582 ArtMethod* method = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700583 if (method == nullptr) {
584 AbortF("expected non-null constructor");
585 return false;
586 }
587 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700588 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700589 return false;
590 }
591 return true;
592 }
593
594 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700595 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700596 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700597 if (field == nullptr) {
598 AbortF("expected non-null java.lang.reflect.Field");
599 return false;
600 }
601 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700602 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700603 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700604 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700605 return false;
606 }
607 return true;
608 }
609
610 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700611 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700612 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700613 if (!obj->GetClass()->IsThrowableClass()) {
614 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700615 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700616 return false;
617 }
618 return true;
619 }
620
621 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700622 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700623 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700624 if (!c->IsThrowableClass()) {
625 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700626 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700627 return false;
628 }
629 return true;
630 }
631
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700632 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700633 IndirectRefKind found_kind;
634 if (expected_kind == kLocal) {
635 found_kind = GetIndirectRefKind(obj);
636 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
637 found_kind = kLocal;
638 }
639 } else {
640 found_kind = GetIndirectRefKind(obj);
641 }
642 if (obj != nullptr && found_kind != expected_kind) {
643 AbortF("expected reference of kind %s but found %s: %p",
644 ToStr<IndirectRefKind>(expected_kind).c_str(),
645 ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
646 obj);
647 return false;
648 }
649 return true;
650 }
651
652 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700653 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700654 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700655 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700656 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700657 return false;
658 }
659 return true;
660 }
661
662 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700663 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700664 if (!CheckArray(soa, array)) {
665 return false;
666 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700667 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700668 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
669 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700670 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700671 return false;
672 }
673 return true;
674 }
675
676 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
677 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700678 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700679 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
680 return false;
681 }
682 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
683 return false;
684 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700685 ArtField* field = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700686 DCHECK(field != nullptr); // Already checked by Check.
687 if (is_static != field->IsStatic()) {
688 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700689 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700690 return false;
691 }
692 if (type != field->GetTypeAsPrimitiveType()) {
693 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700694 field->PrettyField().c_str(),
695 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700696 PrettyDescriptor(type).c_str(), fid);
697 return false;
698 }
699 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700700 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700701 if (o == nullptr || !o->IsClass()) {
702 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700703 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700704 return false;
705 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700706 ObjPtr<mirror::Class> c = o->AsClass();
707 if (c != field->GetDeclaringClass()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700708 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700709 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700710 return false;
711 }
712 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700713 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700714 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
715 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700716 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700717 return false;
718 }
719 }
720 return true;
721 }
722
723 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800724 enum InstanceKind {
725 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700726 kDirectByteBuffer,
727 kObject,
728 kString,
729 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800730 };
731
732 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700733 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800734 * an instance of expectedClass.
735 *
736 * Because we're looking at an object on the GC heap, we have to switch
737 * to "running" mode before doing the checks.
738 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700739 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700740 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800741 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800742 switch (kind) {
743 case kClass:
744 what = "jclass";
745 break;
746 case kDirectByteBuffer:
747 what = "direct ByteBuffer";
748 break;
749 case kObject:
750 what = "jobject";
751 break;
752 case kString:
753 what = "jstring";
754 break;
755 case kThrowable:
756 what = "jthrowable";
757 break;
758 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700759 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800760 }
761
Ian Rogersef7d42f2014-01-06 12:55:46 -0800762 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700763 if (null_ok) {
764 return true;
765 } else {
766 AbortF("%s received NULL %s", function_name_, what);
767 return false;
768 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800769 }
770
Mathieu Chartier0795f232016-09-27 18:43:30 -0700771 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700772 if (obj == nullptr) {
773 // Either java_object is invalid or is a cleared weak.
774 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
775 bool okay;
776 if (GetIndirectRefKind(ref) != kWeakGlobal) {
777 okay = false;
778 } else {
779 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700780 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700781 }
782 if (!okay) {
783 AbortF("%s is an invalid %s: %p (%p)",
784 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700785 java_object, obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700786 return false;
787 }
788 }
789
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700790 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700791 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700792 AbortF("%s is an invalid %s: %p (%p)",
793 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
Mathieu Chartier1cc62e42016-10-03 18:01:28 -0700794 java_object, obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800795 return false;
796 }
797
798 bool okay = true;
799 switch (kind) {
800 case kClass:
801 okay = obj->IsClass();
802 break;
803 case kDirectByteBuffer:
804 UNIMPLEMENTED(FATAL);
805 break;
806 case kString:
807 okay = obj->GetClass()->IsStringClass();
808 break;
809 case kThrowable:
810 okay = obj->GetClass()->IsThrowableClass();
811 break;
812 case kObject:
813 break;
814 }
815 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700816 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800817 return false;
818 }
819
820 return true;
821 }
822
Ian Rogers68d8b422014-07-17 11:09:10 -0700823 /*
824 * Verify that the "mode" argument passed to a primitive array Release
825 * function is one of the valid values.
826 */
827 bool CheckReleaseMode(jint mode) {
828 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
829 AbortF("unknown value for release mode: %d", mode);
830 return false;
831 }
832 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700833 }
834
Ian Rogers68d8b422014-07-17 11:09:10 -0700835 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700836 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700837 switch (fmt) {
838 case 'a': // jarray
839 return CheckArray(soa, arg.a);
840 case 'c': // jclass
841 return CheckInstance(soa, kClass, arg.c, false);
842 case 'f': // jfieldID
843 return CheckFieldID(soa, arg.f) != nullptr;
844 case 'm': // jmethodID
845 return CheckMethodID(soa, arg.m) != nullptr;
846 case 'r': // release int
847 return CheckReleaseMode(arg.r);
848 case 's': // jstring
849 return CheckInstance(soa, kString, arg.s, false);
850 case 't': // jthrowable
851 return CheckInstance(soa, kThrowable, arg.t, false);
852 case 'E': // JNIEnv*
853 return CheckThread(arg.E);
854 case 'L': // jobject
855 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700856 case '.': // A VarArgs list
857 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700858 default:
859 return CheckNonHeapValue(fmt, arg);
860 }
861 }
862
Alex Light48ffe062015-08-19 15:23:23 -0700863 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700864 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700865 CHECK(args_p != nullptr);
866 VarArgs args(args_p->Clone());
867 ArtMethod* m = CheckMethodID(soa, args.GetMethodID());
868 if (m == nullptr) {
869 return false;
870 }
871 uint32_t len = 0;
872 const char* shorty = m->GetShorty(&len);
873 // Skip the return type
874 CHECK_GE(len, 1u);
875 len--;
876 shorty++;
877 for (uint32_t i = 0; i < len; i++) {
878 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
879 return false;
880 }
881 }
882 return true;
883 }
884
Ian Rogers68d8b422014-07-17 11:09:10 -0700885 bool CheckNonHeapValue(char fmt, JniValueType arg) {
886 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700887 case 'p': // TODO: pointer - null or readable?
888 case 'v': // JavaVM*
889 case 'B': // jbyte
890 case 'C': // jchar
891 case 'D': // jdouble
892 case 'F': // jfloat
893 case 'I': // jint
894 case 'J': // jlong
895 case 'S': // jshort
896 break; // Ignored.
897 case 'b': // jboolean, why two? Fall-through.
898 case 'Z':
899 return CheckBoolean(arg.Z);
900 case 'u': // utf8
901 if ((flags_ & kFlag_Release) != 0) {
902 return CheckNonNull(arg.u);
903 } else {
904 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
905 return CheckUtfString(arg.u, nullable);
906 }
907 case 'w': // jobjectRefType
908 switch (arg.w) {
909 case JNIInvalidRefType:
910 case JNILocalRefType:
911 case JNIGlobalRefType:
912 case JNIWeakGlobalRefType:
913 break;
914 default:
915 AbortF("Unknown reference type");
916 return false;
917 }
918 break;
919 case 'z': // jsize
920 return CheckLengthPositive(arg.z);
921 default:
922 AbortF("unknown format specifier: '%c'", fmt);
923 return false;
924 }
925 return true;
926 }
927
928 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
929 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700930 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700931 switch (fmt) {
932 case 'L': // jobject fall-through.
933 case 'a': // jarray fall-through.
934 case 's': // jstring fall-through.
935 case 't': // jthrowable fall-through.
936 if (arg.L == nullptr) {
937 *msg += "NULL";
938 } else {
939 StringAppendF(msg, "%p", arg.L);
940 }
941 break;
942 case 'c': { // jclass
943 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700944 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700945 if (c == nullptr) {
946 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700947 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700948 StringAppendF(msg, "INVALID POINTER:%p", jc);
949 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700950 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700951 } else {
David Sehr709b0702016-10-13 09:12:37 -0700952 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700953 if (!entry) {
954 StringAppendF(msg, " (%p)", jc);
955 }
956 }
957 break;
958 }
959 case 'f': { // jfieldID
960 jfieldID fid = arg.f;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700961 ArtField* f = soa.DecodeField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700962 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700963 if (!entry) {
964 StringAppendF(msg, " (%p)", fid);
965 }
966 break;
967 }
968 case 'm': { // jmethodID
969 jmethodID mid = arg.m;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700970 ArtMethod* m = soa.DecodeMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700971 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700972 if (!entry) {
973 StringAppendF(msg, " (%p)", mid);
974 }
975 break;
976 }
Alex Light48ffe062015-08-19 15:23:23 -0700977 case '.': {
978 const VarArgs* va = arg.va;
979 VarArgs args(va->Clone());
980 ArtMethod* m = soa.DecodeMethod(args.GetMethodID());
981 uint32_t len;
982 const char* shorty = m->GetShorty(&len);
983 CHECK_GE(len, 1u);
984 // Skip past return value.
985 len--;
986 shorty++;
987 // Remove the previous ', ' from the message.
988 msg->erase(msg->length() - 2);
989 for (uint32_t i = 0; i < len; i++) {
990 *msg += ", ";
991 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
992 }
993 break;
994 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700995 default:
996 TraceNonHeapValue(fmt, arg, msg);
997 break;
998 }
999 }
1000
1001 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1002 switch (fmt) {
1003 case 'B': // jbyte
1004 if (arg.B >= 0 && arg.B < 10) {
1005 StringAppendF(msg, "%d", arg.B);
1006 } else {
1007 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1008 }
1009 break;
1010 case 'C': // jchar
1011 if (arg.C < 0x7f && arg.C >= ' ') {
1012 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1013 } else {
1014 StringAppendF(msg, "U+%x", arg.C);
1015 }
1016 break;
1017 case 'F': // jfloat
1018 StringAppendF(msg, "%g", arg.F);
1019 break;
1020 case 'D': // jdouble
1021 StringAppendF(msg, "%g", arg.D);
1022 break;
1023 case 'S': // jshort
1024 StringAppendF(msg, "%d", arg.S);
1025 break;
1026 case 'i': // jint - fall-through.
1027 case 'I': // jint
1028 StringAppendF(msg, "%d", arg.I);
1029 break;
1030 case 'J': // jlong
1031 StringAppendF(msg, "%" PRId64, arg.J);
1032 break;
1033 case 'Z': // jboolean
1034 case 'b': // jboolean (JNI-style)
1035 *msg += arg.b == JNI_TRUE ? "true" : "false";
1036 break;
1037 case 'V': // void
1038 DCHECK(arg.V == nullptr);
1039 *msg += "void";
1040 break;
1041 case 'v': // JavaVM*
1042 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1043 break;
1044 case 'E':
1045 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1046 break;
1047 case 'z': // non-negative jsize
1048 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1049 // We only treat this specially so we can do the non-negative check.
1050 // TODO: maybe this wasn't worth it?
1051 StringAppendF(msg, "%d", arg.z);
1052 break;
1053 case 'p': // void* ("pointer")
1054 if (arg.p == nullptr) {
1055 *msg += "NULL";
1056 } else {
1057 StringAppendF(msg, "(void*) %p", arg.p);
1058 }
1059 break;
1060 case 'r': { // jint (release mode)
1061 jint releaseMode = arg.r;
1062 if (releaseMode == 0) {
1063 *msg += "0";
1064 } else if (releaseMode == JNI_ABORT) {
1065 *msg += "JNI_ABORT";
1066 } else if (releaseMode == JNI_COMMIT) {
1067 *msg += "JNI_COMMIT";
1068 } else {
1069 StringAppendF(msg, "invalid release mode %d", releaseMode);
1070 }
1071 break;
1072 }
1073 case 'u': // const char* (Modified UTF-8)
1074 if (arg.u == nullptr) {
1075 *msg += "NULL";
1076 } else {
1077 StringAppendF(msg, "\"%s\"", arg.u);
1078 }
1079 break;
1080 case 'w': // jobjectRefType
1081 switch (arg.w) {
1082 case JNIInvalidRefType:
1083 *msg += "invalid reference type";
1084 break;
1085 case JNILocalRefType:
1086 *msg += "local ref type";
1087 break;
1088 case JNIGlobalRefType:
1089 *msg += "global ref type";
1090 break;
1091 case JNIWeakGlobalRefType:
1092 *msg += "weak global ref type";
1093 break;
1094 default:
1095 *msg += "unknown ref type";
1096 break;
1097 }
1098 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001099 default:
1100 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1101 }
1102 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001103 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001104 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001105 *
1106 * Since we're dealing with objects, switch to "running" mode.
1107 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001108 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001109 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001110 if (UNLIKELY(java_array == nullptr)) {
1111 AbortF("jarray was NULL");
1112 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001113 }
1114
Mathieu Chartier0795f232016-09-27 18:43:30 -07001115 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001116 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001117 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001118 AbortF("jarray is an invalid %s: %p (%p)",
1119 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
Mathieu Chartier1cc62e42016-10-03 18:01:28 -07001120 java_array, a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001121 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001122 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001123 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001124 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001125 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001126 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001127 }
1128
Ian Rogers68d8b422014-07-17 11:09:10 -07001129 bool CheckBoolean(jboolean z) {
1130 if (z != JNI_TRUE && z != JNI_FALSE) {
1131 AbortF("unexpected jboolean value: %d", z);
1132 return false;
1133 }
1134 return true;
1135 }
1136
1137 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001138 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001139 AbortF("negative jsize: %d", length);
1140 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001141 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001142 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001143 }
1144
Mathieu Chartierc7853442015-03-27 14:35:38 -07001145 ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001146 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001147 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001148 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001149 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001150 }
Mathieu Chartierc7853442015-03-27 14:35:38 -07001151 ArtField* f = soa.DecodeField(fid);
1152 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001153 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001154 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001155 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001156 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001157 }
1158 return f;
1159 }
1160
Mathieu Chartiere401d142015-04-22 13:56:20 -07001161 ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001162 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001163 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001164 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001165 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001166 }
Mathieu Chartiere401d142015-04-22 13:56:20 -07001167 ArtMethod* m = soa.DecodeMethod(mid);
1168 // TODO: Better check here.
1169 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001170 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001171 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001172 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001173 }
1174 return m;
1175 }
1176
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001177 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001178 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001179 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001180 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1181 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001182 }
1183
Daniel Erat35e827a2016-05-10 18:07:18 -06001184 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001185 JNIEnvExt* threadEnv = self->GetJniEnv();
1186
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001187 // Verify that the current thread is (a) attached and (b) associated with
1188 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001189 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001190 // Get the thread owning the JNIEnv that's being used.
1191 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001192 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001193 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001194 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001195 }
1196
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001197 // Verify that, if this thread previously made a critical "get" call, we
1198 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001199 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001200 case kFlag_CritOkay: // okay to call this method
1201 break;
1202 case kFlag_CritBad: // not okay to call
1203 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001204 AbortF("thread %s using JNI after critical get",
1205 ToStr<Thread>(*self).c_str());
1206 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001207 }
1208 break;
1209 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001210 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001211 threadEnv->critical++;
1212 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001213 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001214 threadEnv->critical--;
1215 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001216 AbortF("thread %s called too many critical releases",
1217 ToStr<Thread>(*self).c_str());
1218 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001219 }
1220 break;
1221 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001222 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001223 }
1224
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001225 // Verify that, if an exception has been raised, the native code doesn't
1226 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001227 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001228 mirror::Throwable* exception = self->GetException();
1229 AbortF("JNI %s called with pending exception %s",
1230 function_name_,
1231 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001232 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001233 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001234 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001235 }
1236
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001237 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001238 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001239 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001240 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001241 AbortF("non-nullable const char* was NULL");
1242 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001243 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001244 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001245 }
1246
Ian Rogersef7d42f2014-01-06 12:55:46 -08001247 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001248 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001249 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001250 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1251 // practice anyways.
1252 std::ostringstream oss;
1253 oss << std::hex;
1254 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1255 while (*tmp != 0) {
1256 if (tmp == utf8) {
1257 oss << "<";
1258 }
1259 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1260 if (tmp == utf8) {
1261 oss << '>';
1262 }
1263 tmp++;
1264 if (*tmp != 0) {
1265 oss << ' ';
1266 }
1267 }
1268
Ian Rogers68d8b422014-07-17 11:09:10 -07001269 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001270 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001271 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001272 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001273 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 }
1275
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001276 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1277 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001278 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001279 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001280 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001281 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001282 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001283 case 0x00:
1284 case 0x01:
1285 case 0x02:
1286 case 0x03:
1287 case 0x04:
1288 case 0x05:
1289 case 0x06:
1290 case 0x07:
1291 // Bit pattern 0xxx. No need for any extra bytes.
1292 break;
1293 case 0x08:
1294 case 0x09:
1295 case 0x0a:
1296 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001297 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001298 *errorKind = "start";
1299 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001300 case 0x0f:
1301 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001302 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001303 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1304 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001305 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1306 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001307 *errorKind = "continuation";
1308 return utf8;
1309 }
1310 } else {
1311 *errorKind = "start";
1312 return utf8;
1313 }
1314
1315 // Fall through to the cases below to consume two more continuation bytes.
1316 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001317 case 0x0e:
1318 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001319 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1320 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001321 *errorKind = "continuation";
1322 return utf8;
1323 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001324
1325 // Fall through to consume one more continuation byte.
1326 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001327 case 0x0c:
1328 case 0x0d:
1329 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001330 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1331 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001332 *errorKind = "continuation";
1333 return utf8;
1334 }
1335 break;
1336 }
1337 }
1338 return 0;
1339 }
1340
Ian Rogers68d8b422014-07-17 11:09:10 -07001341 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1342 va_list args;
1343 va_start(args, fmt);
1344 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1345 va_end(args);
1346 }
1347
1348 // The name of the JNI function being checked.
1349 const char* const function_name_;
1350
1351 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001352 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001353
Ian Rogers68d8b422014-07-17 11:09:10 -07001354 const bool has_method_;
1355
Elliott Hughesa2501992011-08-26 19:39:54 -07001356 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1357};
1358
Elliott Hughesa2501992011-08-26 19:39:54 -07001359/*
1360 * ===========================================================================
1361 * Guarded arrays
1362 * ===========================================================================
1363 */
1364
Elliott Hughesa2501992011-08-26 19:39:54 -07001365/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001366class GuardedCopy {
1367 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001368 /*
1369 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1370 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001371 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001372 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001373 const size_t new_len = LengthIncludingRedZones(len);
1374 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001375
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001376 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001377 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001378 if (!mod_okay) {
1379 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001380 }
1381
Ian Rogers68d8b422014-07-17 11:09:10 -07001382 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001383
Ian Rogers68d8b422014-07-17 11:09:10 -07001384 // Fill begin region with canary pattern.
1385 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1386 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1387 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1388 if (kCanary[j] == '\0') {
1389 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001390 } else {
1391 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001392 }
1393 }
1394
1395 // Copy the data in; note "len" could be zero.
1396 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1397
1398 // Fill end region with canary pattern.
1399 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1400 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1401 if (kCanary[j] == '\0') {
1402 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001403 } else {
1404 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001405 }
1406 }
1407
1408 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001409 }
1410
1411 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001412 * Create a guarded copy of a primitive array. Modifications to the copied
1413 * data are allowed. Returns a pointer to the copied data.
1414 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001415 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1416 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001417 ScopedObjectAccess soa(env);
1418
Mathieu Chartier0795f232016-09-27 18:43:30 -07001419 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001420 size_t component_size = a->GetClass()->GetComponentSize();
1421 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001422 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001423 if (is_copy != nullptr) {
1424 *is_copy = JNI_TRUE;
1425 }
1426 return result;
1427 }
1428
1429 /*
1430 * Perform the array "release" operation, which may or may not copy data
1431 * back into the managed heap, and may or may not release the underlying storage.
1432 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001433 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1434 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1435 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001436 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001437 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1438 return nullptr;
1439 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001440 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1441 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001442 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001443 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 }
1445 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001446 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001447 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001448 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001449 }
1450
1451
1452 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001453 * Free up the guard buffer, scrub it, and return the original pointer.
1454 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001455 static void* Destroy(void* embedded_buf) {
1456 GuardedCopy* copy = FromEmbedded(embedded_buf);
1457 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1458 size_t len = LengthIncludingRedZones(copy->original_length_);
1459 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001460 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001461 }
1462
1463 /*
1464 * Verify the guard area and, if "modOkay" is false, that the data itself
1465 * has not been altered.
1466 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001467 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001468 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001469 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1470 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1471 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001472 }
1473
1474 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001475 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001476 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1477 }
1478
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001479 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001480 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001481 if (result == MAP_FAILED) {
1482 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1483 }
1484 return reinterpret_cast<uint8_t*>(result);
1485 }
1486
Ian Rogers68d8b422014-07-17 11:09:10 -07001487 static void DebugFree(void* buf, size_t len) {
1488 if (munmap(buf, len) != 0) {
1489 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001490 }
1491 }
1492
Ian Rogers68d8b422014-07-17 11:09:10 -07001493 static size_t LengthIncludingRedZones(size_t len) {
1494 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001495 }
1496
Ian Rogers68d8b422014-07-17 11:09:10 -07001497 // Get the GuardedCopy from the interior pointer.
1498 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1499 return reinterpret_cast<GuardedCopy*>(
1500 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001501 }
1502
Ian Rogers68d8b422014-07-17 11:09:10 -07001503 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1504 return reinterpret_cast<const GuardedCopy*>(
1505 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001506 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001507
1508 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1509 va_list args;
1510 va_start(args, fmt);
1511 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1512 va_end(args);
1513 }
1514
1515 bool CheckHeader(const char* function_name, bool mod_okay) const {
1516 static const uint32_t kMagicCmp = kGuardMagic;
1517
1518 // Before we do anything with "pExtra", check the magic number. We
1519 // do the check with memcmp rather than "==" in case the pointer is
1520 // unaligned. If it points to completely bogus memory we're going
1521 // to crash, but there's no easy way around that.
1522 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1523 uint8_t buf[4];
1524 memcpy(buf, &magic_, 4);
1525 AbortF(function_name,
1526 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1527 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1528 return false;
1529 }
1530
1531 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1532 // told the client that we made a copy, there's no reason they can't alter the buffer.
1533 if (!mod_okay) {
1534 uLong computed_adler =
1535 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1536 if (computed_adler != adler_) {
1537 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1538 computed_adler, adler_, this);
1539 return false;
1540 }
1541 }
1542 return true;
1543 }
1544
1545 bool CheckRedZones(const char* function_name) const {
1546 // Check the begin red zone.
1547 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1548 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1549 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1550 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1551 return false;
1552 }
1553 if (kCanary[j] == '\0') {
1554 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001555 } else {
1556 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001557 }
1558 }
1559
1560 // Check end region.
1561 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1562 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1563 size_t offset_from_buffer_start =
1564 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1565 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1566 offset_from_buffer_start);
1567 return false;
1568 }
1569 if (kCanary[j] == '\0') {
1570 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001571 } else {
1572 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001573 }
1574 }
1575 return true;
1576 }
1577
1578 // Location that canary value will be written before the guarded region.
1579 const char* StartRedZone() const {
1580 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1581 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1582 }
1583
1584 // Return the interior embedded buffer.
1585 const uint8_t* BufferWithinRedZones() const {
1586 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1587 return embedded_buf;
1588 }
1589
1590 // Location that canary value will be written after the guarded region.
1591 const char* EndRedZone() const {
1592 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1593 size_t buf_len = LengthIncludingRedZones(original_length_);
1594 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1595 }
1596
1597 static constexpr size_t kRedZoneSize = 512;
1598 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1599
1600 // Value written before and after the guarded array.
1601 static const char* const kCanary;
1602
1603 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1604
1605 const uint32_t magic_;
1606 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001607 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001608 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001609};
Ian Rogers68d8b422014-07-17 11:09:10 -07001610const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001611
1612/*
1613 * ===========================================================================
1614 * JNI functions
1615 * ===========================================================================
1616 */
1617
1618class CheckJNI {
1619 public:
1620 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001621 ScopedObjectAccess soa(env);
1622 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1623 JniValueType args[1] = {{.E = env }};
1624 if (sc.Check(soa, true, "E", args)) {
1625 JniValueType result;
1626 result.I = baseEnv(env)->GetVersion(env);
1627 if (sc.Check(soa, false, "I", &result)) {
1628 return result.I;
1629 }
1630 }
1631 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001632 }
1633
Ian Rogers68d8b422014-07-17 11:09:10 -07001634 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1635 ScopedObjectAccess soa(env);
1636 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1637 JniValueType args[2] = {{.E = env }, {.p = vm}};
1638 if (sc.Check(soa, true, "Ep", args)) {
1639 JniValueType result;
1640 result.i = baseEnv(env)->GetJavaVM(env, vm);
1641 if (sc.Check(soa, false, "i", &result)) {
1642 return result.i;
1643 }
1644 }
1645 return JNI_ERR;
1646 }
1647
1648 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1649 ScopedObjectAccess soa(env);
1650 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1651 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1652 if (sc.Check(soa, true, "EcpI", args)) {
1653 JniValueType result;
1654 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1655 if (sc.Check(soa, false, "i", &result)) {
1656 return result.i;
1657 }
1658 }
1659 return JNI_ERR;
1660 }
1661
1662 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1663 ScopedObjectAccess soa(env);
1664 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1665 JniValueType args[2] = {{.E = env }, {.c = c}};
1666 if (sc.Check(soa, true, "Ec", args)) {
1667 JniValueType result;
1668 result.i = baseEnv(env)->UnregisterNatives(env, c);
1669 if (sc.Check(soa, false, "i", &result)) {
1670 return result.i;
1671 }
1672 }
1673 return JNI_ERR;
1674 }
1675
1676 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001677 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1678 // know the object is invalid. The spec says that passing invalid objects or even ones that
1679 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001680 ScopedObjectAccess soa(env);
1681 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001682 JniValueType args[2] = {{.E = env }, {.L = obj}};
1683 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001684 JniValueType result;
1685 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1686 if (sc.Check(soa, false, "w", &result)) {
1687 return result.w;
1688 }
1689 }
1690 return JNIInvalidRefType;
1691 }
1692
1693 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1694 jsize bufLen) {
1695 ScopedObjectAccess soa(env);
1696 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1697 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1698 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1699 JniValueType result;
1700 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1701 if (sc.Check(soa, false, "c", &result)) {
1702 return result.c;
1703 }
1704 }
1705 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001706 }
1707
1708 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001709 ScopedObjectAccess soa(env);
1710 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1711 JniValueType args[2] = {{.E = env}, {.u = name}};
1712 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1713 JniValueType result;
1714 result.c = baseEnv(env)->FindClass(env, name);
1715 if (sc.Check(soa, false, "c", &result)) {
1716 return result.c;
1717 }
1718 }
1719 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001720 }
1721
Elliott Hughese84278b2012-03-22 10:06:53 -07001722 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001723 ScopedObjectAccess soa(env);
1724 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1725 JniValueType args[2] = {{.E = env}, {.c = c}};
1726 if (sc.Check(soa, true, "Ec", args)) {
1727 JniValueType result;
1728 result.c = baseEnv(env)->GetSuperclass(env, c);
1729 if (sc.Check(soa, false, "c", &result)) {
1730 return result.c;
1731 }
1732 }
1733 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001734 }
1735
Elliott Hughese84278b2012-03-22 10:06:53 -07001736 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001737 ScopedObjectAccess soa(env);
1738 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1739 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1740 if (sc.Check(soa, true, "Ecc", args)) {
1741 JniValueType result;
1742 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1743 if (sc.Check(soa, false, "b", &result)) {
1744 return result.b;
1745 }
1746 }
1747 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001748 }
1749
1750 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001751 ScopedObjectAccess soa(env);
1752 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1753 JniValueType args[2] = {{.E = env}, {.L = method}};
1754 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1755 JniValueType result;
1756 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1757 if (sc.Check(soa, false, "m", &result)) {
1758 return result.m;
1759 }
1760 }
1761 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001762 }
1763
1764 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001765 ScopedObjectAccess soa(env);
1766 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1767 JniValueType args[2] = {{.E = env}, {.L = field}};
1768 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1769 JniValueType result;
1770 result.f = baseEnv(env)->FromReflectedField(env, field);
1771 if (sc.Check(soa, false, "f", &result)) {
1772 return result.f;
1773 }
1774 }
1775 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001776 }
1777
1778 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001779 ScopedObjectAccess soa(env);
1780 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1781 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1782 if (sc.Check(soa, true, "Ecmb", args)) {
1783 JniValueType result;
1784 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1785 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1786 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1787 return result.L;
1788 }
1789 }
1790 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001791 }
1792
1793 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001794 ScopedObjectAccess soa(env);
1795 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1796 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1797 if (sc.Check(soa, true, "Ecfb", args)) {
1798 JniValueType result;
1799 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1800 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1801 DCHECK(sc.CheckReflectedField(soa, result.L));
1802 return result.L;
1803 }
1804 }
1805 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001806 }
1807
1808 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001809 ScopedObjectAccess soa(env);
1810 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1811 JniValueType args[2] = {{.E = env}, {.t = obj}};
1812 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1813 JniValueType result;
1814 result.i = baseEnv(env)->Throw(env, obj);
1815 if (sc.Check(soa, false, "i", &result)) {
1816 return result.i;
1817 }
1818 }
1819 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001820 }
1821
Elliott Hughese84278b2012-03-22 10:06:53 -07001822 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001823 ScopedObjectAccess soa(env);
1824 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001825 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001826 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1827 JniValueType result;
1828 result.i = baseEnv(env)->ThrowNew(env, c, message);
1829 if (sc.Check(soa, false, "i", &result)) {
1830 return result.i;
1831 }
1832 }
1833 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001834 }
1835
1836 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001837 ScopedObjectAccess soa(env);
1838 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1839 JniValueType args[1] = {{.E = env}};
1840 if (sc.Check(soa, true, "E", args)) {
1841 JniValueType result;
1842 result.t = baseEnv(env)->ExceptionOccurred(env);
1843 if (sc.Check(soa, false, "t", &result)) {
1844 return result.t;
1845 }
1846 }
1847 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001848 }
1849
1850 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001851 ScopedObjectAccess soa(env);
1852 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1853 JniValueType args[1] = {{.E = env}};
1854 if (sc.Check(soa, true, "E", args)) {
1855 JniValueType result;
1856 baseEnv(env)->ExceptionDescribe(env);
1857 result.V = nullptr;
1858 sc.Check(soa, false, "V", &result);
1859 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001860 }
1861
1862 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001863 ScopedObjectAccess soa(env);
1864 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1865 JniValueType args[1] = {{.E = env}};
1866 if (sc.Check(soa, true, "E", args)) {
1867 JniValueType result;
1868 baseEnv(env)->ExceptionClear(env);
1869 result.V = nullptr;
1870 sc.Check(soa, false, "V", &result);
1871 }
1872 }
1873
1874 static jboolean ExceptionCheck(JNIEnv* env) {
1875 ScopedObjectAccess soa(env);
1876 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1877 JniValueType args[1] = {{.E = env}};
1878 if (sc.Check(soa, true, "E", args)) {
1879 JniValueType result;
1880 result.b = baseEnv(env)->ExceptionCheck(env);
1881 if (sc.Check(soa, false, "b", &result)) {
1882 return result.b;
1883 }
1884 }
1885 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001886 }
1887
1888 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001889 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1890 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1891 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001892 ScopedObjectAccess soa(env);
1893 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1894 JniValueType args[2] = {{.E = env}, {.u = msg}};
1895 if (sc.Check(soa, true, "Eu", args)) {
1896 JniValueType result;
1897 baseEnv(env)->FatalError(env, msg);
1898 // Unreachable.
1899 result.V = nullptr;
1900 sc.Check(soa, false, "V", &result);
1901 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001902 }
1903
1904 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001905 ScopedObjectAccess soa(env);
1906 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1907 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1908 if (sc.Check(soa, true, "EI", args)) {
1909 JniValueType result;
1910 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1911 if (sc.Check(soa, false, "i", &result)) {
1912 return result.i;
1913 }
1914 }
1915 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001916 }
1917
1918 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001919 ScopedObjectAccess soa(env);
1920 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1921 JniValueType args[2] = {{.E = env}, {.L = res}};
1922 if (sc.Check(soa, true, "EL", args)) {
1923 JniValueType result;
1924 result.L = baseEnv(env)->PopLocalFrame(env, res);
1925 sc.Check(soa, false, "L", &result);
1926 return result.L;
1927 }
1928 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001929 }
1930
1931 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001932 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001933 }
1934
Ian Rogers68d8b422014-07-17 11:09:10 -07001935 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1936 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001937 }
1938
1939 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001940 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001941 }
1942
Ian Rogers68d8b422014-07-17 11:09:10 -07001943 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1944 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001945 }
1946
Ian Rogers68d8b422014-07-17 11:09:10 -07001947 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1948 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1949 }
1950
1951 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1952 DeleteRef(__FUNCTION__, env, obj, kLocal);
1953 }
1954
1955 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1956 ScopedObjectAccess soa(env);
1957 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1958 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1959 if (sc.Check(soa, true, "EI", args)) {
1960 JniValueType result;
1961 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1962 if (sc.Check(soa, false, "i", &result)) {
1963 return result.i;
1964 }
1965 }
1966 return JNI_ERR;
1967 }
1968
1969 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1970 ScopedObjectAccess soa(env);
1971 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1972 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1973 if (sc.Check(soa, true, "ELL", args)) {
1974 JniValueType result;
1975 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1976 if (sc.Check(soa, false, "b", &result)) {
1977 return result.b;
1978 }
1979 }
1980 return JNI_FALSE;
1981 }
1982
1983 static jobject AllocObject(JNIEnv* env, jclass c) {
1984 ScopedObjectAccess soa(env);
1985 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1986 JniValueType args[2] = {{.E = env}, {.c = c}};
1987 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1988 JniValueType result;
1989 result.L = baseEnv(env)->AllocObject(env, c);
1990 if (sc.Check(soa, false, "L", &result)) {
1991 return result.L;
1992 }
1993 }
1994 return nullptr;
1995 }
1996
1997 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1998 ScopedObjectAccess soa(env);
1999 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002000 VarArgs rest(mid, vargs);
2001 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2002 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002003 sc.CheckConstructor(soa, mid)) {
2004 JniValueType result;
2005 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2006 if (sc.Check(soa, false, "L", &result)) {
2007 return result.L;
2008 }
2009 }
2010 return nullptr;
2011 }
2012
2013 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2014 va_list args;
2015 va_start(args, mid);
2016 jobject result = NewObjectV(env, c, mid, args);
2017 va_end(args);
2018 return result;
2019 }
2020
2021 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2022 ScopedObjectAccess soa(env);
2023 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002024 VarArgs rest(mid, vargs);
2025 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2026 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002027 sc.CheckConstructor(soa, mid)) {
2028 JniValueType result;
2029 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2030 if (sc.Check(soa, false, "L", &result)) {
2031 return result.L;
2032 }
2033 }
2034 return nullptr;
2035 }
2036
2037 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2038 ScopedObjectAccess soa(env);
2039 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2040 JniValueType args[2] = {{.E = env}, {.L = obj}};
2041 if (sc.Check(soa, true, "EL", args)) {
2042 JniValueType result;
2043 result.c = baseEnv(env)->GetObjectClass(env, obj);
2044 if (sc.Check(soa, false, "c", &result)) {
2045 return result.c;
2046 }
2047 }
2048 return nullptr;
2049 }
2050
2051 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2052 ScopedObjectAccess soa(env);
2053 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2054 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2055 if (sc.Check(soa, true, "ELc", args)) {
2056 JniValueType result;
2057 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2058 if (sc.Check(soa, false, "b", &result)) {
2059 return result.b;
2060 }
2061 }
2062 return JNI_FALSE;
2063 }
2064
2065 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2066 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2067 }
2068
2069 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2070 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2071 }
2072
2073 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2074 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2075 }
2076
2077 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2078 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2079 }
2080
2081#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2082 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2083 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2084 } \
2085 \
2086 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2087 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2088 } \
2089 \
2090 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2091 JniValueType value; \
2092 value.shorty = v; \
2093 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2094 } \
2095 \
2096 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2097 JniValueType value; \
2098 value.shorty = v; \
2099 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2100 }
2101
2102 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2103 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2104 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2105 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2106 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2107 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2108 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2109 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2110 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2111#undef FIELD_ACCESSORS
2112
2113 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2114 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2115 }
2116
2117 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2118 jvalue* vargs) {
2119 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2120 }
2121
2122 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002123 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002124 }
2125
2126 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2127 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2128 }
2129
2130 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2131 va_list vargs) {
2132 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2133 }
2134
2135 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2136 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2137 }
2138
2139 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2140 va_list vargs;
2141 va_start(vargs, mid);
2142 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2143 va_end(vargs);
2144 }
2145
2146 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2147 va_list vargs;
2148 va_start(vargs, mid);
2149 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2150 va_end(vargs);
2151 }
2152
2153 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2154 va_list vargs;
2155 va_start(vargs, mid);
2156 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2157 va_end(vargs);
2158 }
2159
2160#define CALL(rtype, name, ptype, shorty) \
2161 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2162 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2163 } \
2164 \
2165 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2166 jvalue* vargs) { \
2167 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2168 } \
2169 \
2170 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2171 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2172 } \
2173 \
2174 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2175 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2176 } \
2177 \
2178 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2179 va_list vargs) { \
2180 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2181 } \
2182 \
2183 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2184 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2185 } \
2186 \
2187 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2188 va_list vargs; \
2189 va_start(vargs, mid); \
2190 rtype result = \
2191 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2192 va_end(vargs); \
2193 return result; \
2194 } \
2195 \
2196 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2197 ...) { \
2198 va_list vargs; \
2199 va_start(vargs, mid); \
2200 rtype result = \
2201 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2202 va_end(vargs); \
2203 return result; \
2204 } \
2205 \
2206 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2207 va_list vargs; \
2208 va_start(vargs, mid); \
2209 rtype result = \
2210 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2211 va_end(vargs); \
2212 return result; \
2213 }
2214
2215 CALL(jobject, Object, Primitive::kPrimNot, L)
2216 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2217 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2218 CALL(jchar, Char, Primitive::kPrimChar, C)
2219 CALL(jshort, Short, Primitive::kPrimShort, S)
2220 CALL(jint, Int, Primitive::kPrimInt, I)
2221 CALL(jlong, Long, Primitive::kPrimLong, J)
2222 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2223 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2224#undef CALL
2225
2226 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2227 ScopedObjectAccess soa(env);
2228 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2229 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2230 if (sc.Check(soa, true, "Epz", args)) {
2231 JniValueType result;
2232 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2233 if (sc.Check(soa, false, "s", &result)) {
2234 return result.s;
2235 }
2236 }
2237 return nullptr;
2238 }
2239
2240 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2241 ScopedObjectAccess soa(env);
2242 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2243 JniValueType args[2] = {{.E = env}, {.u = chars}};
2244 if (sc.Check(soa, true, "Eu", args)) {
2245 JniValueType result;
2246 // TODO: stale? show pointer and truncate string.
2247 result.s = baseEnv(env)->NewStringUTF(env, chars);
2248 if (sc.Check(soa, false, "s", &result)) {
2249 return result.s;
2250 }
2251 }
2252 return nullptr;
2253 }
2254
2255 static jsize GetStringLength(JNIEnv* env, jstring string) {
2256 ScopedObjectAccess soa(env);
2257 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2258 JniValueType args[2] = {{.E = env}, {.s = string}};
2259 if (sc.Check(soa, true, "Es", args)) {
2260 JniValueType result;
2261 result.z = baseEnv(env)->GetStringLength(env, string);
2262 if (sc.Check(soa, false, "z", &result)) {
2263 return result.z;
2264 }
2265 }
2266 return JNI_ERR;
2267 }
2268
2269 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2270 ScopedObjectAccess soa(env);
2271 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2272 JniValueType args[2] = {{.E = env}, {.s = string}};
2273 if (sc.Check(soa, true, "Es", args)) {
2274 JniValueType result;
2275 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2276 if (sc.Check(soa, false, "z", &result)) {
2277 return result.z;
2278 }
2279 }
2280 return JNI_ERR;
2281 }
2282
2283 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2284 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2285 is_copy, false, false));
2286 }
2287
2288 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2289 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2290 is_copy, true, false));
2291 }
2292
2293 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2294 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2295 is_copy, false, true));
2296 }
2297
2298 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2299 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2300 }
2301
2302 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2303 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2304 }
2305
2306 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2307 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2308 }
2309
2310 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2311 ScopedObjectAccess soa(env);
2312 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2313 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2314 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2315 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2316 if (sc.Check(soa, true, "EsIIp", args)) {
2317 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2318 JniValueType result;
2319 result.V = nullptr;
2320 sc.Check(soa, false, "V", &result);
2321 }
2322 }
2323
2324 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2325 ScopedObjectAccess soa(env);
2326 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2327 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2328 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2329 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2330 if (sc.Check(soa, true, "EsIIp", args)) {
2331 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2332 JniValueType result;
2333 result.V = nullptr;
2334 sc.Check(soa, false, "V", &result);
2335 }
2336 }
2337
2338 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2339 ScopedObjectAccess soa(env);
2340 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2341 JniValueType args[2] = {{.E = env}, {.a = array}};
2342 if (sc.Check(soa, true, "Ea", args)) {
2343 JniValueType result;
2344 result.z = baseEnv(env)->GetArrayLength(env, array);
2345 if (sc.Check(soa, false, "z", &result)) {
2346 return result.z;
2347 }
2348 }
2349 return JNI_ERR;
2350 }
2351
2352 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2353 jobject initial_element) {
2354 ScopedObjectAccess soa(env);
2355 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2356 JniValueType args[4] =
2357 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2358 if (sc.Check(soa, true, "EzcL", args)) {
2359 JniValueType result;
2360 // Note: assignability tests of initial_element are done in the base implementation.
2361 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2362 if (sc.Check(soa, false, "a", &result)) {
2363 return down_cast<jobjectArray>(result.a);
2364 }
2365 }
2366 return nullptr;
2367 }
2368
2369 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2370 ScopedObjectAccess soa(env);
2371 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2372 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2373 if (sc.Check(soa, true, "Eaz", args)) {
2374 JniValueType result;
2375 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2376 if (sc.Check(soa, false, "L", &result)) {
2377 return result.L;
2378 }
2379 }
2380 return nullptr;
2381 }
2382
2383 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2384 ScopedObjectAccess soa(env);
2385 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2386 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2387 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2388 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2389 // in ArrayStoreExceptions.
2390 if (sc.Check(soa, true, "EaIL", args)) {
2391 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2392 JniValueType result;
2393 result.V = nullptr;
2394 sc.Check(soa, false, "V", &result);
2395 }
2396 }
2397
2398 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2399 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2400 Primitive::kPrimBoolean));
2401 }
2402
2403 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2404 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2405 Primitive::kPrimByte));
2406 }
2407
2408 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2409 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2410 Primitive::kPrimChar));
2411 }
2412
2413 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2414 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2415 Primitive::kPrimShort));
2416 }
2417
2418 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2419 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2420 }
2421
2422 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2423 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2424 Primitive::kPrimLong));
2425 }
2426
2427 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2428 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2429 Primitive::kPrimFloat));
2430 }
2431
2432 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2433 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2434 Primitive::kPrimDouble));
2435 }
2436
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002437// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002438#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002439 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2440 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002441 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2442 } \
2443 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002444 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002445 jint mode) { \
2446 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2447 } \
2448 \
2449 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002450 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002451 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2452 } \
2453 \
2454 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2455 const ctype* buf) { \
2456 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2457 }
2458
2459 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2460 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2461 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2462 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2463 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2464 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2465 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2466 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2467#undef PRIMITIVE_ARRAY_FUNCTIONS
2468
2469 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2470 ScopedObjectAccess soa(env);
2471 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2472 JniValueType args[2] = {{.E = env}, {.L = obj}};
2473 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002474 if (obj != nullptr) {
2475 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2476 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002477 JniValueType result;
2478 result.i = baseEnv(env)->MonitorEnter(env, obj);
2479 if (sc.Check(soa, false, "i", &result)) {
2480 return result.i;
2481 }
2482 }
2483 return JNI_ERR;
2484 }
2485
2486 static jint MonitorExit(JNIEnv* env, jobject obj) {
2487 ScopedObjectAccess soa(env);
2488 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2489 JniValueType args[2] = {{.E = env}, {.L = obj}};
2490 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002491 if (obj != nullptr) {
2492 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2493 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002494 JniValueType result;
2495 result.i = baseEnv(env)->MonitorExit(env, obj);
2496 if (sc.Check(soa, false, "i", &result)) {
2497 return result.i;
2498 }
2499 }
2500 return JNI_ERR;
2501 }
2502
2503 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2504 ScopedObjectAccess soa(env);
2505 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2506 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2507 if (sc.Check(soa, true, "Eap", args)) {
2508 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002509 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2510 if (ptr != nullptr && soa.ForceCopy()) {
2511 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002512 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002513 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002514 if (sc.Check(soa, false, "p", &result)) {
2515 return const_cast<void*>(result.p);
2516 }
2517 }
2518 return nullptr;
2519 }
2520
2521 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2522 ScopedObjectAccess soa(env);
2523 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2524 sc.CheckNonNull(carray);
2525 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2526 if (sc.Check(soa, true, "Eapr", args)) {
2527 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002528 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002529 }
2530 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2531 JniValueType result;
2532 result.V = nullptr;
2533 sc.Check(soa, false, "V", &result);
2534 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002535 }
2536
2537 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002538 ScopedObjectAccess soa(env);
2539 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2540 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2541 if (sc.Check(soa, true, "EpJ", args)) {
2542 JniValueType result;
2543 // Note: the validity of address and capacity are checked in the base implementation.
2544 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2545 if (sc.Check(soa, false, "L", &result)) {
2546 return result.L;
2547 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002548 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002549 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002550 }
2551
2552 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002553 ScopedObjectAccess soa(env);
2554 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2555 JniValueType args[2] = {{.E = env}, {.L = buf}};
2556 if (sc.Check(soa, true, "EL", args)) {
2557 JniValueType result;
2558 // Note: this is implemented in the base environment by a GetLongField which will sanity
2559 // check the type of buf in GetLongField above.
2560 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2561 if (sc.Check(soa, false, "p", &result)) {
2562 return const_cast<void*>(result.p);
2563 }
2564 }
2565 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002566 }
2567
2568 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002569 ScopedObjectAccess soa(env);
2570 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2571 JniValueType args[2] = {{.E = env}, {.L = buf}};
2572 if (sc.Check(soa, true, "EL", args)) {
2573 JniValueType result;
2574 // Note: this is implemented in the base environment by a GetIntField which will sanity
2575 // check the type of buf in GetIntField above.
2576 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2577 if (sc.Check(soa, false, "J", &result)) {
2578 return result.J;
2579 }
2580 }
2581 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002582 }
2583
2584 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002585 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2586 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2587 }
2588
2589 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002590 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2591 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002592
2593 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2594 ScopedObjectAccess soa(env);
2595 ScopedCheck sc(kFlag_Default, function_name);
2596 JniValueType args[2] = {{.E = env}, {.L = obj}};
2597 if (sc.Check(soa, true, "EL", args)) {
2598 JniValueType result;
2599 switch (kind) {
2600 case kGlobal:
2601 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2602 break;
2603 case kLocal:
2604 result.L = baseEnv(env)->NewLocalRef(env, obj);
2605 break;
2606 case kWeakGlobal:
2607 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2608 break;
2609 default:
2610 LOG(FATAL) << "Unexpected reference kind: " << kind;
2611 }
2612 if (sc.Check(soa, false, "L", &result)) {
2613 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002614 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002615 return result.L;
2616 }
2617 }
2618 return nullptr;
2619 }
2620
2621 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2622 ScopedObjectAccess soa(env);
2623 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2624 JniValueType args[2] = {{.E = env}, {.L = obj}};
2625 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002626 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002627 JniValueType result;
2628 switch (kind) {
2629 case kGlobal:
2630 baseEnv(env)->DeleteGlobalRef(env, obj);
2631 break;
2632 case kLocal:
2633 baseEnv(env)->DeleteLocalRef(env, obj);
2634 break;
2635 case kWeakGlobal:
2636 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2637 break;
2638 default:
2639 LOG(FATAL) << "Unexpected reference kind: " << kind;
2640 }
2641 result.V = nullptr;
2642 sc.Check(soa, false, "V", &result);
2643 }
2644 }
2645
2646 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2647 const char* name, const char* sig, bool is_static) {
2648 ScopedObjectAccess soa(env);
2649 ScopedCheck sc(kFlag_Default, function_name);
2650 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2651 if (sc.Check(soa, true, "Ecuu", args)) {
2652 JniValueType result;
2653 if (is_static) {
2654 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2655 } else {
2656 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2657 }
2658 if (sc.Check(soa, false, "m", &result)) {
2659 return result.m;
2660 }
2661 }
2662 return nullptr;
2663 }
2664
2665 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2666 const char* name, const char* sig, bool is_static) {
2667 ScopedObjectAccess soa(env);
2668 ScopedCheck sc(kFlag_Default, function_name);
2669 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2670 if (sc.Check(soa, true, "Ecuu", args)) {
2671 JniValueType result;
2672 if (is_static) {
2673 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2674 } else {
2675 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2676 }
2677 if (sc.Check(soa, false, "f", &result)) {
2678 return result.f;
2679 }
2680 }
2681 return nullptr;
2682 }
2683
2684 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2685 bool is_static, Primitive::Type type) {
2686 ScopedObjectAccess soa(env);
2687 ScopedCheck sc(kFlag_Default, function_name);
2688 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2689 JniValueType result;
2690 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2691 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2692 const char* result_check = nullptr;
2693 switch (type) {
2694 case Primitive::kPrimNot:
2695 if (is_static) {
2696 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2697 } else {
2698 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2699 }
2700 result_check = "L";
2701 break;
2702 case Primitive::kPrimBoolean:
2703 if (is_static) {
2704 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2705 } else {
2706 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2707 }
2708 result_check = "Z";
2709 break;
2710 case Primitive::kPrimByte:
2711 if (is_static) {
2712 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2713 } else {
2714 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2715 }
2716 result_check = "B";
2717 break;
2718 case Primitive::kPrimChar:
2719 if (is_static) {
2720 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2721 } else {
2722 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2723 }
2724 result_check = "C";
2725 break;
2726 case Primitive::kPrimShort:
2727 if (is_static) {
2728 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2729 } else {
2730 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2731 }
2732 result_check = "S";
2733 break;
2734 case Primitive::kPrimInt:
2735 if (is_static) {
2736 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2737 } else {
2738 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2739 }
2740 result_check = "I";
2741 break;
2742 case Primitive::kPrimLong:
2743 if (is_static) {
2744 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2745 } else {
2746 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2747 }
2748 result_check = "J";
2749 break;
2750 case Primitive::kPrimFloat:
2751 if (is_static) {
2752 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2753 } else {
2754 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2755 }
2756 result_check = "F";
2757 break;
2758 case Primitive::kPrimDouble:
2759 if (is_static) {
2760 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2761 } else {
2762 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2763 }
2764 result_check = "D";
2765 break;
2766 case Primitive::kPrimVoid:
2767 LOG(FATAL) << "Unexpected type: " << type;
2768 break;
2769 }
2770 if (sc.Check(soa, false, result_check, &result)) {
2771 return result;
2772 }
2773 }
2774 result.J = 0;
2775 return result;
2776 }
2777
2778 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2779 bool is_static, Primitive::Type type, JniValueType value) {
2780 ScopedObjectAccess soa(env);
2781 ScopedCheck sc(kFlag_Default, function_name);
2782 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2783 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2784 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2785 if (sc.Check(soa, true, sig, args) &&
2786 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2787 switch (type) {
2788 case Primitive::kPrimNot:
2789 if (is_static) {
2790 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2791 } else {
2792 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2793 }
2794 break;
2795 case Primitive::kPrimBoolean:
2796 if (is_static) {
2797 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2798 } else {
2799 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2800 }
2801 break;
2802 case Primitive::kPrimByte:
2803 if (is_static) {
2804 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2805 } else {
2806 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2807 }
2808 break;
2809 case Primitive::kPrimChar:
2810 if (is_static) {
2811 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2812 } else {
2813 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2814 }
2815 break;
2816 case Primitive::kPrimShort:
2817 if (is_static) {
2818 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2819 } else {
2820 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2821 }
2822 break;
2823 case Primitive::kPrimInt:
2824 if (is_static) {
2825 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2826 } else {
2827 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2828 }
2829 break;
2830 case Primitive::kPrimLong:
2831 if (is_static) {
2832 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2833 } else {
2834 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2835 }
2836 break;
2837 case Primitive::kPrimFloat:
2838 if (is_static) {
2839 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2840 } else {
2841 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2842 }
2843 break;
2844 case Primitive::kPrimDouble:
2845 if (is_static) {
2846 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2847 } else {
2848 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2849 }
2850 break;
2851 case Primitive::kPrimVoid:
2852 LOG(FATAL) << "Unexpected type: " << type;
2853 break;
2854 }
2855 JniValueType result;
2856 result.V = nullptr;
2857 sc.Check(soa, false, "V", &result);
2858 }
2859 }
2860
2861 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002862 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002863 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002864 bool checked;
2865 switch (invoke) {
2866 case kVirtual: {
2867 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002868 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2869 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002870 break;
2871 }
2872 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002873 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2874 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002875 break;
2876 }
2877 case kStatic: {
2878 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002879 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2880 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002881 break;
2882 }
2883 default:
2884 LOG(FATAL) << "Unexpected invoke: " << invoke;
2885 checked = false;
2886 break;
2887 }
2888 return checked;
2889 }
2890
2891 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2892 jmethodID mid, jvalue* vargs, Primitive::Type type,
2893 InvokeType invoke) {
2894 ScopedObjectAccess soa(env);
2895 ScopedCheck sc(kFlag_Default, function_name);
2896 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002897 VarArgs rest(mid, vargs);
2898 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002899 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2900 const char* result_check;
2901 switch (type) {
2902 case Primitive::kPrimNot:
2903 result_check = "L";
2904 switch (invoke) {
2905 case kVirtual:
2906 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2907 break;
2908 case kDirect:
2909 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2910 break;
2911 case kStatic:
2912 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2913 break;
2914 default:
2915 break;
2916 }
2917 break;
2918 case Primitive::kPrimBoolean:
2919 result_check = "Z";
2920 switch (invoke) {
2921 case kVirtual:
2922 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2923 break;
2924 case kDirect:
2925 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2926 break;
2927 case kStatic:
2928 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2929 break;
2930 default:
2931 break;
2932 }
2933 break;
2934 case Primitive::kPrimByte:
2935 result_check = "B";
2936 switch (invoke) {
2937 case kVirtual:
2938 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2939 break;
2940 case kDirect:
2941 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2942 break;
2943 case kStatic:
2944 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2945 break;
2946 default:
2947 break;
2948 }
2949 break;
2950 case Primitive::kPrimChar:
2951 result_check = "C";
2952 switch (invoke) {
2953 case kVirtual:
2954 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2955 break;
2956 case kDirect:
2957 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2958 break;
2959 case kStatic:
2960 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2961 break;
2962 default:
2963 break;
2964 }
2965 break;
2966 case Primitive::kPrimShort:
2967 result_check = "S";
2968 switch (invoke) {
2969 case kVirtual:
2970 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2971 break;
2972 case kDirect:
2973 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2974 break;
2975 case kStatic:
2976 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2977 break;
2978 default:
2979 break;
2980 }
2981 break;
2982 case Primitive::kPrimInt:
2983 result_check = "I";
2984 switch (invoke) {
2985 case kVirtual:
2986 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2987 break;
2988 case kDirect:
2989 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2990 break;
2991 case kStatic:
2992 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2993 break;
2994 default:
2995 break;
2996 }
2997 break;
2998 case Primitive::kPrimLong:
2999 result_check = "J";
3000 switch (invoke) {
3001 case kVirtual:
3002 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3003 break;
3004 case kDirect:
3005 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3006 break;
3007 case kStatic:
3008 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3009 break;
3010 default:
3011 break;
3012 }
3013 break;
3014 case Primitive::kPrimFloat:
3015 result_check = "F";
3016 switch (invoke) {
3017 case kVirtual:
3018 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3019 break;
3020 case kDirect:
3021 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3022 break;
3023 case kStatic:
3024 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3025 break;
3026 default:
3027 break;
3028 }
3029 break;
3030 case Primitive::kPrimDouble:
3031 result_check = "D";
3032 switch (invoke) {
3033 case kVirtual:
3034 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3035 break;
3036 case kDirect:
3037 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3038 break;
3039 case kStatic:
3040 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3041 break;
3042 default:
3043 break;
3044 }
3045 break;
3046 case Primitive::kPrimVoid:
3047 result_check = "V";
3048 result.V = nullptr;
3049 switch (invoke) {
3050 case kVirtual:
3051 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3052 break;
3053 case kDirect:
3054 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3055 break;
3056 case kStatic:
3057 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3058 break;
3059 default:
3060 LOG(FATAL) << "Unexpected invoke: " << invoke;
3061 }
3062 break;
3063 default:
3064 LOG(FATAL) << "Unexpected return type: " << type;
3065 result_check = nullptr;
3066 }
3067 if (sc.Check(soa, false, result_check, &result)) {
3068 return result;
3069 }
3070 }
3071 result.J = 0;
3072 return result;
3073 }
3074
3075 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3076 jmethodID mid, va_list vargs, Primitive::Type type,
3077 InvokeType invoke) {
3078 ScopedObjectAccess soa(env);
3079 ScopedCheck sc(kFlag_Default, function_name);
3080 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003081 VarArgs rest(mid, vargs);
3082 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003083 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3084 const char* result_check;
3085 switch (type) {
3086 case Primitive::kPrimNot:
3087 result_check = "L";
3088 switch (invoke) {
3089 case kVirtual:
3090 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3091 break;
3092 case kDirect:
3093 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3094 break;
3095 case kStatic:
3096 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3097 break;
3098 default:
3099 LOG(FATAL) << "Unexpected invoke: " << invoke;
3100 }
3101 break;
3102 case Primitive::kPrimBoolean:
3103 result_check = "Z";
3104 switch (invoke) {
3105 case kVirtual:
3106 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3107 break;
3108 case kDirect:
3109 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3110 break;
3111 case kStatic:
3112 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3113 break;
3114 default:
3115 LOG(FATAL) << "Unexpected invoke: " << invoke;
3116 }
3117 break;
3118 case Primitive::kPrimByte:
3119 result_check = "B";
3120 switch (invoke) {
3121 case kVirtual:
3122 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3123 break;
3124 case kDirect:
3125 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3126 break;
3127 case kStatic:
3128 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3129 break;
3130 default:
3131 LOG(FATAL) << "Unexpected invoke: " << invoke;
3132 }
3133 break;
3134 case Primitive::kPrimChar:
3135 result_check = "C";
3136 switch (invoke) {
3137 case kVirtual:
3138 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3139 break;
3140 case kDirect:
3141 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3142 break;
3143 case kStatic:
3144 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3145 break;
3146 default:
3147 LOG(FATAL) << "Unexpected invoke: " << invoke;
3148 }
3149 break;
3150 case Primitive::kPrimShort:
3151 result_check = "S";
3152 switch (invoke) {
3153 case kVirtual:
3154 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3155 break;
3156 case kDirect:
3157 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3158 break;
3159 case kStatic:
3160 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3161 break;
3162 default:
3163 LOG(FATAL) << "Unexpected invoke: " << invoke;
3164 }
3165 break;
3166 case Primitive::kPrimInt:
3167 result_check = "I";
3168 switch (invoke) {
3169 case kVirtual:
3170 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3171 break;
3172 case kDirect:
3173 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3174 break;
3175 case kStatic:
3176 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3177 break;
3178 default:
3179 LOG(FATAL) << "Unexpected invoke: " << invoke;
3180 }
3181 break;
3182 case Primitive::kPrimLong:
3183 result_check = "J";
3184 switch (invoke) {
3185 case kVirtual:
3186 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3187 break;
3188 case kDirect:
3189 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3190 break;
3191 case kStatic:
3192 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3193 break;
3194 default:
3195 LOG(FATAL) << "Unexpected invoke: " << invoke;
3196 }
3197 break;
3198 case Primitive::kPrimFloat:
3199 result_check = "F";
3200 switch (invoke) {
3201 case kVirtual:
3202 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3203 break;
3204 case kDirect:
3205 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3206 break;
3207 case kStatic:
3208 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3209 break;
3210 default:
3211 LOG(FATAL) << "Unexpected invoke: " << invoke;
3212 }
3213 break;
3214 case Primitive::kPrimDouble:
3215 result_check = "D";
3216 switch (invoke) {
3217 case kVirtual:
3218 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3219 break;
3220 case kDirect:
3221 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3222 break;
3223 case kStatic:
3224 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3225 break;
3226 default:
3227 LOG(FATAL) << "Unexpected invoke: " << invoke;
3228 }
3229 break;
3230 case Primitive::kPrimVoid:
3231 result_check = "V";
3232 result.V = nullptr;
3233 switch (invoke) {
3234 case kVirtual:
3235 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3236 break;
3237 case kDirect:
3238 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3239 break;
3240 case kStatic:
3241 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3242 break;
3243 default:
3244 LOG(FATAL) << "Unexpected invoke: " << invoke;
3245 }
3246 break;
3247 default:
3248 LOG(FATAL) << "Unexpected return type: " << type;
3249 result_check = nullptr;
3250 }
3251 if (sc.Check(soa, false, result_check, &result)) {
3252 return result;
3253 }
3254 }
3255 result.J = 0;
3256 return result;
3257 }
3258
3259 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3260 jboolean* is_copy, bool utf, bool critical) {
3261 ScopedObjectAccess soa(env);
3262 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3263 ScopedCheck sc(flags, function_name);
3264 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3265 if (sc.Check(soa, true, "Esp", args)) {
3266 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003267 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003268 if (utf) {
3269 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003270 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3271 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003272 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003273 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3274 baseEnv(env)->GetStringChars(env, string, is_copy));
3275 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003276 }
3277 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003278 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003279 if (utf) {
3280 size_t length_in_bytes = strlen(result.u) + 1;
3281 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003282 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003283 } else {
3284 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3285 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003286 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003287 }
3288 if (is_copy != nullptr) {
3289 *is_copy = JNI_TRUE;
3290 }
3291 }
3292 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3293 return utf ? result.u : result.p;
3294 }
3295 }
3296 return nullptr;
3297 }
3298
3299 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3300 const void* chars, bool utf, bool critical) {
3301 ScopedObjectAccess soa(env);
3302 int flags = kFlag_ExcepOkay | kFlag_Release;
3303 if (critical) {
3304 flags |= kFlag_CritRelease;
3305 }
3306 ScopedCheck sc(flags, function_name);
3307 sc.CheckNonNull(chars);
3308 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3309 if (force_copy_ok && soa.ForceCopy()) {
3310 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3311 }
3312 if (force_copy_ok) {
3313 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3314 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3315 if (utf) {
3316 CHECK(!critical);
3317 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3318 } else {
3319 if (critical) {
3320 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3321 } else {
3322 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3323 }
3324 }
3325 JniValueType result;
3326 sc.Check(soa, false, "V", &result);
3327 }
3328 }
3329 }
3330
3331 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3332 Primitive::Type type) {
3333 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003334 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003335 JniValueType args[2] = {{.E = env}, {.z = length}};
3336 if (sc.Check(soa, true, "Ez", args)) {
3337 JniValueType result;
3338 switch (type) {
3339 case Primitive::kPrimBoolean:
3340 result.a = baseEnv(env)->NewBooleanArray(env, length);
3341 break;
3342 case Primitive::kPrimByte:
3343 result.a = baseEnv(env)->NewByteArray(env, length);
3344 break;
3345 case Primitive::kPrimChar:
3346 result.a = baseEnv(env)->NewCharArray(env, length);
3347 break;
3348 case Primitive::kPrimShort:
3349 result.a = baseEnv(env)->NewShortArray(env, length);
3350 break;
3351 case Primitive::kPrimInt:
3352 result.a = baseEnv(env)->NewIntArray(env, length);
3353 break;
3354 case Primitive::kPrimLong:
3355 result.a = baseEnv(env)->NewLongArray(env, length);
3356 break;
3357 case Primitive::kPrimFloat:
3358 result.a = baseEnv(env)->NewFloatArray(env, length);
3359 break;
3360 case Primitive::kPrimDouble:
3361 result.a = baseEnv(env)->NewDoubleArray(env, length);
3362 break;
3363 default:
3364 LOG(FATAL) << "Unexpected primitive type: " << type;
3365 }
3366 if (sc.Check(soa, false, "a", &result)) {
3367 return result.a;
3368 }
3369 }
3370 return nullptr;
3371 }
3372
3373 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3374 JNIEnv* env, jarray array, jboolean* is_copy) {
3375 ScopedObjectAccess soa(env);
3376 ScopedCheck sc(kFlag_Default, function_name);
3377 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3378 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3379 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003380 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003381 switch (type) {
3382 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003383 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3384 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003385 break;
3386 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003387 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003388 break;
3389 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003390 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003391 break;
3392 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003393 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003394 break;
3395 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003396 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003397 break;
3398 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003399 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003400 break;
3401 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003402 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003403 break;
3404 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003405 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003406 break;
3407 default:
3408 LOG(FATAL) << "Unexpected primitive type: " << type;
3409 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003410 if (ptr != nullptr && soa.ForceCopy()) {
3411 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003412 if (is_copy != nullptr) {
3413 *is_copy = JNI_TRUE;
3414 }
3415 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003416 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003417 if (sc.Check(soa, false, "p", &result)) {
3418 return const_cast<void*>(result.p);
3419 }
3420 }
3421 return nullptr;
3422 }
3423
3424 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3425 JNIEnv* env, jarray array, void* elems, jint mode) {
3426 ScopedObjectAccess soa(env);
3427 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3428 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3429 if (soa.ForceCopy()) {
3430 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3431 }
3432 if (!soa.ForceCopy() || elems != nullptr) {
3433 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3434 if (sc.Check(soa, true, "Eapr", args)) {
3435 switch (type) {
3436 case Primitive::kPrimBoolean:
3437 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3438 reinterpret_cast<jboolean*>(elems), mode);
3439 break;
3440 case Primitive::kPrimByte:
3441 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3442 reinterpret_cast<jbyte*>(elems), mode);
3443 break;
3444 case Primitive::kPrimChar:
3445 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3446 reinterpret_cast<jchar*>(elems), mode);
3447 break;
3448 case Primitive::kPrimShort:
3449 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3450 reinterpret_cast<jshort*>(elems), mode);
3451 break;
3452 case Primitive::kPrimInt:
3453 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3454 reinterpret_cast<jint*>(elems), mode);
3455 break;
3456 case Primitive::kPrimLong:
3457 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3458 reinterpret_cast<jlong*>(elems), mode);
3459 break;
3460 case Primitive::kPrimFloat:
3461 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3462 reinterpret_cast<jfloat*>(elems), mode);
3463 break;
3464 case Primitive::kPrimDouble:
3465 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3466 reinterpret_cast<jdouble*>(elems), mode);
3467 break;
3468 default:
3469 LOG(FATAL) << "Unexpected primitive type: " << type;
3470 }
3471 JniValueType result;
3472 result.V = nullptr;
3473 sc.Check(soa, false, "V", &result);
3474 }
3475 }
3476 }
3477 }
3478
3479 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3480 jarray array, jsize start, jsize len, void* buf) {
3481 ScopedObjectAccess soa(env);
3482 ScopedCheck sc(kFlag_Default, function_name);
3483 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3484 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3485 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3486 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3487 switch (type) {
3488 case Primitive::kPrimBoolean:
3489 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3490 reinterpret_cast<jboolean*>(buf));
3491 break;
3492 case Primitive::kPrimByte:
3493 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3494 reinterpret_cast<jbyte*>(buf));
3495 break;
3496 case Primitive::kPrimChar:
3497 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3498 reinterpret_cast<jchar*>(buf));
3499 break;
3500 case Primitive::kPrimShort:
3501 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3502 reinterpret_cast<jshort*>(buf));
3503 break;
3504 case Primitive::kPrimInt:
3505 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3506 reinterpret_cast<jint*>(buf));
3507 break;
3508 case Primitive::kPrimLong:
3509 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3510 reinterpret_cast<jlong*>(buf));
3511 break;
3512 case Primitive::kPrimFloat:
3513 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3514 reinterpret_cast<jfloat*>(buf));
3515 break;
3516 case Primitive::kPrimDouble:
3517 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3518 reinterpret_cast<jdouble*>(buf));
3519 break;
3520 default:
3521 LOG(FATAL) << "Unexpected primitive type: " << type;
3522 }
3523 JniValueType result;
3524 result.V = nullptr;
3525 sc.Check(soa, false, "V", &result);
3526 }
3527 }
3528
3529 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3530 jarray array, jsize start, jsize len, const void* buf) {
3531 ScopedObjectAccess soa(env);
3532 ScopedCheck sc(kFlag_Default, function_name);
3533 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3534 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3535 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3536 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3537 switch (type) {
3538 case Primitive::kPrimBoolean:
3539 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3540 reinterpret_cast<const jboolean*>(buf));
3541 break;
3542 case Primitive::kPrimByte:
3543 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3544 reinterpret_cast<const jbyte*>(buf));
3545 break;
3546 case Primitive::kPrimChar:
3547 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3548 reinterpret_cast<const jchar*>(buf));
3549 break;
3550 case Primitive::kPrimShort:
3551 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3552 reinterpret_cast<const jshort*>(buf));
3553 break;
3554 case Primitive::kPrimInt:
3555 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3556 reinterpret_cast<const jint*>(buf));
3557 break;
3558 case Primitive::kPrimLong:
3559 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3560 reinterpret_cast<const jlong*>(buf));
3561 break;
3562 case Primitive::kPrimFloat:
3563 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3564 reinterpret_cast<const jfloat*>(buf));
3565 break;
3566 case Primitive::kPrimDouble:
3567 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3568 reinterpret_cast<const jdouble*>(buf));
3569 break;
3570 default:
3571 LOG(FATAL) << "Unexpected primitive type: " << type;
3572 }
3573 JniValueType result;
3574 result.V = nullptr;
3575 sc.Check(soa, false, "V", &result);
3576 }
3577 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003578};
3579
3580const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003581 nullptr, // reserved0.
3582 nullptr, // reserved1.
3583 nullptr, // reserved2.
3584 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003585 CheckJNI::GetVersion,
3586 CheckJNI::DefineClass,
3587 CheckJNI::FindClass,
3588 CheckJNI::FromReflectedMethod,
3589 CheckJNI::FromReflectedField,
3590 CheckJNI::ToReflectedMethod,
3591 CheckJNI::GetSuperclass,
3592 CheckJNI::IsAssignableFrom,
3593 CheckJNI::ToReflectedField,
3594 CheckJNI::Throw,
3595 CheckJNI::ThrowNew,
3596 CheckJNI::ExceptionOccurred,
3597 CheckJNI::ExceptionDescribe,
3598 CheckJNI::ExceptionClear,
3599 CheckJNI::FatalError,
3600 CheckJNI::PushLocalFrame,
3601 CheckJNI::PopLocalFrame,
3602 CheckJNI::NewGlobalRef,
3603 CheckJNI::DeleteGlobalRef,
3604 CheckJNI::DeleteLocalRef,
3605 CheckJNI::IsSameObject,
3606 CheckJNI::NewLocalRef,
3607 CheckJNI::EnsureLocalCapacity,
3608 CheckJNI::AllocObject,
3609 CheckJNI::NewObject,
3610 CheckJNI::NewObjectV,
3611 CheckJNI::NewObjectA,
3612 CheckJNI::GetObjectClass,
3613 CheckJNI::IsInstanceOf,
3614 CheckJNI::GetMethodID,
3615 CheckJNI::CallObjectMethod,
3616 CheckJNI::CallObjectMethodV,
3617 CheckJNI::CallObjectMethodA,
3618 CheckJNI::CallBooleanMethod,
3619 CheckJNI::CallBooleanMethodV,
3620 CheckJNI::CallBooleanMethodA,
3621 CheckJNI::CallByteMethod,
3622 CheckJNI::CallByteMethodV,
3623 CheckJNI::CallByteMethodA,
3624 CheckJNI::CallCharMethod,
3625 CheckJNI::CallCharMethodV,
3626 CheckJNI::CallCharMethodA,
3627 CheckJNI::CallShortMethod,
3628 CheckJNI::CallShortMethodV,
3629 CheckJNI::CallShortMethodA,
3630 CheckJNI::CallIntMethod,
3631 CheckJNI::CallIntMethodV,
3632 CheckJNI::CallIntMethodA,
3633 CheckJNI::CallLongMethod,
3634 CheckJNI::CallLongMethodV,
3635 CheckJNI::CallLongMethodA,
3636 CheckJNI::CallFloatMethod,
3637 CheckJNI::CallFloatMethodV,
3638 CheckJNI::CallFloatMethodA,
3639 CheckJNI::CallDoubleMethod,
3640 CheckJNI::CallDoubleMethodV,
3641 CheckJNI::CallDoubleMethodA,
3642 CheckJNI::CallVoidMethod,
3643 CheckJNI::CallVoidMethodV,
3644 CheckJNI::CallVoidMethodA,
3645 CheckJNI::CallNonvirtualObjectMethod,
3646 CheckJNI::CallNonvirtualObjectMethodV,
3647 CheckJNI::CallNonvirtualObjectMethodA,
3648 CheckJNI::CallNonvirtualBooleanMethod,
3649 CheckJNI::CallNonvirtualBooleanMethodV,
3650 CheckJNI::CallNonvirtualBooleanMethodA,
3651 CheckJNI::CallNonvirtualByteMethod,
3652 CheckJNI::CallNonvirtualByteMethodV,
3653 CheckJNI::CallNonvirtualByteMethodA,
3654 CheckJNI::CallNonvirtualCharMethod,
3655 CheckJNI::CallNonvirtualCharMethodV,
3656 CheckJNI::CallNonvirtualCharMethodA,
3657 CheckJNI::CallNonvirtualShortMethod,
3658 CheckJNI::CallNonvirtualShortMethodV,
3659 CheckJNI::CallNonvirtualShortMethodA,
3660 CheckJNI::CallNonvirtualIntMethod,
3661 CheckJNI::CallNonvirtualIntMethodV,
3662 CheckJNI::CallNonvirtualIntMethodA,
3663 CheckJNI::CallNonvirtualLongMethod,
3664 CheckJNI::CallNonvirtualLongMethodV,
3665 CheckJNI::CallNonvirtualLongMethodA,
3666 CheckJNI::CallNonvirtualFloatMethod,
3667 CheckJNI::CallNonvirtualFloatMethodV,
3668 CheckJNI::CallNonvirtualFloatMethodA,
3669 CheckJNI::CallNonvirtualDoubleMethod,
3670 CheckJNI::CallNonvirtualDoubleMethodV,
3671 CheckJNI::CallNonvirtualDoubleMethodA,
3672 CheckJNI::CallNonvirtualVoidMethod,
3673 CheckJNI::CallNonvirtualVoidMethodV,
3674 CheckJNI::CallNonvirtualVoidMethodA,
3675 CheckJNI::GetFieldID,
3676 CheckJNI::GetObjectField,
3677 CheckJNI::GetBooleanField,
3678 CheckJNI::GetByteField,
3679 CheckJNI::GetCharField,
3680 CheckJNI::GetShortField,
3681 CheckJNI::GetIntField,
3682 CheckJNI::GetLongField,
3683 CheckJNI::GetFloatField,
3684 CheckJNI::GetDoubleField,
3685 CheckJNI::SetObjectField,
3686 CheckJNI::SetBooleanField,
3687 CheckJNI::SetByteField,
3688 CheckJNI::SetCharField,
3689 CheckJNI::SetShortField,
3690 CheckJNI::SetIntField,
3691 CheckJNI::SetLongField,
3692 CheckJNI::SetFloatField,
3693 CheckJNI::SetDoubleField,
3694 CheckJNI::GetStaticMethodID,
3695 CheckJNI::CallStaticObjectMethod,
3696 CheckJNI::CallStaticObjectMethodV,
3697 CheckJNI::CallStaticObjectMethodA,
3698 CheckJNI::CallStaticBooleanMethod,
3699 CheckJNI::CallStaticBooleanMethodV,
3700 CheckJNI::CallStaticBooleanMethodA,
3701 CheckJNI::CallStaticByteMethod,
3702 CheckJNI::CallStaticByteMethodV,
3703 CheckJNI::CallStaticByteMethodA,
3704 CheckJNI::CallStaticCharMethod,
3705 CheckJNI::CallStaticCharMethodV,
3706 CheckJNI::CallStaticCharMethodA,
3707 CheckJNI::CallStaticShortMethod,
3708 CheckJNI::CallStaticShortMethodV,
3709 CheckJNI::CallStaticShortMethodA,
3710 CheckJNI::CallStaticIntMethod,
3711 CheckJNI::CallStaticIntMethodV,
3712 CheckJNI::CallStaticIntMethodA,
3713 CheckJNI::CallStaticLongMethod,
3714 CheckJNI::CallStaticLongMethodV,
3715 CheckJNI::CallStaticLongMethodA,
3716 CheckJNI::CallStaticFloatMethod,
3717 CheckJNI::CallStaticFloatMethodV,
3718 CheckJNI::CallStaticFloatMethodA,
3719 CheckJNI::CallStaticDoubleMethod,
3720 CheckJNI::CallStaticDoubleMethodV,
3721 CheckJNI::CallStaticDoubleMethodA,
3722 CheckJNI::CallStaticVoidMethod,
3723 CheckJNI::CallStaticVoidMethodV,
3724 CheckJNI::CallStaticVoidMethodA,
3725 CheckJNI::GetStaticFieldID,
3726 CheckJNI::GetStaticObjectField,
3727 CheckJNI::GetStaticBooleanField,
3728 CheckJNI::GetStaticByteField,
3729 CheckJNI::GetStaticCharField,
3730 CheckJNI::GetStaticShortField,
3731 CheckJNI::GetStaticIntField,
3732 CheckJNI::GetStaticLongField,
3733 CheckJNI::GetStaticFloatField,
3734 CheckJNI::GetStaticDoubleField,
3735 CheckJNI::SetStaticObjectField,
3736 CheckJNI::SetStaticBooleanField,
3737 CheckJNI::SetStaticByteField,
3738 CheckJNI::SetStaticCharField,
3739 CheckJNI::SetStaticShortField,
3740 CheckJNI::SetStaticIntField,
3741 CheckJNI::SetStaticLongField,
3742 CheckJNI::SetStaticFloatField,
3743 CheckJNI::SetStaticDoubleField,
3744 CheckJNI::NewString,
3745 CheckJNI::GetStringLength,
3746 CheckJNI::GetStringChars,
3747 CheckJNI::ReleaseStringChars,
3748 CheckJNI::NewStringUTF,
3749 CheckJNI::GetStringUTFLength,
3750 CheckJNI::GetStringUTFChars,
3751 CheckJNI::ReleaseStringUTFChars,
3752 CheckJNI::GetArrayLength,
3753 CheckJNI::NewObjectArray,
3754 CheckJNI::GetObjectArrayElement,
3755 CheckJNI::SetObjectArrayElement,
3756 CheckJNI::NewBooleanArray,
3757 CheckJNI::NewByteArray,
3758 CheckJNI::NewCharArray,
3759 CheckJNI::NewShortArray,
3760 CheckJNI::NewIntArray,
3761 CheckJNI::NewLongArray,
3762 CheckJNI::NewFloatArray,
3763 CheckJNI::NewDoubleArray,
3764 CheckJNI::GetBooleanArrayElements,
3765 CheckJNI::GetByteArrayElements,
3766 CheckJNI::GetCharArrayElements,
3767 CheckJNI::GetShortArrayElements,
3768 CheckJNI::GetIntArrayElements,
3769 CheckJNI::GetLongArrayElements,
3770 CheckJNI::GetFloatArrayElements,
3771 CheckJNI::GetDoubleArrayElements,
3772 CheckJNI::ReleaseBooleanArrayElements,
3773 CheckJNI::ReleaseByteArrayElements,
3774 CheckJNI::ReleaseCharArrayElements,
3775 CheckJNI::ReleaseShortArrayElements,
3776 CheckJNI::ReleaseIntArrayElements,
3777 CheckJNI::ReleaseLongArrayElements,
3778 CheckJNI::ReleaseFloatArrayElements,
3779 CheckJNI::ReleaseDoubleArrayElements,
3780 CheckJNI::GetBooleanArrayRegion,
3781 CheckJNI::GetByteArrayRegion,
3782 CheckJNI::GetCharArrayRegion,
3783 CheckJNI::GetShortArrayRegion,
3784 CheckJNI::GetIntArrayRegion,
3785 CheckJNI::GetLongArrayRegion,
3786 CheckJNI::GetFloatArrayRegion,
3787 CheckJNI::GetDoubleArrayRegion,
3788 CheckJNI::SetBooleanArrayRegion,
3789 CheckJNI::SetByteArrayRegion,
3790 CheckJNI::SetCharArrayRegion,
3791 CheckJNI::SetShortArrayRegion,
3792 CheckJNI::SetIntArrayRegion,
3793 CheckJNI::SetLongArrayRegion,
3794 CheckJNI::SetFloatArrayRegion,
3795 CheckJNI::SetDoubleArrayRegion,
3796 CheckJNI::RegisterNatives,
3797 CheckJNI::UnregisterNatives,
3798 CheckJNI::MonitorEnter,
3799 CheckJNI::MonitorExit,
3800 CheckJNI::GetJavaVM,
3801 CheckJNI::GetStringRegion,
3802 CheckJNI::GetStringUTFRegion,
3803 CheckJNI::GetPrimitiveArrayCritical,
3804 CheckJNI::ReleasePrimitiveArrayCritical,
3805 CheckJNI::GetStringCritical,
3806 CheckJNI::ReleaseStringCritical,
3807 CheckJNI::NewWeakGlobalRef,
3808 CheckJNI::DeleteWeakGlobalRef,
3809 CheckJNI::ExceptionCheck,
3810 CheckJNI::NewDirectByteBuffer,
3811 CheckJNI::GetDirectBufferAddress,
3812 CheckJNI::GetDirectBufferCapacity,
3813 CheckJNI::GetObjectRefType,
3814};
3815
3816const JNINativeInterface* GetCheckJniNativeInterface() {
3817 return &gCheckNativeInterface;
3818}
3819
3820class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003821 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003822 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003823 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3824 JniValueType args[1] = {{.v = vm}};
3825 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3826 JniValueType result;
3827 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003828 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3829 // which will delete the JavaVMExt.
3830 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003831 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003832 }
3833
3834 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003835 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3836 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3837 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3838 JniValueType result;
3839 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3840 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3841 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003842 }
3843
3844 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003845 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3846 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3847 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3848 JniValueType result;
3849 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3850 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3851 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003852 }
3853
3854 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003855 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3856 JniValueType args[1] = {{.v = vm}};
3857 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3858 JniValueType result;
3859 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3860 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3861 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003862 }
3863
Ian Rogers68d8b422014-07-17 11:09:10 -07003864 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3865 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3866 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3867 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3868 JniValueType result;
3869 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3870 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3871 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003872 }
3873
3874 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003875 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3876 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003877 }
3878};
3879
3880const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003881 nullptr, // reserved0
3882 nullptr, // reserved1
3883 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003884 CheckJII::DestroyJavaVM,
3885 CheckJII::AttachCurrentThread,
3886 CheckJII::DetachCurrentThread,
3887 CheckJII::GetEnv,
3888 CheckJII::AttachCurrentThreadAsDaemon
3889};
3890
3891const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3892 return &gCheckInvokeInterface;
3893}
3894
3895} // namespace art