blob: a980535c40d840b120694db0732888a06cc7e627 [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"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070039#include "scoped_thread_state_change.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_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700272 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
273 if (o == nullptr) {
274 AbortF("field operation on NULL object: %p", java_object);
275 return false;
276 }
277 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
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",
292 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
293 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])) {
321 AbortF("the return type of %s does not match %s", function_name_, PrettyMethod(m).c_str());
322 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",
328 PrettyMethod(m).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",
331 PrettyMethod(m).c_str(), function_name_);
332 }
333 return false;
334 }
335 if (invoke != kVirtual) {
336 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
337 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
338 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
339 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
340 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) {
344 mirror::Object* o = soa.Decode<mirror::Object*>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700345 if (o == nullptr) {
346 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
347 return false;
348 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700349 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
350 return false;
351 }
352 }
353 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700354 }
355
356 /*
357 * Verify that this static field ID is valid for this class.
358 *
359 * Assumes "java_class" has already been validated.
360 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700361 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700362 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700363 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700364 ArtField* f = CheckFieldID(soa, fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800365 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700366 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700367 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700368 if (f->GetDeclaringClass() != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700369 AbortF("static jfieldID %p not valid for class %s", fid, PrettyClass(c).c_str());
370 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700371 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700372 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700373 }
374
375 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700376 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700377 *
378 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700379 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 * allow bad code in the system though.
381 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700382 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700383 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700384 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700385 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700386 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800387 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700388 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700389 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700390 mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
Brian Carlstrom67fe2b42013-10-15 18:51:42 -0700391 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700392 AbortF("can't call static %s on class %s", PrettyMethod(m).c_str(), PrettyClass(c).c_str());
393 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700394 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700396 }
397
398 /*
399 * Verify that "mid" is appropriate for "jobj".
400 *
401 * Make sure the object is an instance of the method's declaring class.
402 * (Note the mid might point to a declaration in an interface; this
403 * will be handled automatically by the instanceof check.)
404 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700405 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700406 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700407 ArtMethod* m = CheckMethodID(soa, mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800408 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700409 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700410 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700411 mirror::Object* o = soa.Decode<mirror::Object*>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700412 if (o == nullptr) {
413 AbortF("can't call %s on null object", PrettyMethod(m).c_str());
414 return false;
415 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700416 AbortF("can't call %s on instance of %s", PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
417 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700418 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700419 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700420 }
421
422 /**
423 * The format string is a sequence of the following characters,
424 * and must be followed by arguments of the corresponding types
425 * in the same order.
426 *
427 * Java primitive types:
428 * B - jbyte
429 * C - jchar
430 * D - jdouble
431 * F - jfloat
432 * I - jint
433 * J - jlong
434 * S - jshort
435 * Z - jboolean (shown as true and false)
436 * V - void
437 *
438 * Java reference types:
439 * L - jobject
440 * a - jarray
441 * c - jclass
442 * s - jstring
443 *
444 * JNI types:
445 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
446 * f - jfieldID
447 * m - jmethodID
448 * p - void*
449 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700450 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700451 * z - jsize (for lengths; use i if negative values are okay)
452 * v - JavaVM*
453 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700454 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700455 *
456 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
457 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700458 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700459 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700460 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700461 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700462 // We need to guard some of the invocation interface's calls: a bad caller might
463 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700464 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800465 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
466 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700467 }
468 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700469
Ian Rogersef7d42f2014-01-06 12:55:46 -0800470 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700471 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700472 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700473 for (size_t i = 0; fmt[i] != '\0'; ++i) {
474 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
475 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700476 StringAppendF(&msg, ", ");
477 }
478 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700479
Elliott Hughes485cac42011-12-09 17:49:35 -0800480 if ((flags_ & kFlag_ForceTrace) != 0) {
481 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
482 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700483 if (has_method_) {
Elliott Hughesa0957642011-09-02 14:27:33 -0700484 std::string methodName(PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700485 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
486 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700487 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700488 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
489 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700490 }
491 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700492 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700493 }
494 }
495
496 // We always do the thorough checks on entry, and never on exit...
497 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700498 for (size_t i = 0; fmt[i] != '\0'; ++i) {
499 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
500 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700501 }
502 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700503 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700504 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700505 }
506
Ian Rogers68d8b422014-07-17 11:09:10 -0700507 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
508 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800509 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700510 // We need to guard some of the invocation interface's calls: a bad caller might
511 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
512 Thread* self = Thread::Current();
513 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
514 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700515 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700516 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
517 }
518 }
519 if (should_trace) {
520 std::string msg;
521 for (size_t i = 0; fmt[i] != '\0'; ++i) {
522 TraceNonHeapValue(fmt[i], args[i], &msg);
523 if (fmt[i + 1] != '\0') {
524 StringAppendF(&msg, ", ");
525 }
526 }
527
528 if ((flags_ & kFlag_ForceTrace) != 0) {
529 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
530 } else if (entry) {
531 if (has_method_) {
532 Thread* self = Thread::Current();
533 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700534 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700535 std::string methodName(PrettyMethod(traceMethod, false));
536 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
537 indent_ = methodName.size() + 1;
538 } else {
539 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
540 indent_ = 0;
541 }
542 } else {
543 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
544 }
545 }
546
547 // We always do the thorough checks on entry, and never on exit...
548 if (entry) {
549 for (size_t i = 0; fmt[i] != '\0'; ++i) {
550 if (!CheckNonHeapValue(fmt[i], args[i])) {
551 return false;
552 }
553 }
554 }
555 return true;
556 }
557
558 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700559 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700560 mirror::Object* method = soa.Decode<mirror::Object*>(jmethod);
561 if (method == nullptr) {
562 AbortF("expected non-null method");
563 return false;
564 }
565 mirror::Class* c = method->GetClass();
566 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Method) != c &&
567 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
568 AbortF("expected java.lang.reflect.Method or "
569 "java.lang.reflect.Constructor but got object of type %s: %p",
570 PrettyTypeOf(method).c_str(), jmethod);
571 return false;
572 }
573 return true;
574 }
575
576 bool CheckConstructor(ScopedObjectAccess& soa, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700577 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700578 ArtMethod* method = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700579 if (method == nullptr) {
580 AbortF("expected non-null constructor");
581 return false;
582 }
583 if (!method->IsConstructor() || method->IsStatic()) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700584 AbortF("expected a constructor but %s: %p", PrettyMethod(method).c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700585 return false;
586 }
587 return true;
588 }
589
590 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700591 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700592 mirror::Object* field = soa.Decode<mirror::Object*>(jfield);
593 if (field == nullptr) {
594 AbortF("expected non-null java.lang.reflect.Field");
595 return false;
596 }
597 mirror::Class* c = field->GetClass();
598 if (soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_reflect_Field) != c) {
599 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
600 PrettyTypeOf(field).c_str(), jfield);
601 return false;
602 }
603 return true;
604 }
605
606 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700607 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700608 mirror::Object* obj = soa.Decode<mirror::Object*>(jobj);
609 if (!obj->GetClass()->IsThrowableClass()) {
610 AbortF("expected java.lang.Throwable but got object of type "
611 "%s: %p", PrettyTypeOf(obj).c_str(), obj);
612 return false;
613 }
614 return true;
615 }
616
617 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700618 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700619 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
620 if (!c->IsThrowableClass()) {
621 AbortF("expected java.lang.Throwable class but got object of "
622 "type %s: %p", PrettyDescriptor(c).c_str(), c);
623 return false;
624 }
625 return true;
626 }
627
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700628 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700629 IndirectRefKind found_kind;
630 if (expected_kind == kLocal) {
631 found_kind = GetIndirectRefKind(obj);
632 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
633 found_kind = kLocal;
634 }
635 } else {
636 found_kind = GetIndirectRefKind(obj);
637 }
638 if (obj != nullptr && found_kind != expected_kind) {
639 AbortF("expected reference of kind %s but found %s: %p",
640 ToStr<IndirectRefKind>(expected_kind).c_str(),
641 ToStr<IndirectRefKind>(GetIndirectRefKind(obj)).c_str(),
642 obj);
643 return false;
644 }
645 return true;
646 }
647
648 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700649 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700650 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
651 if (!c->IsInstantiableNonArray()) {
652 AbortF("can't make objects of type %s: %p", PrettyDescriptor(c).c_str(), c);
653 return false;
654 }
655 return true;
656 }
657
658 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700659 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700660 if (!CheckArray(soa, array)) {
661 return false;
662 }
663 mirror::Array* a = soa.Decode<mirror::Array*>(array);
664 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
665 AbortF("incompatible array type %s expected %s[]: %p",
666 PrettyDescriptor(a->GetClass()).c_str(), PrettyDescriptor(type).c_str(), array);
667 return false;
668 }
669 return true;
670 }
671
672 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
673 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700674 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700675 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
676 return false;
677 }
678 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
679 return false;
680 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700681 ArtField* field = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700682 DCHECK(field != nullptr); // Already checked by Check.
683 if (is_static != field->IsStatic()) {
684 AbortF("attempt to access %s field %s: %p",
685 field->IsStatic() ? "static" : "non-static", PrettyField(field).c_str(), fid);
686 return false;
687 }
688 if (type != field->GetTypeAsPrimitiveType()) {
689 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
690 PrettyField(field).c_str(), PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
691 PrettyDescriptor(type).c_str(), fid);
692 return false;
693 }
694 if (is_static) {
695 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
696 if (o == nullptr || !o->IsClass()) {
697 AbortF("attempt to access static field %s with a class argument of type %s: %p",
698 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
699 return false;
700 }
701 mirror::Class* c = o->AsClass();
702 if (field->GetDeclaringClass() != c) {
703 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
704 PrettyField(field).c_str(), PrettyDescriptor(c).c_str(), fid);
705 return false;
706 }
707 } else {
708 mirror::Object* o = soa.Decode<mirror::Object*>(obj);
709 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
710 AbortF("attempt to access field %s from an object argument of type %s: %p",
711 PrettyField(field).c_str(), PrettyTypeOf(o).c_str(), fid);
712 return false;
713 }
714 }
715 return true;
716 }
717
718 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800719 enum InstanceKind {
720 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700721 kDirectByteBuffer,
722 kObject,
723 kString,
724 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800725 };
726
727 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700728 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800729 * an instance of expectedClass.
730 *
731 * Because we're looking at an object on the GC heap, we have to switch
732 * to "running" mode before doing the checks.
733 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700734 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700735 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800736 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800737 switch (kind) {
738 case kClass:
739 what = "jclass";
740 break;
741 case kDirectByteBuffer:
742 what = "direct ByteBuffer";
743 break;
744 case kObject:
745 what = "jobject";
746 break;
747 case kString:
748 what = "jstring";
749 break;
750 case kThrowable:
751 what = "jthrowable";
752 break;
753 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700754 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800755 }
756
Ian Rogersef7d42f2014-01-06 12:55:46 -0800757 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700758 if (null_ok) {
759 return true;
760 } else {
761 AbortF("%s received NULL %s", function_name_, what);
762 return false;
763 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800764 }
765
Ian Rogers68d8b422014-07-17 11:09:10 -0700766 mirror::Object* obj = soa.Decode<mirror::Object*>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700767 if (obj == nullptr) {
768 // Either java_object is invalid or is a cleared weak.
769 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
770 bool okay;
771 if (GetIndirectRefKind(ref) != kWeakGlobal) {
772 okay = false;
773 } else {
774 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
775 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
776 }
777 if (!okay) {
778 AbortF("%s is an invalid %s: %p (%p)",
779 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
780 java_object, obj);
781 return false;
782 }
783 }
784
Mathieu Chartier590fee92013-09-13 13:46:47 -0700785 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700786 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700787 AbortF("%s is an invalid %s: %p (%p)",
788 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(),
789 java_object, obj);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800790 return false;
791 }
792
793 bool okay = true;
794 switch (kind) {
795 case kClass:
796 okay = obj->IsClass();
797 break;
798 case kDirectByteBuffer:
799 UNIMPLEMENTED(FATAL);
800 break;
801 case kString:
802 okay = obj->GetClass()->IsStringClass();
803 break;
804 case kThrowable:
805 okay = obj->GetClass()->IsThrowableClass();
806 break;
807 case kObject:
808 break;
809 }
810 if (!okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700811 AbortF("%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800812 return false;
813 }
814
815 return true;
816 }
817
Ian Rogers68d8b422014-07-17 11:09:10 -0700818 /*
819 * Verify that the "mode" argument passed to a primitive array Release
820 * function is one of the valid values.
821 */
822 bool CheckReleaseMode(jint mode) {
823 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
824 AbortF("unknown value for release mode: %d", mode);
825 return false;
826 }
827 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700828 }
829
Ian Rogers68d8b422014-07-17 11:09:10 -0700830 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700831 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700832 switch (fmt) {
833 case 'a': // jarray
834 return CheckArray(soa, arg.a);
835 case 'c': // jclass
836 return CheckInstance(soa, kClass, arg.c, false);
837 case 'f': // jfieldID
838 return CheckFieldID(soa, arg.f) != nullptr;
839 case 'm': // jmethodID
840 return CheckMethodID(soa, arg.m) != nullptr;
841 case 'r': // release int
842 return CheckReleaseMode(arg.r);
843 case 's': // jstring
844 return CheckInstance(soa, kString, arg.s, false);
845 case 't': // jthrowable
846 return CheckInstance(soa, kThrowable, arg.t, false);
847 case 'E': // JNIEnv*
848 return CheckThread(arg.E);
849 case 'L': // jobject
850 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700851 case '.': // A VarArgs list
852 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700853 default:
854 return CheckNonHeapValue(fmt, arg);
855 }
856 }
857
Alex Light48ffe062015-08-19 15:23:23 -0700858 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700859 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700860 CHECK(args_p != nullptr);
861 VarArgs args(args_p->Clone());
862 ArtMethod* m = CheckMethodID(soa, args.GetMethodID());
863 if (m == nullptr) {
864 return false;
865 }
866 uint32_t len = 0;
867 const char* shorty = m->GetShorty(&len);
868 // Skip the return type
869 CHECK_GE(len, 1u);
870 len--;
871 shorty++;
872 for (uint32_t i = 0; i < len; i++) {
873 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
874 return false;
875 }
876 }
877 return true;
878 }
879
Ian Rogers68d8b422014-07-17 11:09:10 -0700880 bool CheckNonHeapValue(char fmt, JniValueType arg) {
881 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700882 case 'p': // TODO: pointer - null or readable?
883 case 'v': // JavaVM*
884 case 'B': // jbyte
885 case 'C': // jchar
886 case 'D': // jdouble
887 case 'F': // jfloat
888 case 'I': // jint
889 case 'J': // jlong
890 case 'S': // jshort
891 break; // Ignored.
892 case 'b': // jboolean, why two? Fall-through.
893 case 'Z':
894 return CheckBoolean(arg.Z);
895 case 'u': // utf8
896 if ((flags_ & kFlag_Release) != 0) {
897 return CheckNonNull(arg.u);
898 } else {
899 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
900 return CheckUtfString(arg.u, nullable);
901 }
902 case 'w': // jobjectRefType
903 switch (arg.w) {
904 case JNIInvalidRefType:
905 case JNILocalRefType:
906 case JNIGlobalRefType:
907 case JNIWeakGlobalRefType:
908 break;
909 default:
910 AbortF("Unknown reference type");
911 return false;
912 }
913 break;
914 case 'z': // jsize
915 return CheckLengthPositive(arg.z);
916 default:
917 AbortF("unknown format specifier: '%c'", fmt);
918 return false;
919 }
920 return true;
921 }
922
923 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
924 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700925 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700926 switch (fmt) {
927 case 'L': // jobject fall-through.
928 case 'a': // jarray fall-through.
929 case 's': // jstring fall-through.
930 case 't': // jthrowable fall-through.
931 if (arg.L == nullptr) {
932 *msg += "NULL";
933 } else {
934 StringAppendF(msg, "%p", arg.L);
935 }
936 break;
937 case 'c': { // jclass
938 jclass jc = arg.c;
939 mirror::Class* c = soa.Decode<mirror::Class*>(jc);
940 if (c == nullptr) {
941 *msg += "NULL";
Ian Rogersc0542af2014-09-03 16:16:56 -0700942 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700943 StringAppendF(msg, "INVALID POINTER:%p", jc);
944 } else if (!c->IsClass()) {
945 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
946 } else {
947 *msg += PrettyClass(c);
948 if (!entry) {
949 StringAppendF(msg, " (%p)", jc);
950 }
951 }
952 break;
953 }
954 case 'f': { // jfieldID
955 jfieldID fid = arg.f;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700956 ArtField* f = soa.DecodeField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700957 *msg += PrettyField(f);
958 if (!entry) {
959 StringAppendF(msg, " (%p)", fid);
960 }
961 break;
962 }
963 case 'm': { // jmethodID
964 jmethodID mid = arg.m;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700965 ArtMethod* m = soa.DecodeMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700966 *msg += PrettyMethod(m);
967 if (!entry) {
968 StringAppendF(msg, " (%p)", mid);
969 }
970 break;
971 }
Alex Light48ffe062015-08-19 15:23:23 -0700972 case '.': {
973 const VarArgs* va = arg.va;
974 VarArgs args(va->Clone());
975 ArtMethod* m = soa.DecodeMethod(args.GetMethodID());
976 uint32_t len;
977 const char* shorty = m->GetShorty(&len);
978 CHECK_GE(len, 1u);
979 // Skip past return value.
980 len--;
981 shorty++;
982 // Remove the previous ', ' from the message.
983 msg->erase(msg->length() - 2);
984 for (uint32_t i = 0; i < len; i++) {
985 *msg += ", ";
986 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
987 }
988 break;
989 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700990 default:
991 TraceNonHeapValue(fmt, arg, msg);
992 break;
993 }
994 }
995
996 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
997 switch (fmt) {
998 case 'B': // jbyte
999 if (arg.B >= 0 && arg.B < 10) {
1000 StringAppendF(msg, "%d", arg.B);
1001 } else {
1002 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1003 }
1004 break;
1005 case 'C': // jchar
1006 if (arg.C < 0x7f && arg.C >= ' ') {
1007 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1008 } else {
1009 StringAppendF(msg, "U+%x", arg.C);
1010 }
1011 break;
1012 case 'F': // jfloat
1013 StringAppendF(msg, "%g", arg.F);
1014 break;
1015 case 'D': // jdouble
1016 StringAppendF(msg, "%g", arg.D);
1017 break;
1018 case 'S': // jshort
1019 StringAppendF(msg, "%d", arg.S);
1020 break;
1021 case 'i': // jint - fall-through.
1022 case 'I': // jint
1023 StringAppendF(msg, "%d", arg.I);
1024 break;
1025 case 'J': // jlong
1026 StringAppendF(msg, "%" PRId64, arg.J);
1027 break;
1028 case 'Z': // jboolean
1029 case 'b': // jboolean (JNI-style)
1030 *msg += arg.b == JNI_TRUE ? "true" : "false";
1031 break;
1032 case 'V': // void
1033 DCHECK(arg.V == nullptr);
1034 *msg += "void";
1035 break;
1036 case 'v': // JavaVM*
1037 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1038 break;
1039 case 'E':
1040 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1041 break;
1042 case 'z': // non-negative jsize
1043 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1044 // We only treat this specially so we can do the non-negative check.
1045 // TODO: maybe this wasn't worth it?
1046 StringAppendF(msg, "%d", arg.z);
1047 break;
1048 case 'p': // void* ("pointer")
1049 if (arg.p == nullptr) {
1050 *msg += "NULL";
1051 } else {
1052 StringAppendF(msg, "(void*) %p", arg.p);
1053 }
1054 break;
1055 case 'r': { // jint (release mode)
1056 jint releaseMode = arg.r;
1057 if (releaseMode == 0) {
1058 *msg += "0";
1059 } else if (releaseMode == JNI_ABORT) {
1060 *msg += "JNI_ABORT";
1061 } else if (releaseMode == JNI_COMMIT) {
1062 *msg += "JNI_COMMIT";
1063 } else {
1064 StringAppendF(msg, "invalid release mode %d", releaseMode);
1065 }
1066 break;
1067 }
1068 case 'u': // const char* (Modified UTF-8)
1069 if (arg.u == nullptr) {
1070 *msg += "NULL";
1071 } else {
1072 StringAppendF(msg, "\"%s\"", arg.u);
1073 }
1074 break;
1075 case 'w': // jobjectRefType
1076 switch (arg.w) {
1077 case JNIInvalidRefType:
1078 *msg += "invalid reference type";
1079 break;
1080 case JNILocalRefType:
1081 *msg += "local ref type";
1082 break;
1083 case JNIGlobalRefType:
1084 *msg += "global ref type";
1085 break;
1086 case JNIWeakGlobalRefType:
1087 *msg += "weak global ref type";
1088 break;
1089 default:
1090 *msg += "unknown ref type";
1091 break;
1092 }
1093 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001094 default:
1095 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1096 }
1097 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001098 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001099 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001100 *
1101 * Since we're dealing with objects, switch to "running" mode.
1102 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001103 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001104 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001105 if (UNLIKELY(java_array == nullptr)) {
1106 AbortF("jarray was NULL");
1107 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001108 }
1109
Ian Rogers68d8b422014-07-17 11:09:10 -07001110 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1111 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001112 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001113 AbortF("jarray is an invalid %s: %p (%p)",
1114 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(),
1115 java_array, a);
1116 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001117 } else if (!a->IsArrayInstance()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001118 AbortF("jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
1119 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001120 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001121 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001122 }
1123
Ian Rogers68d8b422014-07-17 11:09:10 -07001124 bool CheckBoolean(jboolean z) {
1125 if (z != JNI_TRUE && z != JNI_FALSE) {
1126 AbortF("unexpected jboolean value: %d", z);
1127 return false;
1128 }
1129 return true;
1130 }
1131
1132 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001133 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001134 AbortF("negative jsize: %d", length);
1135 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001136 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001137 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001138 }
1139
Mathieu Chartierc7853442015-03-27 14:35:38 -07001140 ArtField* CheckFieldID(ScopedObjectAccess& soa, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001141 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001142 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001143 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001144 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001145 }
Mathieu Chartierc7853442015-03-27 14:35:38 -07001146 ArtField* f = soa.DecodeField(fid);
1147 // TODO: Better check here.
1148 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001149 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001150 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001151 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001152 }
1153 return f;
1154 }
1155
Mathieu Chartiere401d142015-04-22 13:56:20 -07001156 ArtMethod* CheckMethodID(ScopedObjectAccess& soa, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001157 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001158 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001159 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001160 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001161 }
Mathieu Chartiere401d142015-04-22 13:56:20 -07001162 ArtMethod* m = soa.DecodeMethod(mid);
1163 // TODO: Better check here.
1164 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001165 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001166 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001167 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001168 }
1169 return m;
1170 }
1171
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001172 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001173 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001174 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001175 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1176 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001177 }
1178
Daniel Erat35e827a2016-05-10 18:07:18 -06001179 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001180 JNIEnvExt* threadEnv = self->GetJniEnv();
1181
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001182 // Verify that the current thread is (a) attached and (b) associated with
1183 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001184 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001185 // Get the thread owning the JNIEnv that's being used.
1186 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001187 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001188 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001189 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001190 }
1191
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001192 // Verify that, if this thread previously made a critical "get" call, we
1193 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001194 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001195 case kFlag_CritOkay: // okay to call this method
1196 break;
1197 case kFlag_CritBad: // not okay to call
1198 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001199 AbortF("thread %s using JNI after critical get",
1200 ToStr<Thread>(*self).c_str());
1201 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001202 }
1203 break;
1204 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001205 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001206 threadEnv->critical++;
1207 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001208 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001209 threadEnv->critical--;
1210 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001211 AbortF("thread %s called too many critical releases",
1212 ToStr<Thread>(*self).c_str());
1213 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001214 }
1215 break;
1216 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001217 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001218 }
1219
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001220 // Verify that, if an exception has been raised, the native code doesn't
1221 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001222 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001223 mirror::Throwable* exception = self->GetException();
1224 AbortF("JNI %s called with pending exception %s",
1225 function_name_,
1226 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001227 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001228 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001229 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001230 }
1231
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001232 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001233 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001234 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001235 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001236 AbortF("non-nullable const char* was NULL");
1237 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001238 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001239 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001240 }
1241
Ian Rogersef7d42f2014-01-06 12:55:46 -08001242 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001243 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001244 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001245 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1246 // practice anyways.
1247 std::ostringstream oss;
1248 oss << std::hex;
1249 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1250 while (*tmp != 0) {
1251 if (tmp == utf8) {
1252 oss << "<";
1253 }
1254 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1255 if (tmp == utf8) {
1256 oss << '>';
1257 }
1258 tmp++;
1259 if (*tmp != 0) {
1260 oss << ' ';
1261 }
1262 }
1263
Ian Rogers68d8b422014-07-17 11:09:10 -07001264 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001265 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001266 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001267 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001268 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001269 }
1270
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001271 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1272 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001273 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001274 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001275 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001276 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001277 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001278 case 0x00:
1279 case 0x01:
1280 case 0x02:
1281 case 0x03:
1282 case 0x04:
1283 case 0x05:
1284 case 0x06:
1285 case 0x07:
1286 // Bit pattern 0xxx. No need for any extra bytes.
1287 break;
1288 case 0x08:
1289 case 0x09:
1290 case 0x0a:
1291 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001292 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001293 *errorKind = "start";
1294 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001295 case 0x0f:
1296 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001297 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001298 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1299 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001300 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1301 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001302 *errorKind = "continuation";
1303 return utf8;
1304 }
1305 } else {
1306 *errorKind = "start";
1307 return utf8;
1308 }
1309
1310 // Fall through to the cases below to consume two more continuation bytes.
1311 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001312 case 0x0e:
1313 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001314 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1315 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001316 *errorKind = "continuation";
1317 return utf8;
1318 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001319
1320 // Fall through to consume one more continuation byte.
1321 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001322 case 0x0c:
1323 case 0x0d:
1324 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001325 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1326 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001327 *errorKind = "continuation";
1328 return utf8;
1329 }
1330 break;
1331 }
1332 }
1333 return 0;
1334 }
1335
Ian Rogers68d8b422014-07-17 11:09:10 -07001336 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1337 va_list args;
1338 va_start(args, fmt);
1339 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1340 va_end(args);
1341 }
1342
1343 // The name of the JNI function being checked.
1344 const char* const function_name_;
1345
1346 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001347 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001348
Ian Rogers68d8b422014-07-17 11:09:10 -07001349 const bool has_method_;
1350
Elliott Hughesa2501992011-08-26 19:39:54 -07001351 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1352};
1353
Elliott Hughesa2501992011-08-26 19:39:54 -07001354/*
1355 * ===========================================================================
1356 * Guarded arrays
1357 * ===========================================================================
1358 */
1359
Elliott Hughesa2501992011-08-26 19:39:54 -07001360/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001361class GuardedCopy {
1362 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001363 /*
1364 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1365 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001366 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001367 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001368 const size_t new_len = LengthIncludingRedZones(len);
1369 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001370
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001371 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001372 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001373 if (!mod_okay) {
1374 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001375 }
1376
Ian Rogers68d8b422014-07-17 11:09:10 -07001377 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001378
Ian Rogers68d8b422014-07-17 11:09:10 -07001379 // Fill begin region with canary pattern.
1380 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1381 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1382 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1383 if (kCanary[j] == '\0') {
1384 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001385 } else {
1386 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001387 }
1388 }
1389
1390 // Copy the data in; note "len" could be zero.
1391 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1392
1393 // Fill end region with canary pattern.
1394 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1395 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1396 if (kCanary[j] == '\0') {
1397 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001398 } else {
1399 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001400 }
1401 }
1402
1403 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001404 }
1405
1406 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001407 * Create a guarded copy of a primitive array. Modifications to the copied
1408 * data are allowed. Returns a pointer to the copied data.
1409 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001410 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1411 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001412 ScopedObjectAccess soa(env);
1413
1414 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1415 size_t component_size = a->GetClass()->GetComponentSize();
1416 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001417 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001418 if (is_copy != nullptr) {
1419 *is_copy = JNI_TRUE;
1420 }
1421 return result;
1422 }
1423
1424 /*
1425 * Perform the array "release" operation, which may or may not copy data
1426 * back into the managed heap, and may or may not release the underlying storage.
1427 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001428 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1429 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1430 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001431 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001432 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1433 return nullptr;
1434 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001435 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1436 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001437 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001438 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001439 }
1440 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001441 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001442 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001443 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 }
1445
1446
1447 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001448 * Free up the guard buffer, scrub it, and return the original pointer.
1449 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001450 static void* Destroy(void* embedded_buf) {
1451 GuardedCopy* copy = FromEmbedded(embedded_buf);
1452 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1453 size_t len = LengthIncludingRedZones(copy->original_length_);
1454 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001455 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001456 }
1457
1458 /*
1459 * Verify the guard area and, if "modOkay" is false, that the data itself
1460 * has not been altered.
1461 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001462 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001463 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001464 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1465 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1466 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001467 }
1468
1469 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001470 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001471 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1472 }
1473
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001474 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001475 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001476 if (result == MAP_FAILED) {
1477 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1478 }
1479 return reinterpret_cast<uint8_t*>(result);
1480 }
1481
Ian Rogers68d8b422014-07-17 11:09:10 -07001482 static void DebugFree(void* buf, size_t len) {
1483 if (munmap(buf, len) != 0) {
1484 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001485 }
1486 }
1487
Ian Rogers68d8b422014-07-17 11:09:10 -07001488 static size_t LengthIncludingRedZones(size_t len) {
1489 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001490 }
1491
Ian Rogers68d8b422014-07-17 11:09:10 -07001492 // Get the GuardedCopy from the interior pointer.
1493 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1494 return reinterpret_cast<GuardedCopy*>(
1495 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001496 }
1497
Ian Rogers68d8b422014-07-17 11:09:10 -07001498 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1499 return reinterpret_cast<const GuardedCopy*>(
1500 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001501 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001502
1503 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1504 va_list args;
1505 va_start(args, fmt);
1506 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1507 va_end(args);
1508 }
1509
1510 bool CheckHeader(const char* function_name, bool mod_okay) const {
1511 static const uint32_t kMagicCmp = kGuardMagic;
1512
1513 // Before we do anything with "pExtra", check the magic number. We
1514 // do the check with memcmp rather than "==" in case the pointer is
1515 // unaligned. If it points to completely bogus memory we're going
1516 // to crash, but there's no easy way around that.
1517 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1518 uint8_t buf[4];
1519 memcpy(buf, &magic_, 4);
1520 AbortF(function_name,
1521 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1522 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1523 return false;
1524 }
1525
1526 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1527 // told the client that we made a copy, there's no reason they can't alter the buffer.
1528 if (!mod_okay) {
1529 uLong computed_adler =
1530 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1531 if (computed_adler != adler_) {
1532 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1533 computed_adler, adler_, this);
1534 return false;
1535 }
1536 }
1537 return true;
1538 }
1539
1540 bool CheckRedZones(const char* function_name) const {
1541 // Check the begin red zone.
1542 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1543 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1544 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1545 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1546 return false;
1547 }
1548 if (kCanary[j] == '\0') {
1549 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001550 } else {
1551 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001552 }
1553 }
1554
1555 // Check end region.
1556 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1557 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1558 size_t offset_from_buffer_start =
1559 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1560 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1561 offset_from_buffer_start);
1562 return false;
1563 }
1564 if (kCanary[j] == '\0') {
1565 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001566 } else {
1567 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001568 }
1569 }
1570 return true;
1571 }
1572
1573 // Location that canary value will be written before the guarded region.
1574 const char* StartRedZone() const {
1575 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1576 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1577 }
1578
1579 // Return the interior embedded buffer.
1580 const uint8_t* BufferWithinRedZones() const {
1581 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1582 return embedded_buf;
1583 }
1584
1585 // Location that canary value will be written after the guarded region.
1586 const char* EndRedZone() const {
1587 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1588 size_t buf_len = LengthIncludingRedZones(original_length_);
1589 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1590 }
1591
1592 static constexpr size_t kRedZoneSize = 512;
1593 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1594
1595 // Value written before and after the guarded array.
1596 static const char* const kCanary;
1597
1598 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1599
1600 const uint32_t magic_;
1601 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001602 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001603 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001604};
Ian Rogers68d8b422014-07-17 11:09:10 -07001605const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001606
1607/*
1608 * ===========================================================================
1609 * JNI functions
1610 * ===========================================================================
1611 */
1612
1613class CheckJNI {
1614 public:
1615 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001616 ScopedObjectAccess soa(env);
1617 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1618 JniValueType args[1] = {{.E = env }};
1619 if (sc.Check(soa, true, "E", args)) {
1620 JniValueType result;
1621 result.I = baseEnv(env)->GetVersion(env);
1622 if (sc.Check(soa, false, "I", &result)) {
1623 return result.I;
1624 }
1625 }
1626 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001627 }
1628
Ian Rogers68d8b422014-07-17 11:09:10 -07001629 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1630 ScopedObjectAccess soa(env);
1631 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1632 JniValueType args[2] = {{.E = env }, {.p = vm}};
1633 if (sc.Check(soa, true, "Ep", args)) {
1634 JniValueType result;
1635 result.i = baseEnv(env)->GetJavaVM(env, vm);
1636 if (sc.Check(soa, false, "i", &result)) {
1637 return result.i;
1638 }
1639 }
1640 return JNI_ERR;
1641 }
1642
1643 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1644 ScopedObjectAccess soa(env);
1645 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1646 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1647 if (sc.Check(soa, true, "EcpI", args)) {
1648 JniValueType result;
1649 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1650 if (sc.Check(soa, false, "i", &result)) {
1651 return result.i;
1652 }
1653 }
1654 return JNI_ERR;
1655 }
1656
1657 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1658 ScopedObjectAccess soa(env);
1659 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1660 JniValueType args[2] = {{.E = env }, {.c = c}};
1661 if (sc.Check(soa, true, "Ec", args)) {
1662 JniValueType result;
1663 result.i = baseEnv(env)->UnregisterNatives(env, c);
1664 if (sc.Check(soa, false, "i", &result)) {
1665 return result.i;
1666 }
1667 }
1668 return JNI_ERR;
1669 }
1670
1671 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001672 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1673 // know the object is invalid. The spec says that passing invalid objects or even ones that
1674 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001675 ScopedObjectAccess soa(env);
1676 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001677 JniValueType args[2] = {{.E = env }, {.L = obj}};
1678 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001679 JniValueType result;
1680 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1681 if (sc.Check(soa, false, "w", &result)) {
1682 return result.w;
1683 }
1684 }
1685 return JNIInvalidRefType;
1686 }
1687
1688 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1689 jsize bufLen) {
1690 ScopedObjectAccess soa(env);
1691 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1692 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1693 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1694 JniValueType result;
1695 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1696 if (sc.Check(soa, false, "c", &result)) {
1697 return result.c;
1698 }
1699 }
1700 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001701 }
1702
1703 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001704 ScopedObjectAccess soa(env);
1705 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1706 JniValueType args[2] = {{.E = env}, {.u = name}};
1707 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1708 JniValueType result;
1709 result.c = baseEnv(env)->FindClass(env, name);
1710 if (sc.Check(soa, false, "c", &result)) {
1711 return result.c;
1712 }
1713 }
1714 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001715 }
1716
Elliott Hughese84278b2012-03-22 10:06:53 -07001717 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001718 ScopedObjectAccess soa(env);
1719 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1720 JniValueType args[2] = {{.E = env}, {.c = c}};
1721 if (sc.Check(soa, true, "Ec", args)) {
1722 JniValueType result;
1723 result.c = baseEnv(env)->GetSuperclass(env, c);
1724 if (sc.Check(soa, false, "c", &result)) {
1725 return result.c;
1726 }
1727 }
1728 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001729 }
1730
Elliott Hughese84278b2012-03-22 10:06:53 -07001731 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001732 ScopedObjectAccess soa(env);
1733 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1734 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1735 if (sc.Check(soa, true, "Ecc", args)) {
1736 JniValueType result;
1737 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1738 if (sc.Check(soa, false, "b", &result)) {
1739 return result.b;
1740 }
1741 }
1742 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001743 }
1744
1745 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001746 ScopedObjectAccess soa(env);
1747 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1748 JniValueType args[2] = {{.E = env}, {.L = method}};
1749 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1750 JniValueType result;
1751 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1752 if (sc.Check(soa, false, "m", &result)) {
1753 return result.m;
1754 }
1755 }
1756 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001757 }
1758
1759 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001760 ScopedObjectAccess soa(env);
1761 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1762 JniValueType args[2] = {{.E = env}, {.L = field}};
1763 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1764 JniValueType result;
1765 result.f = baseEnv(env)->FromReflectedField(env, field);
1766 if (sc.Check(soa, false, "f", &result)) {
1767 return result.f;
1768 }
1769 }
1770 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001771 }
1772
1773 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001774 ScopedObjectAccess soa(env);
1775 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1776 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1777 if (sc.Check(soa, true, "Ecmb", args)) {
1778 JniValueType result;
1779 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1780 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1781 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1782 return result.L;
1783 }
1784 }
1785 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001786 }
1787
1788 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001789 ScopedObjectAccess soa(env);
1790 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1791 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1792 if (sc.Check(soa, true, "Ecfb", args)) {
1793 JniValueType result;
1794 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1795 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1796 DCHECK(sc.CheckReflectedField(soa, result.L));
1797 return result.L;
1798 }
1799 }
1800 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001801 }
1802
1803 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001804 ScopedObjectAccess soa(env);
1805 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1806 JniValueType args[2] = {{.E = env}, {.t = obj}};
1807 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1808 JniValueType result;
1809 result.i = baseEnv(env)->Throw(env, obj);
1810 if (sc.Check(soa, false, "i", &result)) {
1811 return result.i;
1812 }
1813 }
1814 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001815 }
1816
Elliott Hughese84278b2012-03-22 10:06:53 -07001817 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001818 ScopedObjectAccess soa(env);
1819 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001820 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001821 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1822 JniValueType result;
1823 result.i = baseEnv(env)->ThrowNew(env, c, message);
1824 if (sc.Check(soa, false, "i", &result)) {
1825 return result.i;
1826 }
1827 }
1828 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001829 }
1830
1831 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001832 ScopedObjectAccess soa(env);
1833 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1834 JniValueType args[1] = {{.E = env}};
1835 if (sc.Check(soa, true, "E", args)) {
1836 JniValueType result;
1837 result.t = baseEnv(env)->ExceptionOccurred(env);
1838 if (sc.Check(soa, false, "t", &result)) {
1839 return result.t;
1840 }
1841 }
1842 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001843 }
1844
1845 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001846 ScopedObjectAccess soa(env);
1847 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1848 JniValueType args[1] = {{.E = env}};
1849 if (sc.Check(soa, true, "E", args)) {
1850 JniValueType result;
1851 baseEnv(env)->ExceptionDescribe(env);
1852 result.V = nullptr;
1853 sc.Check(soa, false, "V", &result);
1854 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001855 }
1856
1857 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001858 ScopedObjectAccess soa(env);
1859 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1860 JniValueType args[1] = {{.E = env}};
1861 if (sc.Check(soa, true, "E", args)) {
1862 JniValueType result;
1863 baseEnv(env)->ExceptionClear(env);
1864 result.V = nullptr;
1865 sc.Check(soa, false, "V", &result);
1866 }
1867 }
1868
1869 static jboolean ExceptionCheck(JNIEnv* env) {
1870 ScopedObjectAccess soa(env);
1871 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1872 JniValueType args[1] = {{.E = env}};
1873 if (sc.Check(soa, true, "E", args)) {
1874 JniValueType result;
1875 result.b = baseEnv(env)->ExceptionCheck(env);
1876 if (sc.Check(soa, false, "b", &result)) {
1877 return result.b;
1878 }
1879 }
1880 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001881 }
1882
1883 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001884 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1885 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1886 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001887 ScopedObjectAccess soa(env);
1888 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1889 JniValueType args[2] = {{.E = env}, {.u = msg}};
1890 if (sc.Check(soa, true, "Eu", args)) {
1891 JniValueType result;
1892 baseEnv(env)->FatalError(env, msg);
1893 // Unreachable.
1894 result.V = nullptr;
1895 sc.Check(soa, false, "V", &result);
1896 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001897 }
1898
1899 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001900 ScopedObjectAccess soa(env);
1901 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1902 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1903 if (sc.Check(soa, true, "EI", args)) {
1904 JniValueType result;
1905 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1906 if (sc.Check(soa, false, "i", &result)) {
1907 return result.i;
1908 }
1909 }
1910 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001911 }
1912
1913 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001914 ScopedObjectAccess soa(env);
1915 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1916 JniValueType args[2] = {{.E = env}, {.L = res}};
1917 if (sc.Check(soa, true, "EL", args)) {
1918 JniValueType result;
1919 result.L = baseEnv(env)->PopLocalFrame(env, res);
1920 sc.Check(soa, false, "L", &result);
1921 return result.L;
1922 }
1923 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001924 }
1925
1926 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001927 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001928 }
1929
Ian Rogers68d8b422014-07-17 11:09:10 -07001930 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1931 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001932 }
1933
1934 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001935 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001936 }
1937
Ian Rogers68d8b422014-07-17 11:09:10 -07001938 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1939 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001940 }
1941
Ian Rogers68d8b422014-07-17 11:09:10 -07001942 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1943 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1944 }
1945
1946 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1947 DeleteRef(__FUNCTION__, env, obj, kLocal);
1948 }
1949
1950 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1951 ScopedObjectAccess soa(env);
1952 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1953 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1954 if (sc.Check(soa, true, "EI", args)) {
1955 JniValueType result;
1956 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1957 if (sc.Check(soa, false, "i", &result)) {
1958 return result.i;
1959 }
1960 }
1961 return JNI_ERR;
1962 }
1963
1964 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1965 ScopedObjectAccess soa(env);
1966 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1967 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1968 if (sc.Check(soa, true, "ELL", args)) {
1969 JniValueType result;
1970 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1971 if (sc.Check(soa, false, "b", &result)) {
1972 return result.b;
1973 }
1974 }
1975 return JNI_FALSE;
1976 }
1977
1978 static jobject AllocObject(JNIEnv* env, jclass c) {
1979 ScopedObjectAccess soa(env);
1980 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1981 JniValueType args[2] = {{.E = env}, {.c = c}};
1982 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1983 JniValueType result;
1984 result.L = baseEnv(env)->AllocObject(env, c);
1985 if (sc.Check(soa, false, "L", &result)) {
1986 return result.L;
1987 }
1988 }
1989 return nullptr;
1990 }
1991
1992 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
1993 ScopedObjectAccess soa(env);
1994 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07001995 VarArgs rest(mid, vargs);
1996 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
1997 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07001998 sc.CheckConstructor(soa, mid)) {
1999 JniValueType result;
2000 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2001 if (sc.Check(soa, false, "L", &result)) {
2002 return result.L;
2003 }
2004 }
2005 return nullptr;
2006 }
2007
2008 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2009 va_list args;
2010 va_start(args, mid);
2011 jobject result = NewObjectV(env, c, mid, args);
2012 va_end(args);
2013 return result;
2014 }
2015
2016 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2017 ScopedObjectAccess soa(env);
2018 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002019 VarArgs rest(mid, vargs);
2020 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2021 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002022 sc.CheckConstructor(soa, mid)) {
2023 JniValueType result;
2024 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2025 if (sc.Check(soa, false, "L", &result)) {
2026 return result.L;
2027 }
2028 }
2029 return nullptr;
2030 }
2031
2032 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2033 ScopedObjectAccess soa(env);
2034 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2035 JniValueType args[2] = {{.E = env}, {.L = obj}};
2036 if (sc.Check(soa, true, "EL", args)) {
2037 JniValueType result;
2038 result.c = baseEnv(env)->GetObjectClass(env, obj);
2039 if (sc.Check(soa, false, "c", &result)) {
2040 return result.c;
2041 }
2042 }
2043 return nullptr;
2044 }
2045
2046 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2047 ScopedObjectAccess soa(env);
2048 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2049 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2050 if (sc.Check(soa, true, "ELc", args)) {
2051 JniValueType result;
2052 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2053 if (sc.Check(soa, false, "b", &result)) {
2054 return result.b;
2055 }
2056 }
2057 return JNI_FALSE;
2058 }
2059
2060 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2061 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2062 }
2063
2064 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2065 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2066 }
2067
2068 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2069 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2070 }
2071
2072 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2073 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2074 }
2075
2076#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2077 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2078 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2079 } \
2080 \
2081 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2082 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2083 } \
2084 \
2085 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2086 JniValueType value; \
2087 value.shorty = v; \
2088 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2089 } \
2090 \
2091 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2092 JniValueType value; \
2093 value.shorty = v; \
2094 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2095 }
2096
2097 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2098 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2099 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2100 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2101 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2102 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2103 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2104 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2105 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2106#undef FIELD_ACCESSORS
2107
2108 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2109 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2110 }
2111
2112 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2113 jvalue* vargs) {
2114 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2115 }
2116
2117 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002118 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002119 }
2120
2121 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2122 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2123 }
2124
2125 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2126 va_list vargs) {
2127 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2128 }
2129
2130 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2131 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2132 }
2133
2134 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2135 va_list vargs;
2136 va_start(vargs, mid);
2137 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2138 va_end(vargs);
2139 }
2140
2141 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2142 va_list vargs;
2143 va_start(vargs, mid);
2144 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2145 va_end(vargs);
2146 }
2147
2148 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2149 va_list vargs;
2150 va_start(vargs, mid);
2151 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2152 va_end(vargs);
2153 }
2154
2155#define CALL(rtype, name, ptype, shorty) \
2156 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2157 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2158 } \
2159 \
2160 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2161 jvalue* vargs) { \
2162 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2163 } \
2164 \
2165 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2166 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2167 } \
2168 \
2169 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2170 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2171 } \
2172 \
2173 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2174 va_list vargs) { \
2175 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2176 } \
2177 \
2178 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2179 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2180 } \
2181 \
2182 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2183 va_list vargs; \
2184 va_start(vargs, mid); \
2185 rtype result = \
2186 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2187 va_end(vargs); \
2188 return result; \
2189 } \
2190 \
2191 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2192 ...) { \
2193 va_list vargs; \
2194 va_start(vargs, mid); \
2195 rtype result = \
2196 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2197 va_end(vargs); \
2198 return result; \
2199 } \
2200 \
2201 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2202 va_list vargs; \
2203 va_start(vargs, mid); \
2204 rtype result = \
2205 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2206 va_end(vargs); \
2207 return result; \
2208 }
2209
2210 CALL(jobject, Object, Primitive::kPrimNot, L)
2211 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2212 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2213 CALL(jchar, Char, Primitive::kPrimChar, C)
2214 CALL(jshort, Short, Primitive::kPrimShort, S)
2215 CALL(jint, Int, Primitive::kPrimInt, I)
2216 CALL(jlong, Long, Primitive::kPrimLong, J)
2217 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2218 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2219#undef CALL
2220
2221 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2222 ScopedObjectAccess soa(env);
2223 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2224 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2225 if (sc.Check(soa, true, "Epz", args)) {
2226 JniValueType result;
2227 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2228 if (sc.Check(soa, false, "s", &result)) {
2229 return result.s;
2230 }
2231 }
2232 return nullptr;
2233 }
2234
2235 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2236 ScopedObjectAccess soa(env);
2237 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2238 JniValueType args[2] = {{.E = env}, {.u = chars}};
2239 if (sc.Check(soa, true, "Eu", args)) {
2240 JniValueType result;
2241 // TODO: stale? show pointer and truncate string.
2242 result.s = baseEnv(env)->NewStringUTF(env, chars);
2243 if (sc.Check(soa, false, "s", &result)) {
2244 return result.s;
2245 }
2246 }
2247 return nullptr;
2248 }
2249
2250 static jsize GetStringLength(JNIEnv* env, jstring string) {
2251 ScopedObjectAccess soa(env);
2252 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2253 JniValueType args[2] = {{.E = env}, {.s = string}};
2254 if (sc.Check(soa, true, "Es", args)) {
2255 JniValueType result;
2256 result.z = baseEnv(env)->GetStringLength(env, string);
2257 if (sc.Check(soa, false, "z", &result)) {
2258 return result.z;
2259 }
2260 }
2261 return JNI_ERR;
2262 }
2263
2264 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2265 ScopedObjectAccess soa(env);
2266 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2267 JniValueType args[2] = {{.E = env}, {.s = string}};
2268 if (sc.Check(soa, true, "Es", args)) {
2269 JniValueType result;
2270 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2271 if (sc.Check(soa, false, "z", &result)) {
2272 return result.z;
2273 }
2274 }
2275 return JNI_ERR;
2276 }
2277
2278 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2279 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2280 is_copy, false, false));
2281 }
2282
2283 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2284 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2285 is_copy, true, false));
2286 }
2287
2288 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2289 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2290 is_copy, false, true));
2291 }
2292
2293 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2294 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2295 }
2296
2297 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2298 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2299 }
2300
2301 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2302 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2303 }
2304
2305 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2306 ScopedObjectAccess soa(env);
2307 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2308 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2309 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2310 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2311 if (sc.Check(soa, true, "EsIIp", args)) {
2312 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2313 JniValueType result;
2314 result.V = nullptr;
2315 sc.Check(soa, false, "V", &result);
2316 }
2317 }
2318
2319 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2320 ScopedObjectAccess soa(env);
2321 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2322 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2323 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2324 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2325 if (sc.Check(soa, true, "EsIIp", args)) {
2326 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2327 JniValueType result;
2328 result.V = nullptr;
2329 sc.Check(soa, false, "V", &result);
2330 }
2331 }
2332
2333 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2334 ScopedObjectAccess soa(env);
2335 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2336 JniValueType args[2] = {{.E = env}, {.a = array}};
2337 if (sc.Check(soa, true, "Ea", args)) {
2338 JniValueType result;
2339 result.z = baseEnv(env)->GetArrayLength(env, array);
2340 if (sc.Check(soa, false, "z", &result)) {
2341 return result.z;
2342 }
2343 }
2344 return JNI_ERR;
2345 }
2346
2347 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2348 jobject initial_element) {
2349 ScopedObjectAccess soa(env);
2350 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2351 JniValueType args[4] =
2352 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2353 if (sc.Check(soa, true, "EzcL", args)) {
2354 JniValueType result;
2355 // Note: assignability tests of initial_element are done in the base implementation.
2356 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2357 if (sc.Check(soa, false, "a", &result)) {
2358 return down_cast<jobjectArray>(result.a);
2359 }
2360 }
2361 return nullptr;
2362 }
2363
2364 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2365 ScopedObjectAccess soa(env);
2366 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2367 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2368 if (sc.Check(soa, true, "Eaz", args)) {
2369 JniValueType result;
2370 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2371 if (sc.Check(soa, false, "L", &result)) {
2372 return result.L;
2373 }
2374 }
2375 return nullptr;
2376 }
2377
2378 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2379 ScopedObjectAccess soa(env);
2380 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2381 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2382 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2383 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2384 // in ArrayStoreExceptions.
2385 if (sc.Check(soa, true, "EaIL", args)) {
2386 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2387 JniValueType result;
2388 result.V = nullptr;
2389 sc.Check(soa, false, "V", &result);
2390 }
2391 }
2392
2393 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2394 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2395 Primitive::kPrimBoolean));
2396 }
2397
2398 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2399 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2400 Primitive::kPrimByte));
2401 }
2402
2403 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2404 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2405 Primitive::kPrimChar));
2406 }
2407
2408 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2409 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2410 Primitive::kPrimShort));
2411 }
2412
2413 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2414 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2415 }
2416
2417 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2418 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2419 Primitive::kPrimLong));
2420 }
2421
2422 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2423 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2424 Primitive::kPrimFloat));
2425 }
2426
2427 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2428 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2429 Primitive::kPrimDouble));
2430 }
2431
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002432// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002433#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002434 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2435 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002436 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2437 } \
2438 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002439 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002440 jint mode) { \
2441 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2442 } \
2443 \
2444 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002445 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002446 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2447 } \
2448 \
2449 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2450 const ctype* buf) { \
2451 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2452 }
2453
2454 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2455 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2456 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2457 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2458 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2459 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2460 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2461 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2462#undef PRIMITIVE_ARRAY_FUNCTIONS
2463
2464 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2465 ScopedObjectAccess soa(env);
2466 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2467 JniValueType args[2] = {{.E = env}, {.L = obj}};
2468 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002469 if (obj != nullptr) {
2470 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2471 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002472 JniValueType result;
2473 result.i = baseEnv(env)->MonitorEnter(env, obj);
2474 if (sc.Check(soa, false, "i", &result)) {
2475 return result.i;
2476 }
2477 }
2478 return JNI_ERR;
2479 }
2480
2481 static jint MonitorExit(JNIEnv* env, jobject obj) {
2482 ScopedObjectAccess soa(env);
2483 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2484 JniValueType args[2] = {{.E = env}, {.L = obj}};
2485 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002486 if (obj != nullptr) {
2487 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2488 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002489 JniValueType result;
2490 result.i = baseEnv(env)->MonitorExit(env, obj);
2491 if (sc.Check(soa, false, "i", &result)) {
2492 return result.i;
2493 }
2494 }
2495 return JNI_ERR;
2496 }
2497
2498 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2499 ScopedObjectAccess soa(env);
2500 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2501 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2502 if (sc.Check(soa, true, "Eap", args)) {
2503 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002504 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2505 if (ptr != nullptr && soa.ForceCopy()) {
2506 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002507 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002508 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002509 if (sc.Check(soa, false, "p", &result)) {
2510 return const_cast<void*>(result.p);
2511 }
2512 }
2513 return nullptr;
2514 }
2515
2516 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2517 ScopedObjectAccess soa(env);
2518 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2519 sc.CheckNonNull(carray);
2520 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2521 if (sc.Check(soa, true, "Eapr", args)) {
2522 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002523 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002524 }
2525 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2526 JniValueType result;
2527 result.V = nullptr;
2528 sc.Check(soa, false, "V", &result);
2529 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002530 }
2531
2532 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002533 ScopedObjectAccess soa(env);
2534 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2535 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2536 if (sc.Check(soa, true, "EpJ", args)) {
2537 JniValueType result;
2538 // Note: the validity of address and capacity are checked in the base implementation.
2539 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2540 if (sc.Check(soa, false, "L", &result)) {
2541 return result.L;
2542 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002543 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002544 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002545 }
2546
2547 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002548 ScopedObjectAccess soa(env);
2549 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2550 JniValueType args[2] = {{.E = env}, {.L = buf}};
2551 if (sc.Check(soa, true, "EL", args)) {
2552 JniValueType result;
2553 // Note: this is implemented in the base environment by a GetLongField which will sanity
2554 // check the type of buf in GetLongField above.
2555 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2556 if (sc.Check(soa, false, "p", &result)) {
2557 return const_cast<void*>(result.p);
2558 }
2559 }
2560 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002561 }
2562
2563 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002564 ScopedObjectAccess soa(env);
2565 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2566 JniValueType args[2] = {{.E = env}, {.L = buf}};
2567 if (sc.Check(soa, true, "EL", args)) {
2568 JniValueType result;
2569 // Note: this is implemented in the base environment by a GetIntField which will sanity
2570 // check the type of buf in GetIntField above.
2571 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2572 if (sc.Check(soa, false, "J", &result)) {
2573 return result.J;
2574 }
2575 }
2576 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002577 }
2578
2579 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002580 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2581 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2582 }
2583
2584 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002585 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2586 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002587
2588 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2589 ScopedObjectAccess soa(env);
2590 ScopedCheck sc(kFlag_Default, function_name);
2591 JniValueType args[2] = {{.E = env}, {.L = obj}};
2592 if (sc.Check(soa, true, "EL", args)) {
2593 JniValueType result;
2594 switch (kind) {
2595 case kGlobal:
2596 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2597 break;
2598 case kLocal:
2599 result.L = baseEnv(env)->NewLocalRef(env, obj);
2600 break;
2601 case kWeakGlobal:
2602 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2603 break;
2604 default:
2605 LOG(FATAL) << "Unexpected reference kind: " << kind;
2606 }
2607 if (sc.Check(soa, false, "L", &result)) {
2608 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002609 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002610 return result.L;
2611 }
2612 }
2613 return nullptr;
2614 }
2615
2616 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2617 ScopedObjectAccess soa(env);
2618 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2619 JniValueType args[2] = {{.E = env}, {.L = obj}};
2620 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002621 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002622 JniValueType result;
2623 switch (kind) {
2624 case kGlobal:
2625 baseEnv(env)->DeleteGlobalRef(env, obj);
2626 break;
2627 case kLocal:
2628 baseEnv(env)->DeleteLocalRef(env, obj);
2629 break;
2630 case kWeakGlobal:
2631 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2632 break;
2633 default:
2634 LOG(FATAL) << "Unexpected reference kind: " << kind;
2635 }
2636 result.V = nullptr;
2637 sc.Check(soa, false, "V", &result);
2638 }
2639 }
2640
2641 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2642 const char* name, const char* sig, bool is_static) {
2643 ScopedObjectAccess soa(env);
2644 ScopedCheck sc(kFlag_Default, function_name);
2645 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2646 if (sc.Check(soa, true, "Ecuu", args)) {
2647 JniValueType result;
2648 if (is_static) {
2649 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2650 } else {
2651 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2652 }
2653 if (sc.Check(soa, false, "m", &result)) {
2654 return result.m;
2655 }
2656 }
2657 return nullptr;
2658 }
2659
2660 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2661 const char* name, const char* sig, bool is_static) {
2662 ScopedObjectAccess soa(env);
2663 ScopedCheck sc(kFlag_Default, function_name);
2664 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2665 if (sc.Check(soa, true, "Ecuu", args)) {
2666 JniValueType result;
2667 if (is_static) {
2668 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2669 } else {
2670 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2671 }
2672 if (sc.Check(soa, false, "f", &result)) {
2673 return result.f;
2674 }
2675 }
2676 return nullptr;
2677 }
2678
2679 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2680 bool is_static, Primitive::Type type) {
2681 ScopedObjectAccess soa(env);
2682 ScopedCheck sc(kFlag_Default, function_name);
2683 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2684 JniValueType result;
2685 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2686 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2687 const char* result_check = nullptr;
2688 switch (type) {
2689 case Primitive::kPrimNot:
2690 if (is_static) {
2691 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2692 } else {
2693 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2694 }
2695 result_check = "L";
2696 break;
2697 case Primitive::kPrimBoolean:
2698 if (is_static) {
2699 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2700 } else {
2701 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2702 }
2703 result_check = "Z";
2704 break;
2705 case Primitive::kPrimByte:
2706 if (is_static) {
2707 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2708 } else {
2709 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2710 }
2711 result_check = "B";
2712 break;
2713 case Primitive::kPrimChar:
2714 if (is_static) {
2715 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2716 } else {
2717 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2718 }
2719 result_check = "C";
2720 break;
2721 case Primitive::kPrimShort:
2722 if (is_static) {
2723 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2724 } else {
2725 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2726 }
2727 result_check = "S";
2728 break;
2729 case Primitive::kPrimInt:
2730 if (is_static) {
2731 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2732 } else {
2733 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2734 }
2735 result_check = "I";
2736 break;
2737 case Primitive::kPrimLong:
2738 if (is_static) {
2739 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2740 } else {
2741 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2742 }
2743 result_check = "J";
2744 break;
2745 case Primitive::kPrimFloat:
2746 if (is_static) {
2747 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2748 } else {
2749 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2750 }
2751 result_check = "F";
2752 break;
2753 case Primitive::kPrimDouble:
2754 if (is_static) {
2755 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2756 } else {
2757 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2758 }
2759 result_check = "D";
2760 break;
2761 case Primitive::kPrimVoid:
2762 LOG(FATAL) << "Unexpected type: " << type;
2763 break;
2764 }
2765 if (sc.Check(soa, false, result_check, &result)) {
2766 return result;
2767 }
2768 }
2769 result.J = 0;
2770 return result;
2771 }
2772
2773 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2774 bool is_static, Primitive::Type type, JniValueType value) {
2775 ScopedObjectAccess soa(env);
2776 ScopedCheck sc(kFlag_Default, function_name);
2777 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2778 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2779 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2780 if (sc.Check(soa, true, sig, args) &&
2781 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2782 switch (type) {
2783 case Primitive::kPrimNot:
2784 if (is_static) {
2785 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2786 } else {
2787 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2788 }
2789 break;
2790 case Primitive::kPrimBoolean:
2791 if (is_static) {
2792 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2793 } else {
2794 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2795 }
2796 break;
2797 case Primitive::kPrimByte:
2798 if (is_static) {
2799 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2800 } else {
2801 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2802 }
2803 break;
2804 case Primitive::kPrimChar:
2805 if (is_static) {
2806 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2807 } else {
2808 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2809 }
2810 break;
2811 case Primitive::kPrimShort:
2812 if (is_static) {
2813 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2814 } else {
2815 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2816 }
2817 break;
2818 case Primitive::kPrimInt:
2819 if (is_static) {
2820 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2821 } else {
2822 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2823 }
2824 break;
2825 case Primitive::kPrimLong:
2826 if (is_static) {
2827 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2828 } else {
2829 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2830 }
2831 break;
2832 case Primitive::kPrimFloat:
2833 if (is_static) {
2834 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2835 } else {
2836 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2837 }
2838 break;
2839 case Primitive::kPrimDouble:
2840 if (is_static) {
2841 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2842 } else {
2843 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2844 }
2845 break;
2846 case Primitive::kPrimVoid:
2847 LOG(FATAL) << "Unexpected type: " << type;
2848 break;
2849 }
2850 JniValueType result;
2851 result.V = nullptr;
2852 sc.Check(soa, false, "V", &result);
2853 }
2854 }
2855
2856 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002857 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002858 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002859 bool checked;
2860 switch (invoke) {
2861 case kVirtual: {
2862 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002863 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2864 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002865 break;
2866 }
2867 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002868 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2869 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002870 break;
2871 }
2872 case kStatic: {
2873 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002874 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2875 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002876 break;
2877 }
2878 default:
2879 LOG(FATAL) << "Unexpected invoke: " << invoke;
2880 checked = false;
2881 break;
2882 }
2883 return checked;
2884 }
2885
2886 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2887 jmethodID mid, jvalue* vargs, Primitive::Type type,
2888 InvokeType invoke) {
2889 ScopedObjectAccess soa(env);
2890 ScopedCheck sc(kFlag_Default, function_name);
2891 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002892 VarArgs rest(mid, vargs);
2893 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002894 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2895 const char* result_check;
2896 switch (type) {
2897 case Primitive::kPrimNot:
2898 result_check = "L";
2899 switch (invoke) {
2900 case kVirtual:
2901 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2902 break;
2903 case kDirect:
2904 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2905 break;
2906 case kStatic:
2907 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2908 break;
2909 default:
2910 break;
2911 }
2912 break;
2913 case Primitive::kPrimBoolean:
2914 result_check = "Z";
2915 switch (invoke) {
2916 case kVirtual:
2917 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2918 break;
2919 case kDirect:
2920 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2921 break;
2922 case kStatic:
2923 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2924 break;
2925 default:
2926 break;
2927 }
2928 break;
2929 case Primitive::kPrimByte:
2930 result_check = "B";
2931 switch (invoke) {
2932 case kVirtual:
2933 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2934 break;
2935 case kDirect:
2936 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2937 break;
2938 case kStatic:
2939 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2940 break;
2941 default:
2942 break;
2943 }
2944 break;
2945 case Primitive::kPrimChar:
2946 result_check = "C";
2947 switch (invoke) {
2948 case kVirtual:
2949 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2950 break;
2951 case kDirect:
2952 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2953 break;
2954 case kStatic:
2955 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2956 break;
2957 default:
2958 break;
2959 }
2960 break;
2961 case Primitive::kPrimShort:
2962 result_check = "S";
2963 switch (invoke) {
2964 case kVirtual:
2965 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2966 break;
2967 case kDirect:
2968 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2969 break;
2970 case kStatic:
2971 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2972 break;
2973 default:
2974 break;
2975 }
2976 break;
2977 case Primitive::kPrimInt:
2978 result_check = "I";
2979 switch (invoke) {
2980 case kVirtual:
2981 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2982 break;
2983 case kDirect:
2984 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2985 break;
2986 case kStatic:
2987 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
2988 break;
2989 default:
2990 break;
2991 }
2992 break;
2993 case Primitive::kPrimLong:
2994 result_check = "J";
2995 switch (invoke) {
2996 case kVirtual:
2997 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
2998 break;
2999 case kDirect:
3000 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3001 break;
3002 case kStatic:
3003 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3004 break;
3005 default:
3006 break;
3007 }
3008 break;
3009 case Primitive::kPrimFloat:
3010 result_check = "F";
3011 switch (invoke) {
3012 case kVirtual:
3013 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3014 break;
3015 case kDirect:
3016 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3017 break;
3018 case kStatic:
3019 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3020 break;
3021 default:
3022 break;
3023 }
3024 break;
3025 case Primitive::kPrimDouble:
3026 result_check = "D";
3027 switch (invoke) {
3028 case kVirtual:
3029 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3030 break;
3031 case kDirect:
3032 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3033 break;
3034 case kStatic:
3035 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3036 break;
3037 default:
3038 break;
3039 }
3040 break;
3041 case Primitive::kPrimVoid:
3042 result_check = "V";
3043 result.V = nullptr;
3044 switch (invoke) {
3045 case kVirtual:
3046 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3047 break;
3048 case kDirect:
3049 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3050 break;
3051 case kStatic:
3052 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3053 break;
3054 default:
3055 LOG(FATAL) << "Unexpected invoke: " << invoke;
3056 }
3057 break;
3058 default:
3059 LOG(FATAL) << "Unexpected return type: " << type;
3060 result_check = nullptr;
3061 }
3062 if (sc.Check(soa, false, result_check, &result)) {
3063 return result;
3064 }
3065 }
3066 result.J = 0;
3067 return result;
3068 }
3069
3070 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3071 jmethodID mid, va_list vargs, Primitive::Type type,
3072 InvokeType invoke) {
3073 ScopedObjectAccess soa(env);
3074 ScopedCheck sc(kFlag_Default, function_name);
3075 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003076 VarArgs rest(mid, vargs);
3077 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003078 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3079 const char* result_check;
3080 switch (type) {
3081 case Primitive::kPrimNot:
3082 result_check = "L";
3083 switch (invoke) {
3084 case kVirtual:
3085 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3086 break;
3087 case kDirect:
3088 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3089 break;
3090 case kStatic:
3091 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3092 break;
3093 default:
3094 LOG(FATAL) << "Unexpected invoke: " << invoke;
3095 }
3096 break;
3097 case Primitive::kPrimBoolean:
3098 result_check = "Z";
3099 switch (invoke) {
3100 case kVirtual:
3101 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3102 break;
3103 case kDirect:
3104 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3105 break;
3106 case kStatic:
3107 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3108 break;
3109 default:
3110 LOG(FATAL) << "Unexpected invoke: " << invoke;
3111 }
3112 break;
3113 case Primitive::kPrimByte:
3114 result_check = "B";
3115 switch (invoke) {
3116 case kVirtual:
3117 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3118 break;
3119 case kDirect:
3120 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3121 break;
3122 case kStatic:
3123 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3124 break;
3125 default:
3126 LOG(FATAL) << "Unexpected invoke: " << invoke;
3127 }
3128 break;
3129 case Primitive::kPrimChar:
3130 result_check = "C";
3131 switch (invoke) {
3132 case kVirtual:
3133 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3134 break;
3135 case kDirect:
3136 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3137 break;
3138 case kStatic:
3139 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3140 break;
3141 default:
3142 LOG(FATAL) << "Unexpected invoke: " << invoke;
3143 }
3144 break;
3145 case Primitive::kPrimShort:
3146 result_check = "S";
3147 switch (invoke) {
3148 case kVirtual:
3149 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3150 break;
3151 case kDirect:
3152 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3153 break;
3154 case kStatic:
3155 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3156 break;
3157 default:
3158 LOG(FATAL) << "Unexpected invoke: " << invoke;
3159 }
3160 break;
3161 case Primitive::kPrimInt:
3162 result_check = "I";
3163 switch (invoke) {
3164 case kVirtual:
3165 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3166 break;
3167 case kDirect:
3168 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3169 break;
3170 case kStatic:
3171 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3172 break;
3173 default:
3174 LOG(FATAL) << "Unexpected invoke: " << invoke;
3175 }
3176 break;
3177 case Primitive::kPrimLong:
3178 result_check = "J";
3179 switch (invoke) {
3180 case kVirtual:
3181 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3182 break;
3183 case kDirect:
3184 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3185 break;
3186 case kStatic:
3187 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3188 break;
3189 default:
3190 LOG(FATAL) << "Unexpected invoke: " << invoke;
3191 }
3192 break;
3193 case Primitive::kPrimFloat:
3194 result_check = "F";
3195 switch (invoke) {
3196 case kVirtual:
3197 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3198 break;
3199 case kDirect:
3200 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3201 break;
3202 case kStatic:
3203 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3204 break;
3205 default:
3206 LOG(FATAL) << "Unexpected invoke: " << invoke;
3207 }
3208 break;
3209 case Primitive::kPrimDouble:
3210 result_check = "D";
3211 switch (invoke) {
3212 case kVirtual:
3213 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3214 break;
3215 case kDirect:
3216 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3217 break;
3218 case kStatic:
3219 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3220 break;
3221 default:
3222 LOG(FATAL) << "Unexpected invoke: " << invoke;
3223 }
3224 break;
3225 case Primitive::kPrimVoid:
3226 result_check = "V";
3227 result.V = nullptr;
3228 switch (invoke) {
3229 case kVirtual:
3230 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3231 break;
3232 case kDirect:
3233 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3234 break;
3235 case kStatic:
3236 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3237 break;
3238 default:
3239 LOG(FATAL) << "Unexpected invoke: " << invoke;
3240 }
3241 break;
3242 default:
3243 LOG(FATAL) << "Unexpected return type: " << type;
3244 result_check = nullptr;
3245 }
3246 if (sc.Check(soa, false, result_check, &result)) {
3247 return result;
3248 }
3249 }
3250 result.J = 0;
3251 return result;
3252 }
3253
3254 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3255 jboolean* is_copy, bool utf, bool critical) {
3256 ScopedObjectAccess soa(env);
3257 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3258 ScopedCheck sc(flags, function_name);
3259 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3260 if (sc.Check(soa, true, "Esp", args)) {
3261 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003262 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003263 if (utf) {
3264 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003265 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3266 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003267 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003268 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3269 baseEnv(env)->GetStringChars(env, string, is_copy));
3270 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003271 }
3272 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003273 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003274 if (utf) {
3275 size_t length_in_bytes = strlen(result.u) + 1;
3276 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003277 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003278 } else {
3279 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3280 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003281 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003282 }
3283 if (is_copy != nullptr) {
3284 *is_copy = JNI_TRUE;
3285 }
3286 }
3287 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3288 return utf ? result.u : result.p;
3289 }
3290 }
3291 return nullptr;
3292 }
3293
3294 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3295 const void* chars, bool utf, bool critical) {
3296 ScopedObjectAccess soa(env);
3297 int flags = kFlag_ExcepOkay | kFlag_Release;
3298 if (critical) {
3299 flags |= kFlag_CritRelease;
3300 }
3301 ScopedCheck sc(flags, function_name);
3302 sc.CheckNonNull(chars);
3303 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3304 if (force_copy_ok && soa.ForceCopy()) {
3305 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3306 }
3307 if (force_copy_ok) {
3308 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3309 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3310 if (utf) {
3311 CHECK(!critical);
3312 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3313 } else {
3314 if (critical) {
3315 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3316 } else {
3317 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3318 }
3319 }
3320 JniValueType result;
3321 sc.Check(soa, false, "V", &result);
3322 }
3323 }
3324 }
3325
3326 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3327 Primitive::Type type) {
3328 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003329 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003330 JniValueType args[2] = {{.E = env}, {.z = length}};
3331 if (sc.Check(soa, true, "Ez", args)) {
3332 JniValueType result;
3333 switch (type) {
3334 case Primitive::kPrimBoolean:
3335 result.a = baseEnv(env)->NewBooleanArray(env, length);
3336 break;
3337 case Primitive::kPrimByte:
3338 result.a = baseEnv(env)->NewByteArray(env, length);
3339 break;
3340 case Primitive::kPrimChar:
3341 result.a = baseEnv(env)->NewCharArray(env, length);
3342 break;
3343 case Primitive::kPrimShort:
3344 result.a = baseEnv(env)->NewShortArray(env, length);
3345 break;
3346 case Primitive::kPrimInt:
3347 result.a = baseEnv(env)->NewIntArray(env, length);
3348 break;
3349 case Primitive::kPrimLong:
3350 result.a = baseEnv(env)->NewLongArray(env, length);
3351 break;
3352 case Primitive::kPrimFloat:
3353 result.a = baseEnv(env)->NewFloatArray(env, length);
3354 break;
3355 case Primitive::kPrimDouble:
3356 result.a = baseEnv(env)->NewDoubleArray(env, length);
3357 break;
3358 default:
3359 LOG(FATAL) << "Unexpected primitive type: " << type;
3360 }
3361 if (sc.Check(soa, false, "a", &result)) {
3362 return result.a;
3363 }
3364 }
3365 return nullptr;
3366 }
3367
3368 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3369 JNIEnv* env, jarray array, jboolean* is_copy) {
3370 ScopedObjectAccess soa(env);
3371 ScopedCheck sc(kFlag_Default, function_name);
3372 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3373 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3374 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003375 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003376 switch (type) {
3377 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003378 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3379 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003380 break;
3381 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003382 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003383 break;
3384 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003385 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003386 break;
3387 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003388 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003389 break;
3390 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003391 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003392 break;
3393 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003394 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003395 break;
3396 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003397 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003398 break;
3399 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003400 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003401 break;
3402 default:
3403 LOG(FATAL) << "Unexpected primitive type: " << type;
3404 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003405 if (ptr != nullptr && soa.ForceCopy()) {
3406 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003407 if (is_copy != nullptr) {
3408 *is_copy = JNI_TRUE;
3409 }
3410 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003411 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003412 if (sc.Check(soa, false, "p", &result)) {
3413 return const_cast<void*>(result.p);
3414 }
3415 }
3416 return nullptr;
3417 }
3418
3419 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3420 JNIEnv* env, jarray array, void* elems, jint mode) {
3421 ScopedObjectAccess soa(env);
3422 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3423 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3424 if (soa.ForceCopy()) {
3425 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3426 }
3427 if (!soa.ForceCopy() || elems != nullptr) {
3428 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3429 if (sc.Check(soa, true, "Eapr", args)) {
3430 switch (type) {
3431 case Primitive::kPrimBoolean:
3432 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3433 reinterpret_cast<jboolean*>(elems), mode);
3434 break;
3435 case Primitive::kPrimByte:
3436 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3437 reinterpret_cast<jbyte*>(elems), mode);
3438 break;
3439 case Primitive::kPrimChar:
3440 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3441 reinterpret_cast<jchar*>(elems), mode);
3442 break;
3443 case Primitive::kPrimShort:
3444 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3445 reinterpret_cast<jshort*>(elems), mode);
3446 break;
3447 case Primitive::kPrimInt:
3448 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3449 reinterpret_cast<jint*>(elems), mode);
3450 break;
3451 case Primitive::kPrimLong:
3452 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3453 reinterpret_cast<jlong*>(elems), mode);
3454 break;
3455 case Primitive::kPrimFloat:
3456 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3457 reinterpret_cast<jfloat*>(elems), mode);
3458 break;
3459 case Primitive::kPrimDouble:
3460 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3461 reinterpret_cast<jdouble*>(elems), mode);
3462 break;
3463 default:
3464 LOG(FATAL) << "Unexpected primitive type: " << type;
3465 }
3466 JniValueType result;
3467 result.V = nullptr;
3468 sc.Check(soa, false, "V", &result);
3469 }
3470 }
3471 }
3472 }
3473
3474 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3475 jarray array, jsize start, jsize len, void* buf) {
3476 ScopedObjectAccess soa(env);
3477 ScopedCheck sc(kFlag_Default, function_name);
3478 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3479 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3480 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3481 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3482 switch (type) {
3483 case Primitive::kPrimBoolean:
3484 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3485 reinterpret_cast<jboolean*>(buf));
3486 break;
3487 case Primitive::kPrimByte:
3488 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3489 reinterpret_cast<jbyte*>(buf));
3490 break;
3491 case Primitive::kPrimChar:
3492 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3493 reinterpret_cast<jchar*>(buf));
3494 break;
3495 case Primitive::kPrimShort:
3496 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3497 reinterpret_cast<jshort*>(buf));
3498 break;
3499 case Primitive::kPrimInt:
3500 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3501 reinterpret_cast<jint*>(buf));
3502 break;
3503 case Primitive::kPrimLong:
3504 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3505 reinterpret_cast<jlong*>(buf));
3506 break;
3507 case Primitive::kPrimFloat:
3508 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3509 reinterpret_cast<jfloat*>(buf));
3510 break;
3511 case Primitive::kPrimDouble:
3512 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3513 reinterpret_cast<jdouble*>(buf));
3514 break;
3515 default:
3516 LOG(FATAL) << "Unexpected primitive type: " << type;
3517 }
3518 JniValueType result;
3519 result.V = nullptr;
3520 sc.Check(soa, false, "V", &result);
3521 }
3522 }
3523
3524 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3525 jarray array, jsize start, jsize len, const void* buf) {
3526 ScopedObjectAccess soa(env);
3527 ScopedCheck sc(kFlag_Default, function_name);
3528 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3529 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3530 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3531 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3532 switch (type) {
3533 case Primitive::kPrimBoolean:
3534 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3535 reinterpret_cast<const jboolean*>(buf));
3536 break;
3537 case Primitive::kPrimByte:
3538 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3539 reinterpret_cast<const jbyte*>(buf));
3540 break;
3541 case Primitive::kPrimChar:
3542 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3543 reinterpret_cast<const jchar*>(buf));
3544 break;
3545 case Primitive::kPrimShort:
3546 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3547 reinterpret_cast<const jshort*>(buf));
3548 break;
3549 case Primitive::kPrimInt:
3550 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3551 reinterpret_cast<const jint*>(buf));
3552 break;
3553 case Primitive::kPrimLong:
3554 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3555 reinterpret_cast<const jlong*>(buf));
3556 break;
3557 case Primitive::kPrimFloat:
3558 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3559 reinterpret_cast<const jfloat*>(buf));
3560 break;
3561 case Primitive::kPrimDouble:
3562 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3563 reinterpret_cast<const jdouble*>(buf));
3564 break;
3565 default:
3566 LOG(FATAL) << "Unexpected primitive type: " << type;
3567 }
3568 JniValueType result;
3569 result.V = nullptr;
3570 sc.Check(soa, false, "V", &result);
3571 }
3572 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003573};
3574
3575const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003576 nullptr, // reserved0.
3577 nullptr, // reserved1.
3578 nullptr, // reserved2.
3579 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003580 CheckJNI::GetVersion,
3581 CheckJNI::DefineClass,
3582 CheckJNI::FindClass,
3583 CheckJNI::FromReflectedMethod,
3584 CheckJNI::FromReflectedField,
3585 CheckJNI::ToReflectedMethod,
3586 CheckJNI::GetSuperclass,
3587 CheckJNI::IsAssignableFrom,
3588 CheckJNI::ToReflectedField,
3589 CheckJNI::Throw,
3590 CheckJNI::ThrowNew,
3591 CheckJNI::ExceptionOccurred,
3592 CheckJNI::ExceptionDescribe,
3593 CheckJNI::ExceptionClear,
3594 CheckJNI::FatalError,
3595 CheckJNI::PushLocalFrame,
3596 CheckJNI::PopLocalFrame,
3597 CheckJNI::NewGlobalRef,
3598 CheckJNI::DeleteGlobalRef,
3599 CheckJNI::DeleteLocalRef,
3600 CheckJNI::IsSameObject,
3601 CheckJNI::NewLocalRef,
3602 CheckJNI::EnsureLocalCapacity,
3603 CheckJNI::AllocObject,
3604 CheckJNI::NewObject,
3605 CheckJNI::NewObjectV,
3606 CheckJNI::NewObjectA,
3607 CheckJNI::GetObjectClass,
3608 CheckJNI::IsInstanceOf,
3609 CheckJNI::GetMethodID,
3610 CheckJNI::CallObjectMethod,
3611 CheckJNI::CallObjectMethodV,
3612 CheckJNI::CallObjectMethodA,
3613 CheckJNI::CallBooleanMethod,
3614 CheckJNI::CallBooleanMethodV,
3615 CheckJNI::CallBooleanMethodA,
3616 CheckJNI::CallByteMethod,
3617 CheckJNI::CallByteMethodV,
3618 CheckJNI::CallByteMethodA,
3619 CheckJNI::CallCharMethod,
3620 CheckJNI::CallCharMethodV,
3621 CheckJNI::CallCharMethodA,
3622 CheckJNI::CallShortMethod,
3623 CheckJNI::CallShortMethodV,
3624 CheckJNI::CallShortMethodA,
3625 CheckJNI::CallIntMethod,
3626 CheckJNI::CallIntMethodV,
3627 CheckJNI::CallIntMethodA,
3628 CheckJNI::CallLongMethod,
3629 CheckJNI::CallLongMethodV,
3630 CheckJNI::CallLongMethodA,
3631 CheckJNI::CallFloatMethod,
3632 CheckJNI::CallFloatMethodV,
3633 CheckJNI::CallFloatMethodA,
3634 CheckJNI::CallDoubleMethod,
3635 CheckJNI::CallDoubleMethodV,
3636 CheckJNI::CallDoubleMethodA,
3637 CheckJNI::CallVoidMethod,
3638 CheckJNI::CallVoidMethodV,
3639 CheckJNI::CallVoidMethodA,
3640 CheckJNI::CallNonvirtualObjectMethod,
3641 CheckJNI::CallNonvirtualObjectMethodV,
3642 CheckJNI::CallNonvirtualObjectMethodA,
3643 CheckJNI::CallNonvirtualBooleanMethod,
3644 CheckJNI::CallNonvirtualBooleanMethodV,
3645 CheckJNI::CallNonvirtualBooleanMethodA,
3646 CheckJNI::CallNonvirtualByteMethod,
3647 CheckJNI::CallNonvirtualByteMethodV,
3648 CheckJNI::CallNonvirtualByteMethodA,
3649 CheckJNI::CallNonvirtualCharMethod,
3650 CheckJNI::CallNonvirtualCharMethodV,
3651 CheckJNI::CallNonvirtualCharMethodA,
3652 CheckJNI::CallNonvirtualShortMethod,
3653 CheckJNI::CallNonvirtualShortMethodV,
3654 CheckJNI::CallNonvirtualShortMethodA,
3655 CheckJNI::CallNonvirtualIntMethod,
3656 CheckJNI::CallNonvirtualIntMethodV,
3657 CheckJNI::CallNonvirtualIntMethodA,
3658 CheckJNI::CallNonvirtualLongMethod,
3659 CheckJNI::CallNonvirtualLongMethodV,
3660 CheckJNI::CallNonvirtualLongMethodA,
3661 CheckJNI::CallNonvirtualFloatMethod,
3662 CheckJNI::CallNonvirtualFloatMethodV,
3663 CheckJNI::CallNonvirtualFloatMethodA,
3664 CheckJNI::CallNonvirtualDoubleMethod,
3665 CheckJNI::CallNonvirtualDoubleMethodV,
3666 CheckJNI::CallNonvirtualDoubleMethodA,
3667 CheckJNI::CallNonvirtualVoidMethod,
3668 CheckJNI::CallNonvirtualVoidMethodV,
3669 CheckJNI::CallNonvirtualVoidMethodA,
3670 CheckJNI::GetFieldID,
3671 CheckJNI::GetObjectField,
3672 CheckJNI::GetBooleanField,
3673 CheckJNI::GetByteField,
3674 CheckJNI::GetCharField,
3675 CheckJNI::GetShortField,
3676 CheckJNI::GetIntField,
3677 CheckJNI::GetLongField,
3678 CheckJNI::GetFloatField,
3679 CheckJNI::GetDoubleField,
3680 CheckJNI::SetObjectField,
3681 CheckJNI::SetBooleanField,
3682 CheckJNI::SetByteField,
3683 CheckJNI::SetCharField,
3684 CheckJNI::SetShortField,
3685 CheckJNI::SetIntField,
3686 CheckJNI::SetLongField,
3687 CheckJNI::SetFloatField,
3688 CheckJNI::SetDoubleField,
3689 CheckJNI::GetStaticMethodID,
3690 CheckJNI::CallStaticObjectMethod,
3691 CheckJNI::CallStaticObjectMethodV,
3692 CheckJNI::CallStaticObjectMethodA,
3693 CheckJNI::CallStaticBooleanMethod,
3694 CheckJNI::CallStaticBooleanMethodV,
3695 CheckJNI::CallStaticBooleanMethodA,
3696 CheckJNI::CallStaticByteMethod,
3697 CheckJNI::CallStaticByteMethodV,
3698 CheckJNI::CallStaticByteMethodA,
3699 CheckJNI::CallStaticCharMethod,
3700 CheckJNI::CallStaticCharMethodV,
3701 CheckJNI::CallStaticCharMethodA,
3702 CheckJNI::CallStaticShortMethod,
3703 CheckJNI::CallStaticShortMethodV,
3704 CheckJNI::CallStaticShortMethodA,
3705 CheckJNI::CallStaticIntMethod,
3706 CheckJNI::CallStaticIntMethodV,
3707 CheckJNI::CallStaticIntMethodA,
3708 CheckJNI::CallStaticLongMethod,
3709 CheckJNI::CallStaticLongMethodV,
3710 CheckJNI::CallStaticLongMethodA,
3711 CheckJNI::CallStaticFloatMethod,
3712 CheckJNI::CallStaticFloatMethodV,
3713 CheckJNI::CallStaticFloatMethodA,
3714 CheckJNI::CallStaticDoubleMethod,
3715 CheckJNI::CallStaticDoubleMethodV,
3716 CheckJNI::CallStaticDoubleMethodA,
3717 CheckJNI::CallStaticVoidMethod,
3718 CheckJNI::CallStaticVoidMethodV,
3719 CheckJNI::CallStaticVoidMethodA,
3720 CheckJNI::GetStaticFieldID,
3721 CheckJNI::GetStaticObjectField,
3722 CheckJNI::GetStaticBooleanField,
3723 CheckJNI::GetStaticByteField,
3724 CheckJNI::GetStaticCharField,
3725 CheckJNI::GetStaticShortField,
3726 CheckJNI::GetStaticIntField,
3727 CheckJNI::GetStaticLongField,
3728 CheckJNI::GetStaticFloatField,
3729 CheckJNI::GetStaticDoubleField,
3730 CheckJNI::SetStaticObjectField,
3731 CheckJNI::SetStaticBooleanField,
3732 CheckJNI::SetStaticByteField,
3733 CheckJNI::SetStaticCharField,
3734 CheckJNI::SetStaticShortField,
3735 CheckJNI::SetStaticIntField,
3736 CheckJNI::SetStaticLongField,
3737 CheckJNI::SetStaticFloatField,
3738 CheckJNI::SetStaticDoubleField,
3739 CheckJNI::NewString,
3740 CheckJNI::GetStringLength,
3741 CheckJNI::GetStringChars,
3742 CheckJNI::ReleaseStringChars,
3743 CheckJNI::NewStringUTF,
3744 CheckJNI::GetStringUTFLength,
3745 CheckJNI::GetStringUTFChars,
3746 CheckJNI::ReleaseStringUTFChars,
3747 CheckJNI::GetArrayLength,
3748 CheckJNI::NewObjectArray,
3749 CheckJNI::GetObjectArrayElement,
3750 CheckJNI::SetObjectArrayElement,
3751 CheckJNI::NewBooleanArray,
3752 CheckJNI::NewByteArray,
3753 CheckJNI::NewCharArray,
3754 CheckJNI::NewShortArray,
3755 CheckJNI::NewIntArray,
3756 CheckJNI::NewLongArray,
3757 CheckJNI::NewFloatArray,
3758 CheckJNI::NewDoubleArray,
3759 CheckJNI::GetBooleanArrayElements,
3760 CheckJNI::GetByteArrayElements,
3761 CheckJNI::GetCharArrayElements,
3762 CheckJNI::GetShortArrayElements,
3763 CheckJNI::GetIntArrayElements,
3764 CheckJNI::GetLongArrayElements,
3765 CheckJNI::GetFloatArrayElements,
3766 CheckJNI::GetDoubleArrayElements,
3767 CheckJNI::ReleaseBooleanArrayElements,
3768 CheckJNI::ReleaseByteArrayElements,
3769 CheckJNI::ReleaseCharArrayElements,
3770 CheckJNI::ReleaseShortArrayElements,
3771 CheckJNI::ReleaseIntArrayElements,
3772 CheckJNI::ReleaseLongArrayElements,
3773 CheckJNI::ReleaseFloatArrayElements,
3774 CheckJNI::ReleaseDoubleArrayElements,
3775 CheckJNI::GetBooleanArrayRegion,
3776 CheckJNI::GetByteArrayRegion,
3777 CheckJNI::GetCharArrayRegion,
3778 CheckJNI::GetShortArrayRegion,
3779 CheckJNI::GetIntArrayRegion,
3780 CheckJNI::GetLongArrayRegion,
3781 CheckJNI::GetFloatArrayRegion,
3782 CheckJNI::GetDoubleArrayRegion,
3783 CheckJNI::SetBooleanArrayRegion,
3784 CheckJNI::SetByteArrayRegion,
3785 CheckJNI::SetCharArrayRegion,
3786 CheckJNI::SetShortArrayRegion,
3787 CheckJNI::SetIntArrayRegion,
3788 CheckJNI::SetLongArrayRegion,
3789 CheckJNI::SetFloatArrayRegion,
3790 CheckJNI::SetDoubleArrayRegion,
3791 CheckJNI::RegisterNatives,
3792 CheckJNI::UnregisterNatives,
3793 CheckJNI::MonitorEnter,
3794 CheckJNI::MonitorExit,
3795 CheckJNI::GetJavaVM,
3796 CheckJNI::GetStringRegion,
3797 CheckJNI::GetStringUTFRegion,
3798 CheckJNI::GetPrimitiveArrayCritical,
3799 CheckJNI::ReleasePrimitiveArrayCritical,
3800 CheckJNI::GetStringCritical,
3801 CheckJNI::ReleaseStringCritical,
3802 CheckJNI::NewWeakGlobalRef,
3803 CheckJNI::DeleteWeakGlobalRef,
3804 CheckJNI::ExceptionCheck,
3805 CheckJNI::NewDirectByteBuffer,
3806 CheckJNI::GetDirectBufferAddress,
3807 CheckJNI::GetDirectBufferCapacity,
3808 CheckJNI::GetObjectRefType,
3809};
3810
3811const JNINativeInterface* GetCheckJniNativeInterface() {
3812 return &gCheckNativeInterface;
3813}
3814
3815class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003816 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003817 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003818 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3819 JniValueType args[1] = {{.v = vm}};
3820 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3821 JniValueType result;
3822 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003823 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3824 // which will delete the JavaVMExt.
3825 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003826 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003827 }
3828
3829 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003830 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3831 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3832 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3833 JniValueType result;
3834 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3835 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3836 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003837 }
3838
3839 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003840 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3841 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3842 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3843 JniValueType result;
3844 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3845 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3846 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003847 }
3848
3849 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003850 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3851 JniValueType args[1] = {{.v = vm}};
3852 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3853 JniValueType result;
3854 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3855 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3856 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003857 }
3858
Ian Rogers68d8b422014-07-17 11:09:10 -07003859 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3860 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3861 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3862 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3863 JniValueType result;
3864 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3865 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3866 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003867 }
3868
3869 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003870 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3871 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003872 }
3873};
3874
3875const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003876 nullptr, // reserved0
3877 nullptr, // reserved1
3878 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003879 CheckJII::DestroyJavaVM,
3880 CheckJII::AttachCurrentThread,
3881 CheckJII::DetachCurrentThread,
3882 CheckJII::GetEnv,
3883 CheckJII::AttachCurrentThreadAsDaemon
3884};
3885
3886const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3887 return &gCheckInvokeInterface;
3888}
3889
3890} // namespace art