blob: 0b9bf225d4c6fed8abcec34f7f6bdfe448afca37 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
19#include <sys/mman.h>
20#include <zlib.h>
21
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070022#include <iomanip>
23
Andreas Gampe57943812017-12-06 21:39:13 -080024#include <android-base/logging.h>
25#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080026
Mathieu Chartierc7853442015-03-27 14:35:38 -070027#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070028#include "art_method-inl.h"
Andreas Gampe57943812017-12-06 21:39:13 -080029#include "base/macros.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070030#include "base/to_str.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031#include "class_linker-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070032#include "class_linker.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070033#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070034#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070035#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080036#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080037#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080038#include "mirror/object-inl.h"
39#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070040#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080041#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070042#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070043#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070044#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070045#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070046
47namespace art {
48
Andreas Gampe46ee31b2016-12-14 10:11:49 -080049using android::base::StringAppendF;
50using android::base::StringPrintf;
51
Elliott Hughesa2501992011-08-26 19:39:54 -070052/*
53 * ===========================================================================
54 * JNI function helpers
55 * ===========================================================================
56 */
57
Elliott Hughes3f6635a2012-06-19 13:37:49 -070058// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070059#define kFlag_Default 0x0000
60
Elliott Hughes3f6635a2012-06-19 13:37:49 -070061#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
62#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
63#define kFlag_CritGet 0x0002 // This is a critical "get".
64#define kFlag_CritRelease 0x0003 // This is a critical "release".
65#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070066
Elliott Hughes3f6635a2012-06-19 13:37:49 -070067#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
68#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070069
Elliott Hughes3f6635a2012-06-19 13:37:49 -070070#define kFlag_Release 0x0010 // Are we in a non-critical release function?
71#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070072
Elliott Hughes3f6635a2012-06-19 13:37:49 -070073#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070074
Elliott Hughes485cac42011-12-09 17:49:35 -080075#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 -070076
77class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070078/*
79 * Java primitive types:
80 * B - jbyte
81 * C - jchar
82 * D - jdouble
83 * F - jfloat
84 * I - jint
85 * J - jlong
86 * S - jshort
87 * Z - jboolean (shown as true and false)
88 * V - void
89 *
90 * Java reference types:
91 * L - jobject
92 * a - jarray
93 * c - jclass
94 * s - jstring
95 * t - jthrowable
96 *
97 * JNI types:
98 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
99 * f - jfieldID
100 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
101 * m - jmethodID
102 * p - void*
103 * r - jint (for release mode arguments)
104 * u - const char* (Modified UTF-8)
105 * z - jsize (for lengths; use i if negative values are okay)
106 * v - JavaVM*
107 * w - jobjectRefType
108 * E - JNIEnv*
109 * . - no argument; just print "..." (used for varargs JNI calls)
110 *
111 */
112union JniValueType {
113 jarray a;
114 jboolean b;
115 jclass c;
116 jfieldID f;
117 jint i;
118 jmethodID m;
119 const void* p; // Pointer.
120 jint r; // Release mode.
121 jstring s;
122 jthrowable t;
123 const char* u; // Modified UTF-8.
124 JavaVM* v;
125 jobjectRefType w;
126 jsize z;
127 jbyte B;
128 jchar C;
129 jdouble D;
130 JNIEnv* E;
131 jfloat F;
132 jint I;
133 jlong J;
134 jobject L;
135 jshort S;
136 const void* V; // void
137 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700138 const VarArgs* va;
139};
140
141/*
142 * A structure containing all the information needed to validate varargs arguments.
143 *
144 * Note that actually getting the arguments from this structure mutates it so should only be done on
145 * owned copies.
146 */
147class VarArgs {
148 public:
149 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
150 va_copy(vargs_, var);
151 }
152
153 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
154
155 ~VarArgs() {
156 if (type_ == kTypeVaList) {
157 va_end(vargs_);
158 }
159 }
160
161 VarArgs(VarArgs&& other) {
162 m_ = other.m_;
163 cnt_ = other.cnt_;
164 type_ = other.type_;
165 if (other.type_ == kTypeVaList) {
166 va_copy(vargs_, other.vargs_);
167 } else {
168 ptr_ = other.ptr_;
169 }
170 }
171
172 // This method is const because we need to ensure that one only uses the GetValue method on an
173 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
174 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
175 // we want to use one we need to Clone() it.
176 VarArgs Clone() const {
177 if (type_ == kTypeVaList) {
178 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
179 // messed up if the source argument is not the exact type 'va_list'.
180 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
181 } else {
182 return VarArgs(m_, cnt_, ptr_);
183 }
184 }
185
186 jmethodID GetMethodID() const {
187 return m_;
188 }
189
190 JniValueType GetValue(char fmt) {
191 JniValueType o;
192 if (type_ == kTypeVaList) {
193 switch (fmt) {
194 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
195 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
196 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
197 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
198 case 'I': o.I = va_arg(vargs_, jint); break;
199 case 'J': o.J = va_arg(vargs_, jlong); break;
200 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
201 case 'D': o.D = va_arg(vargs_, jdouble); break;
202 case 'L': o.L = va_arg(vargs_, jobject); break;
203 default:
204 LOG(FATAL) << "Illegal type format char " << fmt;
205 UNREACHABLE();
206 }
207 } else {
208 CHECK(type_ == kTypePtr);
209 jvalue v = ptr_[cnt_];
210 cnt_++;
211 switch (fmt) {
212 case 'Z': o.Z = v.z; break;
213 case 'B': o.B = v.b; break;
214 case 'C': o.C = v.c; break;
215 case 'S': o.S = v.s; break;
216 case 'I': o.I = v.i; break;
217 case 'J': o.J = v.j; break;
218 case 'F': o.F = v.f; break;
219 case 'D': o.D = v.d; break;
220 case 'L': o.L = v.l; break;
221 default:
222 LOG(FATAL) << "Illegal type format char " << fmt;
223 UNREACHABLE();
224 }
225 }
226 return o;
227 }
228
229 private:
230 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
231 va_copy(vargs_, var);
232 }
233
234 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
235
236 enum VarArgsType {
237 kTypeVaList,
238 kTypePtr,
239 };
240
241 jmethodID m_;
242 VarArgsType type_;
243 uint32_t cnt_;
244 union {
245 va_list vargs_;
246 const jvalue* ptr_;
247 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700248};
249
Elliott Hughesa2501992011-08-26 19:39:54 -0700250class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800251 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100252 ScopedCheck(int flags, const char* functionName, bool has_method = true)
Ian Rogers68d8b422014-07-17 11:09:10 -0700253 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700254 }
255
Ian Rogers68d8b422014-07-17 11:09:10 -0700256 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700257
Elliott Hughes81ff3182012-03-23 20:35:56 -0700258 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
259 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
260 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
261 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700262 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700263 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700264 AbortF("illegal class name '%s'\n"
265 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
266 class_name);
267 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700268 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700269 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700270 }
271
272 /*
273 * Verify that this instance field ID is valid for this object.
274 *
275 * Assumes "jobj" has already been validated.
276 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700277 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700278 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700279 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700280 if (o == nullptr) {
281 AbortF("field operation on NULL object: %p", java_object);
282 return false;
283 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700284 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700285 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700286 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700287 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700288 java_object);
289 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700290 }
291
Andreas Gampe08883de2016-11-08 13:20:52 -0800292 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800293 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700294 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700295 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800296 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700297 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700298 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700299 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700300 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700301 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700302 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700303 }
304
305 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700306 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700307 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700308 bool CheckNonNull(const void* ptr) {
309 if (UNLIKELY(ptr == nullptr)) {
310 AbortF("non-nullable argument was NULL");
311 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700312 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700313 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700314 }
315
316 /*
317 * Verify that the method's return type matches the type of call.
318 * 'expectedType' will be "L" for all objects, including arrays.
319 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700320 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
321 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700322 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800323 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800324 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700325 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700326 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700327 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700328 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700329 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700330 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700331 bool is_static = (invoke == kStatic);
332 if (is_static != m->IsStatic()) {
333 if (is_static) {
334 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700335 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700336 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700337 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700338 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700339 }
340 return false;
341 }
342 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700343 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700344 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700345 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700346 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700347 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700348 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700349 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700350 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700351 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700352 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700353 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700354 return false;
355 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700356 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
357 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700358 return false;
359 }
360 }
361 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700362 }
363
364 /*
365 * Verify that this static field ID is valid for this class.
366 *
367 * Assumes "java_class" has already been validated.
368 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700369 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700370 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700371 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800372 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800373 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700374 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700375 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700376 if (c != f->GetDeclaringClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700377 AbortF("static jfieldID %p not valid for class %s", fid,
378 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700379 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700381 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700382 }
383
384 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700385 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700386 *
387 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700388 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700389 * allow bad code in the system though.
390 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700391 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700392 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700393 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700394 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800395 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800396 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700397 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700398 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700399 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700400 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700401 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
402 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700403 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700404 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700405 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700406 }
407
408 /*
409 * Verify that "mid" is appropriate for "jobj".
410 *
411 * Make sure the object is an instance of the method's declaring class.
412 * (Note the mid might point to a declaration in an interface; this
413 * will be handled automatically by the instanceof check.)
414 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700415 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700416 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800417 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800418 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700419 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700420 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700421 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700422 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700423 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700424 return false;
425 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700426 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
427 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700428 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700429 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700430 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700431 }
432
433 /**
434 * The format string is a sequence of the following characters,
435 * and must be followed by arguments of the corresponding types
436 * in the same order.
437 *
438 * Java primitive types:
439 * B - jbyte
440 * C - jchar
441 * D - jdouble
442 * F - jfloat
443 * I - jint
444 * J - jlong
445 * S - jshort
446 * Z - jboolean (shown as true and false)
447 * V - void
448 *
449 * Java reference types:
450 * L - jobject
451 * a - jarray
452 * c - jclass
453 * s - jstring
454 *
455 * JNI types:
456 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
457 * f - jfieldID
458 * m - jmethodID
459 * p - void*
460 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700461 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700462 * z - jsize (for lengths; use i if negative values are okay)
463 * v - JavaVM*
464 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700465 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700466 *
467 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
468 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700469 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700470 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700471 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700472 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700473 // We need to guard some of the invocation interface's calls: a bad caller might
474 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700475 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800476 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
477 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700478 }
479 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700480
Ian Rogersef7d42f2014-01-06 12:55:46 -0800481 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700482 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700483 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700484 for (size_t i = 0; fmt[i] != '\0'; ++i) {
485 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
486 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700487 StringAppendF(&msg, ", ");
488 }
489 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700490
Elliott Hughes485cac42011-12-09 17:49:35 -0800491 if ((flags_ & kFlag_ForceTrace) != 0) {
492 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
493 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700494 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700495 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700496 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
497 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700498 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700499 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
500 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700501 }
502 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700503 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700504 }
505 }
506
507 // We always do the thorough checks on entry, and never on exit...
508 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700509 for (size_t i = 0; fmt[i] != '\0'; ++i) {
510 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
511 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700512 }
513 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700514 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700515 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700516 }
517
Ian Rogers68d8b422014-07-17 11:09:10 -0700518 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
519 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800520 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700521 // We need to guard some of the invocation interface's calls: a bad caller might
522 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
523 Thread* self = Thread::Current();
524 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
525 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700526 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700527 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
528 }
529 }
530 if (should_trace) {
531 std::string msg;
532 for (size_t i = 0; fmt[i] != '\0'; ++i) {
533 TraceNonHeapValue(fmt[i], args[i], &msg);
534 if (fmt[i + 1] != '\0') {
535 StringAppendF(&msg, ", ");
536 }
537 }
538
539 if ((flags_ & kFlag_ForceTrace) != 0) {
540 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
541 } else if (entry) {
542 if (has_method_) {
543 Thread* self = Thread::Current();
544 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700545 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700546 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700547 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
548 indent_ = methodName.size() + 1;
549 } else {
550 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
551 indent_ = 0;
552 }
553 } else {
554 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
555 }
556 }
557
558 // We always do the thorough checks on entry, and never on exit...
559 if (entry) {
560 for (size_t i = 0; fmt[i] != '\0'; ++i) {
561 if (!CheckNonHeapValue(fmt[i], args[i])) {
562 return false;
563 }
564 }
565 }
566 return true;
567 }
568
569 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700570 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700571 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700572 if (method == nullptr) {
573 AbortF("expected non-null method");
574 return false;
575 }
576 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700577 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
578 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700579 AbortF("expected java.lang.reflect.Method or "
580 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700581 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700582 return false;
583 }
584 return true;
585 }
586
Andreas Gampe13b27842016-11-07 16:48:23 -0800587 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
588 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700589 if (method == nullptr) {
590 AbortF("expected non-null constructor");
591 return false;
592 }
593 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700594 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700595 return false;
596 }
597 return true;
598 }
599
600 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700601 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700602 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700603 if (field == nullptr) {
604 AbortF("expected non-null java.lang.reflect.Field");
605 return false;
606 }
607 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700608 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700609 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700610 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700611 return false;
612 }
613 return true;
614 }
615
616 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700617 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700618 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700619 if (!obj->GetClass()->IsThrowableClass()) {
620 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700621 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700622 return false;
623 }
624 return true;
625 }
626
627 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700628 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700629 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700630 if (!c->IsThrowableClass()) {
631 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700632 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700633 return false;
634 }
635 return true;
636 }
637
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700638 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700639 IndirectRefKind found_kind;
640 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700641 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700642 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
643 found_kind = kLocal;
644 }
645 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700646 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700647 }
648 if (obj != nullptr && found_kind != expected_kind) {
649 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700650 GetIndirectRefKindString(expected_kind),
651 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700652 obj);
653 return false;
654 }
655 return true;
656 }
657
658 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700659 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700660 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700661 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700662 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700663 return false;
664 }
665 return true;
666 }
667
668 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700669 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700670 if (!CheckArray(soa, array)) {
671 return false;
672 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700673 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700674 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
675 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700676 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700677 return false;
678 }
679 return true;
680 }
681
682 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
683 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700684 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700685 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
686 return false;
687 }
688 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
689 return false;
690 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800691 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700692 DCHECK(field != nullptr); // Already checked by Check.
693 if (is_static != field->IsStatic()) {
694 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700695 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700696 return false;
697 }
698 if (type != field->GetTypeAsPrimitiveType()) {
699 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700700 field->PrettyField().c_str(),
701 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700702 PrettyDescriptor(type).c_str(), fid);
703 return false;
704 }
705 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700706 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700707 if (o == nullptr || !o->IsClass()) {
708 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700709 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700710 return false;
711 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700712 ObjPtr<mirror::Class> c = o->AsClass();
713 if (c != field->GetDeclaringClass()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700714 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700715 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700716 return false;
717 }
718 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700719 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700720 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
721 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700722 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700723 return false;
724 }
725 }
726 return true;
727 }
728
729 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800730 enum InstanceKind {
731 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700732 kDirectByteBuffer,
733 kObject,
734 kString,
735 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800736 };
737
738 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700739 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800740 * an instance of expectedClass.
741 *
742 * Because we're looking at an object on the GC heap, we have to switch
743 * to "running" mode before doing the checks.
744 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700745 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700746 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800747 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800748 switch (kind) {
749 case kClass:
750 what = "jclass";
751 break;
752 case kDirectByteBuffer:
753 what = "direct ByteBuffer";
754 break;
755 case kObject:
756 what = "jobject";
757 break;
758 case kString:
759 what = "jstring";
760 break;
761 case kThrowable:
762 what = "jthrowable";
763 break;
764 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700765 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800766 }
767
Ian Rogersef7d42f2014-01-06 12:55:46 -0800768 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700769 if (null_ok) {
770 return true;
771 } else {
772 AbortF("%s received NULL %s", function_name_, what);
773 return false;
774 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800775 }
776
Mathieu Chartier0795f232016-09-27 18:43:30 -0700777 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700778 if (obj == nullptr) {
779 // Either java_object is invalid or is a cleared weak.
780 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
781 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700782 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700783 okay = false;
784 } else {
785 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700786 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700787 }
788 if (!okay) {
789 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700790 what,
791 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
792 java_object,
793 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700794 return false;
795 }
796 }
797
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700798 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700799 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700800 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700801 what,
802 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
803 java_object,
804 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800805 return false;
806 }
807
808 bool okay = true;
809 switch (kind) {
810 case kClass:
811 okay = obj->IsClass();
812 break;
813 case kDirectByteBuffer:
814 UNIMPLEMENTED(FATAL);
815 break;
816 case kString:
817 okay = obj->GetClass()->IsStringClass();
818 break;
819 case kThrowable:
820 okay = obj->GetClass()->IsThrowableClass();
821 break;
822 case kObject:
823 break;
824 }
825 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700826 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800827 return false;
828 }
829
830 return true;
831 }
832
Ian Rogers68d8b422014-07-17 11:09:10 -0700833 /*
834 * Verify that the "mode" argument passed to a primitive array Release
835 * function is one of the valid values.
836 */
837 bool CheckReleaseMode(jint mode) {
838 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
839 AbortF("unknown value for release mode: %d", mode);
840 return false;
841 }
842 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700843 }
844
Ian Rogers68d8b422014-07-17 11:09:10 -0700845 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700846 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700847 switch (fmt) {
848 case 'a': // jarray
849 return CheckArray(soa, arg.a);
850 case 'c': // jclass
851 return CheckInstance(soa, kClass, arg.c, false);
852 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800853 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700854 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800855 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700856 case 'r': // release int
857 return CheckReleaseMode(arg.r);
858 case 's': // jstring
859 return CheckInstance(soa, kString, arg.s, false);
860 case 't': // jthrowable
861 return CheckInstance(soa, kThrowable, arg.t, false);
862 case 'E': // JNIEnv*
863 return CheckThread(arg.E);
864 case 'L': // jobject
865 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700866 case '.': // A VarArgs list
867 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700868 default:
869 return CheckNonHeapValue(fmt, arg);
870 }
871 }
872
Alex Light48ffe062015-08-19 15:23:23 -0700873 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700874 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700875 CHECK(args_p != nullptr);
876 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800877 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700878 if (m == nullptr) {
879 return false;
880 }
881 uint32_t len = 0;
882 const char* shorty = m->GetShorty(&len);
883 // Skip the return type
884 CHECK_GE(len, 1u);
885 len--;
886 shorty++;
887 for (uint32_t i = 0; i < len; i++) {
888 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
889 return false;
890 }
891 }
892 return true;
893 }
894
Ian Rogers68d8b422014-07-17 11:09:10 -0700895 bool CheckNonHeapValue(char fmt, JniValueType arg) {
896 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700897 case 'p': // TODO: pointer - null or readable?
898 case 'v': // JavaVM*
899 case 'B': // jbyte
900 case 'C': // jchar
901 case 'D': // jdouble
902 case 'F': // jfloat
903 case 'I': // jint
904 case 'J': // jlong
905 case 'S': // jshort
906 break; // Ignored.
907 case 'b': // jboolean, why two? Fall-through.
908 case 'Z':
909 return CheckBoolean(arg.Z);
910 case 'u': // utf8
911 if ((flags_ & kFlag_Release) != 0) {
912 return CheckNonNull(arg.u);
913 } else {
914 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
915 return CheckUtfString(arg.u, nullable);
916 }
917 case 'w': // jobjectRefType
918 switch (arg.w) {
919 case JNIInvalidRefType:
920 case JNILocalRefType:
921 case JNIGlobalRefType:
922 case JNIWeakGlobalRefType:
923 break;
924 default:
925 AbortF("Unknown reference type");
926 return false;
927 }
928 break;
929 case 'z': // jsize
930 return CheckLengthPositive(arg.z);
931 default:
932 AbortF("unknown format specifier: '%c'", fmt);
933 return false;
934 }
935 return true;
936 }
937
938 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
939 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700940 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700941 switch (fmt) {
942 case 'L': // jobject fall-through.
943 case 'a': // jarray fall-through.
944 case 's': // jstring fall-through.
945 case 't': // jthrowable fall-through.
946 if (arg.L == nullptr) {
947 *msg += "NULL";
948 } else {
949 StringAppendF(msg, "%p", arg.L);
950 }
951 break;
952 case 'c': { // jclass
953 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700954 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700955 if (c == nullptr) {
956 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700957 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700958 StringAppendF(msg, "INVALID POINTER:%p", jc);
959 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700960 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700961 } else {
David Sehr709b0702016-10-13 09:12:37 -0700962 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700963 if (!entry) {
964 StringAppendF(msg, " (%p)", jc);
965 }
966 }
967 break;
968 }
969 case 'f': { // jfieldID
970 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800971 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700972 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700973 if (!entry) {
974 StringAppendF(msg, " (%p)", fid);
975 }
976 break;
977 }
978 case 'm': { // jmethodID
979 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800980 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700981 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700982 if (!entry) {
983 StringAppendF(msg, " (%p)", mid);
984 }
985 break;
986 }
Alex Light48ffe062015-08-19 15:23:23 -0700987 case '.': {
988 const VarArgs* va = arg.va;
989 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800990 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700991 uint32_t len;
992 const char* shorty = m->GetShorty(&len);
993 CHECK_GE(len, 1u);
994 // Skip past return value.
995 len--;
996 shorty++;
997 // Remove the previous ', ' from the message.
998 msg->erase(msg->length() - 2);
999 for (uint32_t i = 0; i < len; i++) {
1000 *msg += ", ";
1001 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1002 }
1003 break;
1004 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001005 default:
1006 TraceNonHeapValue(fmt, arg, msg);
1007 break;
1008 }
1009 }
1010
1011 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1012 switch (fmt) {
1013 case 'B': // jbyte
1014 if (arg.B >= 0 && arg.B < 10) {
1015 StringAppendF(msg, "%d", arg.B);
1016 } else {
1017 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1018 }
1019 break;
1020 case 'C': // jchar
1021 if (arg.C < 0x7f && arg.C >= ' ') {
1022 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1023 } else {
1024 StringAppendF(msg, "U+%x", arg.C);
1025 }
1026 break;
1027 case 'F': // jfloat
1028 StringAppendF(msg, "%g", arg.F);
1029 break;
1030 case 'D': // jdouble
1031 StringAppendF(msg, "%g", arg.D);
1032 break;
1033 case 'S': // jshort
1034 StringAppendF(msg, "%d", arg.S);
1035 break;
1036 case 'i': // jint - fall-through.
1037 case 'I': // jint
1038 StringAppendF(msg, "%d", arg.I);
1039 break;
1040 case 'J': // jlong
1041 StringAppendF(msg, "%" PRId64, arg.J);
1042 break;
1043 case 'Z': // jboolean
1044 case 'b': // jboolean (JNI-style)
1045 *msg += arg.b == JNI_TRUE ? "true" : "false";
1046 break;
1047 case 'V': // void
1048 DCHECK(arg.V == nullptr);
1049 *msg += "void";
1050 break;
1051 case 'v': // JavaVM*
1052 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1053 break;
1054 case 'E':
1055 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1056 break;
1057 case 'z': // non-negative jsize
1058 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1059 // We only treat this specially so we can do the non-negative check.
1060 // TODO: maybe this wasn't worth it?
1061 StringAppendF(msg, "%d", arg.z);
1062 break;
1063 case 'p': // void* ("pointer")
1064 if (arg.p == nullptr) {
1065 *msg += "NULL";
1066 } else {
1067 StringAppendF(msg, "(void*) %p", arg.p);
1068 }
1069 break;
1070 case 'r': { // jint (release mode)
1071 jint releaseMode = arg.r;
1072 if (releaseMode == 0) {
1073 *msg += "0";
1074 } else if (releaseMode == JNI_ABORT) {
1075 *msg += "JNI_ABORT";
1076 } else if (releaseMode == JNI_COMMIT) {
1077 *msg += "JNI_COMMIT";
1078 } else {
1079 StringAppendF(msg, "invalid release mode %d", releaseMode);
1080 }
1081 break;
1082 }
1083 case 'u': // const char* (Modified UTF-8)
1084 if (arg.u == nullptr) {
1085 *msg += "NULL";
1086 } else {
1087 StringAppendF(msg, "\"%s\"", arg.u);
1088 }
1089 break;
1090 case 'w': // jobjectRefType
1091 switch (arg.w) {
1092 case JNIInvalidRefType:
1093 *msg += "invalid reference type";
1094 break;
1095 case JNILocalRefType:
1096 *msg += "local ref type";
1097 break;
1098 case JNIGlobalRefType:
1099 *msg += "global ref type";
1100 break;
1101 case JNIWeakGlobalRefType:
1102 *msg += "weak global ref type";
1103 break;
1104 default:
1105 *msg += "unknown ref type";
1106 break;
1107 }
1108 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001109 default:
1110 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1111 }
1112 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001113 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001114 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001115 *
1116 * Since we're dealing with objects, switch to "running" mode.
1117 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001118 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001119 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001120 if (UNLIKELY(java_array == nullptr)) {
1121 AbortF("jarray was NULL");
1122 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001123 }
1124
Mathieu Chartier0795f232016-09-27 18:43:30 -07001125 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001126 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001127 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001128 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001129 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1130 java_array,
1131 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001132 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001133 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001134 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001135 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
Ian Rogers68d8b422014-07-17 11:09:10 -07001140 bool CheckBoolean(jboolean z) {
1141 if (z != JNI_TRUE && z != JNI_FALSE) {
1142 AbortF("unexpected jboolean value: %d", z);
1143 return false;
1144 }
1145 return true;
1146 }
1147
1148 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001149 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001150 AbortF("negative jsize: %d", length);
1151 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001152 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001153 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001154 }
1155
Andreas Gampe08883de2016-11-08 13:20:52 -08001156 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001157 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001158 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001159 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001160 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001161 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001162 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001163 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001164 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001165 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001166 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001167 }
1168 return f;
1169 }
1170
Andreas Gampe13b27842016-11-07 16:48:23 -08001171 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001172 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001173 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001174 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001175 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001176 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001177 // TODO: Better check here.
1178 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001179 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001180 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001181 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001182 }
1183 return m;
1184 }
1185
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001186 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001187 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001188 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001189 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1190 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001191 }
1192
Daniel Erat35e827a2016-05-10 18:07:18 -06001193 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001194 JNIEnvExt* threadEnv = self->GetJniEnv();
1195
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001196 // Verify that the current thread is (a) attached and (b) associated with
1197 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001198 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001199 // Get the thread owning the JNIEnv that's being used.
1200 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001201 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001202 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001203 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001204 }
1205
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001206 // Verify that, if this thread previously made a critical "get" call, we
1207 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001208 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001209 case kFlag_CritOkay: // okay to call this method
1210 break;
1211 case kFlag_CritBad: // not okay to call
1212 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001213 AbortF("thread %s using JNI after critical get",
1214 ToStr<Thread>(*self).c_str());
1215 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001216 }
1217 break;
1218 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001219 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001220 threadEnv->critical++;
1221 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001222 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001223 threadEnv->critical--;
1224 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001225 AbortF("thread %s called too many critical releases",
1226 ToStr<Thread>(*self).c_str());
1227 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001228 }
1229 break;
1230 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001231 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001232 }
1233
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001234 // Verify that, if an exception has been raised, the native code doesn't
1235 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001236 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001237 mirror::Throwable* exception = self->GetException();
1238 AbortF("JNI %s called with pending exception %s",
1239 function_name_,
1240 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001241 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001242 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001243 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001244 }
1245
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001246 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001247 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001248 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001249 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001250 AbortF("non-nullable const char* was NULL");
1251 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001252 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001253 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001254 }
1255
Ian Rogersef7d42f2014-01-06 12:55:46 -08001256 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001257 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001258 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001259 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1260 // practice anyways.
1261 std::ostringstream oss;
1262 oss << std::hex;
1263 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1264 while (*tmp != 0) {
1265 if (tmp == utf8) {
1266 oss << "<";
1267 }
1268 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1269 if (tmp == utf8) {
1270 oss << '>';
1271 }
1272 tmp++;
1273 if (*tmp != 0) {
1274 oss << ' ';
1275 }
1276 }
1277
Ian Rogers68d8b422014-07-17 11:09:10 -07001278 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001279 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001280 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001281 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001282 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001283 }
1284
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001285 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1286 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001287 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001288 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001289 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001290 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001291 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001292 case 0x00:
1293 case 0x01:
1294 case 0x02:
1295 case 0x03:
1296 case 0x04:
1297 case 0x05:
1298 case 0x06:
1299 case 0x07:
1300 // Bit pattern 0xxx. No need for any extra bytes.
1301 break;
1302 case 0x08:
1303 case 0x09:
1304 case 0x0a:
1305 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001306 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001307 *errorKind = "start";
1308 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001309 case 0x0f:
1310 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001311 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001312 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1313 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001314 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1315 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001316 *errorKind = "continuation";
1317 return utf8;
1318 }
1319 } else {
1320 *errorKind = "start";
1321 return utf8;
1322 }
1323
1324 // Fall through to the cases below to consume two more continuation bytes.
1325 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001326 case 0x0e:
1327 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001328 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1329 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001330 *errorKind = "continuation";
1331 return utf8;
1332 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001333
1334 // Fall through to consume one more continuation byte.
1335 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001336 case 0x0c:
1337 case 0x0d:
1338 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001339 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1340 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001341 *errorKind = "continuation";
1342 return utf8;
1343 }
1344 break;
1345 }
1346 }
1347 return 0;
1348 }
1349
Ian Rogers68d8b422014-07-17 11:09:10 -07001350 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1351 va_list args;
1352 va_start(args, fmt);
1353 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1354 va_end(args);
1355 }
1356
1357 // The name of the JNI function being checked.
1358 const char* const function_name_;
1359
1360 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001361 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001362
Ian Rogers68d8b422014-07-17 11:09:10 -07001363 const bool has_method_;
1364
Elliott Hughesa2501992011-08-26 19:39:54 -07001365 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1366};
1367
Elliott Hughesa2501992011-08-26 19:39:54 -07001368/*
1369 * ===========================================================================
1370 * Guarded arrays
1371 * ===========================================================================
1372 */
1373
Elliott Hughesa2501992011-08-26 19:39:54 -07001374/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001375class GuardedCopy {
1376 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001377 /*
1378 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1379 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001380 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001381 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001382 const size_t new_len = LengthIncludingRedZones(len);
1383 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001384
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001385 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001386 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001387 if (!mod_okay) {
1388 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001389 }
1390
Ian Rogers68d8b422014-07-17 11:09:10 -07001391 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001392
Ian Rogers68d8b422014-07-17 11:09:10 -07001393 // Fill begin region with canary pattern.
1394 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1395 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1396 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1397 if (kCanary[j] == '\0') {
1398 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001399 } else {
1400 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001401 }
1402 }
1403
1404 // Copy the data in; note "len" could be zero.
1405 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1406
1407 // Fill end region with canary pattern.
1408 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1409 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1410 if (kCanary[j] == '\0') {
1411 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001412 } else {
1413 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001414 }
1415 }
1416
1417 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001418 }
1419
1420 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001421 * Create a guarded copy of a primitive array. Modifications to the copied
1422 * data are allowed. Returns a pointer to the copied data.
1423 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001424 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1425 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001426 ScopedObjectAccess soa(env);
1427
Mathieu Chartier0795f232016-09-27 18:43:30 -07001428 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001429 size_t component_size = a->GetClass()->GetComponentSize();
1430 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001431 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001432 if (is_copy != nullptr) {
1433 *is_copy = JNI_TRUE;
1434 }
1435 return result;
1436 }
1437
1438 /*
1439 * Perform the array "release" operation, which may or may not copy data
1440 * back into the managed heap, and may or may not release the underlying storage.
1441 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001442 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1443 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1444 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001445 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001446 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1447 return nullptr;
1448 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001449 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1450 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001451 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001452 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001453 }
1454 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001455 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001456 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001457 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001458 }
1459
1460
1461 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001462 * Free up the guard buffer, scrub it, and return the original pointer.
1463 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001464 static void* Destroy(void* embedded_buf) {
1465 GuardedCopy* copy = FromEmbedded(embedded_buf);
1466 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1467 size_t len = LengthIncludingRedZones(copy->original_length_);
1468 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001469 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001470 }
1471
1472 /*
1473 * Verify the guard area and, if "modOkay" is false, that the data itself
1474 * has not been altered.
1475 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001476 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001477 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001478 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1479 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1480 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001481 }
1482
1483 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001484 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001485 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1486 }
1487
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001488 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001489 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001490 if (result == MAP_FAILED) {
1491 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1492 }
1493 return reinterpret_cast<uint8_t*>(result);
1494 }
1495
Ian Rogers68d8b422014-07-17 11:09:10 -07001496 static void DebugFree(void* buf, size_t len) {
1497 if (munmap(buf, len) != 0) {
1498 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001499 }
1500 }
1501
Ian Rogers68d8b422014-07-17 11:09:10 -07001502 static size_t LengthIncludingRedZones(size_t len) {
1503 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001504 }
1505
Ian Rogers68d8b422014-07-17 11:09:10 -07001506 // Get the GuardedCopy from the interior pointer.
1507 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1508 return reinterpret_cast<GuardedCopy*>(
1509 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001510 }
1511
Ian Rogers68d8b422014-07-17 11:09:10 -07001512 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1513 return reinterpret_cast<const GuardedCopy*>(
1514 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001515 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001516
1517 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1518 va_list args;
1519 va_start(args, fmt);
1520 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1521 va_end(args);
1522 }
1523
1524 bool CheckHeader(const char* function_name, bool mod_okay) const {
1525 static const uint32_t kMagicCmp = kGuardMagic;
1526
1527 // Before we do anything with "pExtra", check the magic number. We
1528 // do the check with memcmp rather than "==" in case the pointer is
1529 // unaligned. If it points to completely bogus memory we're going
1530 // to crash, but there's no easy way around that.
1531 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1532 uint8_t buf[4];
1533 memcpy(buf, &magic_, 4);
1534 AbortF(function_name,
1535 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1536 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1537 return false;
1538 }
1539
1540 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1541 // told the client that we made a copy, there's no reason they can't alter the buffer.
1542 if (!mod_okay) {
1543 uLong computed_adler =
1544 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1545 if (computed_adler != adler_) {
1546 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1547 computed_adler, adler_, this);
1548 return false;
1549 }
1550 }
1551 return true;
1552 }
1553
1554 bool CheckRedZones(const char* function_name) const {
1555 // Check the begin red zone.
1556 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1557 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1558 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1559 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1560 return false;
1561 }
1562 if (kCanary[j] == '\0') {
1563 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001564 } else {
1565 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001566 }
1567 }
1568
1569 // Check end region.
1570 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1571 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1572 size_t offset_from_buffer_start =
1573 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1574 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1575 offset_from_buffer_start);
1576 return false;
1577 }
1578 if (kCanary[j] == '\0') {
1579 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001580 } else {
1581 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001582 }
1583 }
1584 return true;
1585 }
1586
1587 // Location that canary value will be written before the guarded region.
1588 const char* StartRedZone() const {
1589 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1590 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1591 }
1592
1593 // Return the interior embedded buffer.
1594 const uint8_t* BufferWithinRedZones() const {
1595 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1596 return embedded_buf;
1597 }
1598
1599 // Location that canary value will be written after the guarded region.
1600 const char* EndRedZone() const {
1601 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1602 size_t buf_len = LengthIncludingRedZones(original_length_);
1603 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1604 }
1605
1606 static constexpr size_t kRedZoneSize = 512;
1607 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1608
1609 // Value written before and after the guarded array.
1610 static const char* const kCanary;
1611
1612 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1613
1614 const uint32_t magic_;
1615 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001616 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001617 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001618};
Ian Rogers68d8b422014-07-17 11:09:10 -07001619const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001620
1621/*
1622 * ===========================================================================
1623 * JNI functions
1624 * ===========================================================================
1625 */
1626
1627class CheckJNI {
1628 public:
1629 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001630 ScopedObjectAccess soa(env);
1631 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1632 JniValueType args[1] = {{.E = env }};
1633 if (sc.Check(soa, true, "E", args)) {
1634 JniValueType result;
1635 result.I = baseEnv(env)->GetVersion(env);
1636 if (sc.Check(soa, false, "I", &result)) {
1637 return result.I;
1638 }
1639 }
1640 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001641 }
1642
Ian Rogers68d8b422014-07-17 11:09:10 -07001643 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1644 ScopedObjectAccess soa(env);
1645 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1646 JniValueType args[2] = {{.E = env }, {.p = vm}};
1647 if (sc.Check(soa, true, "Ep", args)) {
1648 JniValueType result;
1649 result.i = baseEnv(env)->GetJavaVM(env, vm);
1650 if (sc.Check(soa, false, "i", &result)) {
1651 return result.i;
1652 }
1653 }
1654 return JNI_ERR;
1655 }
1656
1657 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1658 ScopedObjectAccess soa(env);
1659 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1660 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1661 if (sc.Check(soa, true, "EcpI", args)) {
1662 JniValueType result;
1663 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1664 if (sc.Check(soa, false, "i", &result)) {
1665 return result.i;
1666 }
1667 }
1668 return JNI_ERR;
1669 }
1670
1671 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1672 ScopedObjectAccess soa(env);
1673 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1674 JniValueType args[2] = {{.E = env }, {.c = c}};
1675 if (sc.Check(soa, true, "Ec", args)) {
1676 JniValueType result;
1677 result.i = baseEnv(env)->UnregisterNatives(env, c);
1678 if (sc.Check(soa, false, "i", &result)) {
1679 return result.i;
1680 }
1681 }
1682 return JNI_ERR;
1683 }
1684
1685 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001686 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1687 // know the object is invalid. The spec says that passing invalid objects or even ones that
1688 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001689 ScopedObjectAccess soa(env);
1690 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001691 JniValueType args[2] = {{.E = env }, {.L = obj}};
1692 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001693 JniValueType result;
1694 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1695 if (sc.Check(soa, false, "w", &result)) {
1696 return result.w;
1697 }
1698 }
1699 return JNIInvalidRefType;
1700 }
1701
1702 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1703 jsize bufLen) {
1704 ScopedObjectAccess soa(env);
1705 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1706 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1707 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1708 JniValueType result;
1709 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
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
1717 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001718 ScopedObjectAccess soa(env);
1719 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1720 JniValueType args[2] = {{.E = env}, {.u = name}};
1721 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1722 JniValueType result;
1723 result.c = baseEnv(env)->FindClass(env, name);
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 jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001732 ScopedObjectAccess soa(env);
1733 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1734 JniValueType args[2] = {{.E = env}, {.c = c}};
1735 if (sc.Check(soa, true, "Ec", args)) {
1736 JniValueType result;
1737 result.c = baseEnv(env)->GetSuperclass(env, c);
1738 if (sc.Check(soa, false, "c", &result)) {
1739 return result.c;
1740 }
1741 }
1742 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001743 }
1744
Elliott Hughese84278b2012-03-22 10:06:53 -07001745 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001746 ScopedObjectAccess soa(env);
1747 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1748 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1749 if (sc.Check(soa, true, "Ecc", args)) {
1750 JniValueType result;
1751 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1752 if (sc.Check(soa, false, "b", &result)) {
1753 return result.b;
1754 }
1755 }
1756 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001757 }
1758
1759 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001760 ScopedObjectAccess soa(env);
1761 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1762 JniValueType args[2] = {{.E = env}, {.L = method}};
1763 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1764 JniValueType result;
1765 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1766 if (sc.Check(soa, false, "m", &result)) {
1767 return result.m;
1768 }
1769 }
1770 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001771 }
1772
1773 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001774 ScopedObjectAccess soa(env);
1775 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1776 JniValueType args[2] = {{.E = env}, {.L = field}};
1777 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1778 JniValueType result;
1779 result.f = baseEnv(env)->FromReflectedField(env, field);
1780 if (sc.Check(soa, false, "f", &result)) {
1781 return result.f;
1782 }
1783 }
1784 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001785 }
1786
1787 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001788 ScopedObjectAccess soa(env);
1789 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1790 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1791 if (sc.Check(soa, true, "Ecmb", args)) {
1792 JniValueType result;
1793 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1794 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1795 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1796 return result.L;
1797 }
1798 }
1799 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001800 }
1801
1802 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001803 ScopedObjectAccess soa(env);
1804 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1805 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1806 if (sc.Check(soa, true, "Ecfb", args)) {
1807 JniValueType result;
1808 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1809 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1810 DCHECK(sc.CheckReflectedField(soa, result.L));
1811 return result.L;
1812 }
1813 }
1814 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001815 }
1816
1817 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001818 ScopedObjectAccess soa(env);
1819 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1820 JniValueType args[2] = {{.E = env}, {.t = obj}};
1821 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1822 JniValueType result;
1823 result.i = baseEnv(env)->Throw(env, obj);
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
Elliott Hughese84278b2012-03-22 10:06:53 -07001831 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001832 ScopedObjectAccess soa(env);
1833 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001834 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001835 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1836 JniValueType result;
1837 result.i = baseEnv(env)->ThrowNew(env, c, message);
1838 if (sc.Check(soa, false, "i", &result)) {
1839 return result.i;
1840 }
1841 }
1842 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001843 }
1844
1845 static jthrowable ExceptionOccurred(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 result.t = baseEnv(env)->ExceptionOccurred(env);
1852 if (sc.Check(soa, false, "t", &result)) {
1853 return result.t;
1854 }
1855 }
1856 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001857 }
1858
1859 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001860 ScopedObjectAccess soa(env);
1861 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1862 JniValueType args[1] = {{.E = env}};
1863 if (sc.Check(soa, true, "E", args)) {
1864 JniValueType result;
1865 baseEnv(env)->ExceptionDescribe(env);
1866 result.V = nullptr;
1867 sc.Check(soa, false, "V", &result);
1868 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001869 }
1870
1871 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001872 ScopedObjectAccess soa(env);
1873 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1874 JniValueType args[1] = {{.E = env}};
1875 if (sc.Check(soa, true, "E", args)) {
1876 JniValueType result;
1877 baseEnv(env)->ExceptionClear(env);
1878 result.V = nullptr;
1879 sc.Check(soa, false, "V", &result);
1880 }
1881 }
1882
1883 static jboolean ExceptionCheck(JNIEnv* env) {
1884 ScopedObjectAccess soa(env);
1885 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1886 JniValueType args[1] = {{.E = env}};
1887 if (sc.Check(soa, true, "E", args)) {
1888 JniValueType result;
1889 result.b = baseEnv(env)->ExceptionCheck(env);
1890 if (sc.Check(soa, false, "b", &result)) {
1891 return result.b;
1892 }
1893 }
1894 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001895 }
1896
1897 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001898 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1899 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1900 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001901 ScopedObjectAccess soa(env);
1902 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1903 JniValueType args[2] = {{.E = env}, {.u = msg}};
1904 if (sc.Check(soa, true, "Eu", args)) {
1905 JniValueType result;
1906 baseEnv(env)->FatalError(env, msg);
1907 // Unreachable.
1908 result.V = nullptr;
1909 sc.Check(soa, false, "V", &result);
1910 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001911 }
1912
1913 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001914 ScopedObjectAccess soa(env);
1915 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1916 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1917 if (sc.Check(soa, true, "EI", args)) {
1918 JniValueType result;
1919 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1920 if (sc.Check(soa, false, "i", &result)) {
1921 return result.i;
1922 }
1923 }
1924 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001925 }
1926
1927 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001928 ScopedObjectAccess soa(env);
1929 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1930 JniValueType args[2] = {{.E = env}, {.L = res}};
1931 if (sc.Check(soa, true, "EL", args)) {
1932 JniValueType result;
1933 result.L = baseEnv(env)->PopLocalFrame(env, res);
1934 sc.Check(soa, false, "L", &result);
1935 return result.L;
1936 }
1937 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001938 }
1939
1940 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001941 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001942 }
1943
Ian Rogers68d8b422014-07-17 11:09:10 -07001944 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1945 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001946 }
1947
1948 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001949 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001950 }
1951
Ian Rogers68d8b422014-07-17 11:09:10 -07001952 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1953 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001954 }
1955
Ian Rogers68d8b422014-07-17 11:09:10 -07001956 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1957 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1958 }
1959
1960 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1961 DeleteRef(__FUNCTION__, env, obj, kLocal);
1962 }
1963
1964 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1965 ScopedObjectAccess soa(env);
1966 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1967 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1968 if (sc.Check(soa, true, "EI", args)) {
1969 JniValueType result;
1970 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1971 if (sc.Check(soa, false, "i", &result)) {
1972 return result.i;
1973 }
1974 }
1975 return JNI_ERR;
1976 }
1977
1978 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1979 ScopedObjectAccess soa(env);
1980 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1981 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1982 if (sc.Check(soa, true, "ELL", args)) {
1983 JniValueType result;
1984 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1985 if (sc.Check(soa, false, "b", &result)) {
1986 return result.b;
1987 }
1988 }
1989 return JNI_FALSE;
1990 }
1991
1992 static jobject AllocObject(JNIEnv* env, jclass c) {
1993 ScopedObjectAccess soa(env);
1994 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1995 JniValueType args[2] = {{.E = env}, {.c = c}};
1996 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1997 JniValueType result;
1998 result.L = baseEnv(env)->AllocObject(env, c);
1999 if (sc.Check(soa, false, "L", &result)) {
2000 return result.L;
2001 }
2002 }
2003 return nullptr;
2004 }
2005
2006 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2007 ScopedObjectAccess soa(env);
2008 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002009 VarArgs rest(mid, vargs);
2010 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2011 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002012 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002013 JniValueType result;
2014 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2015 if (sc.Check(soa, false, "L", &result)) {
2016 return result.L;
2017 }
2018 }
2019 return nullptr;
2020 }
2021
2022 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2023 va_list args;
2024 va_start(args, mid);
2025 jobject result = NewObjectV(env, c, mid, args);
2026 va_end(args);
2027 return result;
2028 }
2029
2030 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2031 ScopedObjectAccess soa(env);
2032 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002033 VarArgs rest(mid, vargs);
2034 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2035 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002036 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002037 JniValueType result;
2038 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2039 if (sc.Check(soa, false, "L", &result)) {
2040 return result.L;
2041 }
2042 }
2043 return nullptr;
2044 }
2045
2046 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2047 ScopedObjectAccess soa(env);
2048 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2049 JniValueType args[2] = {{.E = env}, {.L = obj}};
2050 if (sc.Check(soa, true, "EL", args)) {
2051 JniValueType result;
2052 result.c = baseEnv(env)->GetObjectClass(env, obj);
2053 if (sc.Check(soa, false, "c", &result)) {
2054 return result.c;
2055 }
2056 }
2057 return nullptr;
2058 }
2059
2060 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2061 ScopedObjectAccess soa(env);
2062 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2063 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2064 if (sc.Check(soa, true, "ELc", args)) {
2065 JniValueType result;
2066 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2067 if (sc.Check(soa, false, "b", &result)) {
2068 return result.b;
2069 }
2070 }
2071 return JNI_FALSE;
2072 }
2073
2074 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2075 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2076 }
2077
2078 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2079 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2080 }
2081
2082 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2083 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2084 }
2085
2086 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2087 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2088 }
2089
2090#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2091 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2092 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2093 } \
2094 \
2095 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2096 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2097 } \
2098 \
2099 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2100 JniValueType value; \
2101 value.shorty = v; \
2102 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2103 } \
2104 \
2105 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2106 JniValueType value; \
2107 value.shorty = v; \
2108 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2109 }
2110
2111 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2112 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2113 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2114 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2115 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2116 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2117 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2118 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2119 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2120#undef FIELD_ACCESSORS
2121
2122 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2123 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2124 }
2125
2126 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2127 jvalue* vargs) {
2128 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2129 }
2130
2131 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002132 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002133 }
2134
2135 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2136 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2137 }
2138
2139 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2140 va_list vargs) {
2141 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2142 }
2143
2144 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2145 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2146 }
2147
2148 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2149 va_list vargs;
2150 va_start(vargs, mid);
2151 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2152 va_end(vargs);
2153 }
2154
2155 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2156 va_list vargs;
2157 va_start(vargs, mid);
2158 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2159 va_end(vargs);
2160 }
2161
2162 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2163 va_list vargs;
2164 va_start(vargs, mid);
2165 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2166 va_end(vargs);
2167 }
2168
2169#define CALL(rtype, name, ptype, shorty) \
2170 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2171 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2172 } \
2173 \
2174 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2175 jvalue* vargs) { \
2176 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2177 } \
2178 \
2179 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2180 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2181 } \
2182 \
2183 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2184 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2185 } \
2186 \
2187 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2188 va_list vargs) { \
2189 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2190 } \
2191 \
2192 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2193 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2194 } \
2195 \
2196 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2197 va_list vargs; \
2198 va_start(vargs, mid); \
2199 rtype result = \
2200 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2201 va_end(vargs); \
2202 return result; \
2203 } \
2204 \
2205 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2206 ...) { \
2207 va_list vargs; \
2208 va_start(vargs, mid); \
2209 rtype result = \
2210 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2211 va_end(vargs); \
2212 return result; \
2213 } \
2214 \
2215 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2216 va_list vargs; \
2217 va_start(vargs, mid); \
2218 rtype result = \
2219 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2220 va_end(vargs); \
2221 return result; \
2222 }
2223
2224 CALL(jobject, Object, Primitive::kPrimNot, L)
2225 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2226 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2227 CALL(jchar, Char, Primitive::kPrimChar, C)
2228 CALL(jshort, Short, Primitive::kPrimShort, S)
2229 CALL(jint, Int, Primitive::kPrimInt, I)
2230 CALL(jlong, Long, Primitive::kPrimLong, J)
2231 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2232 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2233#undef CALL
2234
2235 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2236 ScopedObjectAccess soa(env);
2237 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2238 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2239 if (sc.Check(soa, true, "Epz", args)) {
2240 JniValueType result;
2241 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2242 if (sc.Check(soa, false, "s", &result)) {
2243 return result.s;
2244 }
2245 }
2246 return nullptr;
2247 }
2248
2249 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2250 ScopedObjectAccess soa(env);
2251 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2252 JniValueType args[2] = {{.E = env}, {.u = chars}};
2253 if (sc.Check(soa, true, "Eu", args)) {
2254 JniValueType result;
2255 // TODO: stale? show pointer and truncate string.
2256 result.s = baseEnv(env)->NewStringUTF(env, chars);
2257 if (sc.Check(soa, false, "s", &result)) {
2258 return result.s;
2259 }
2260 }
2261 return nullptr;
2262 }
2263
2264 static jsize GetStringLength(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)->GetStringLength(env, string);
2271 if (sc.Check(soa, false, "z", &result)) {
2272 return result.z;
2273 }
2274 }
2275 return JNI_ERR;
2276 }
2277
2278 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2279 ScopedObjectAccess soa(env);
2280 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2281 JniValueType args[2] = {{.E = env}, {.s = string}};
2282 if (sc.Check(soa, true, "Es", args)) {
2283 JniValueType result;
2284 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2285 if (sc.Check(soa, false, "z", &result)) {
2286 return result.z;
2287 }
2288 }
2289 return JNI_ERR;
2290 }
2291
2292 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2293 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2294 is_copy, false, false));
2295 }
2296
2297 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2298 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2299 is_copy, true, false));
2300 }
2301
2302 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2303 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2304 is_copy, false, true));
2305 }
2306
2307 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2308 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2309 }
2310
2311 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2312 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2313 }
2314
2315 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2316 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2317 }
2318
2319 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* 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)->GetStringRegion(env, string, start, len, buf);
2327 JniValueType result;
2328 result.V = nullptr;
2329 sc.Check(soa, false, "V", &result);
2330 }
2331 }
2332
2333 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2334 ScopedObjectAccess soa(env);
2335 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2336 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2337 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2338 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2339 if (sc.Check(soa, true, "EsIIp", args)) {
2340 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2341 JniValueType result;
2342 result.V = nullptr;
2343 sc.Check(soa, false, "V", &result);
2344 }
2345 }
2346
2347 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2348 ScopedObjectAccess soa(env);
2349 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2350 JniValueType args[2] = {{.E = env}, {.a = array}};
2351 if (sc.Check(soa, true, "Ea", args)) {
2352 JniValueType result;
2353 result.z = baseEnv(env)->GetArrayLength(env, array);
2354 if (sc.Check(soa, false, "z", &result)) {
2355 return result.z;
2356 }
2357 }
2358 return JNI_ERR;
2359 }
2360
2361 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2362 jobject initial_element) {
2363 ScopedObjectAccess soa(env);
2364 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2365 JniValueType args[4] =
2366 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2367 if (sc.Check(soa, true, "EzcL", args)) {
2368 JniValueType result;
2369 // Note: assignability tests of initial_element are done in the base implementation.
2370 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2371 if (sc.Check(soa, false, "a", &result)) {
2372 return down_cast<jobjectArray>(result.a);
2373 }
2374 }
2375 return nullptr;
2376 }
2377
2378 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2379 ScopedObjectAccess soa(env);
2380 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2381 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2382 if (sc.Check(soa, true, "Eaz", args)) {
2383 JniValueType result;
2384 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2385 if (sc.Check(soa, false, "L", &result)) {
2386 return result.L;
2387 }
2388 }
2389 return nullptr;
2390 }
2391
2392 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2393 ScopedObjectAccess soa(env);
2394 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2395 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2396 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2397 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2398 // in ArrayStoreExceptions.
2399 if (sc.Check(soa, true, "EaIL", args)) {
2400 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2401 JniValueType result;
2402 result.V = nullptr;
2403 sc.Check(soa, false, "V", &result);
2404 }
2405 }
2406
2407 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2408 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2409 Primitive::kPrimBoolean));
2410 }
2411
2412 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2413 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2414 Primitive::kPrimByte));
2415 }
2416
2417 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2418 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2419 Primitive::kPrimChar));
2420 }
2421
2422 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2423 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2424 Primitive::kPrimShort));
2425 }
2426
2427 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2428 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2429 }
2430
2431 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2432 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2433 Primitive::kPrimLong));
2434 }
2435
2436 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2437 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2438 Primitive::kPrimFloat));
2439 }
2440
2441 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2442 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2443 Primitive::kPrimDouble));
2444 }
2445
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002446// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002447#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002448 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2449 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002450 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2451 } \
2452 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002453 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002454 jint mode) { \
2455 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2456 } \
2457 \
2458 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002459 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002460 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2461 } \
2462 \
2463 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2464 const ctype* buf) { \
2465 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2466 }
2467
2468 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2469 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2470 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2471 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2472 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2473 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2474 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2475 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2476#undef PRIMITIVE_ARRAY_FUNCTIONS
2477
2478 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2479 ScopedObjectAccess soa(env);
2480 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2481 JniValueType args[2] = {{.E = env}, {.L = obj}};
2482 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002483 if (obj != nullptr) {
2484 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2485 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002486 JniValueType result;
2487 result.i = baseEnv(env)->MonitorEnter(env, obj);
2488 if (sc.Check(soa, false, "i", &result)) {
2489 return result.i;
2490 }
2491 }
2492 return JNI_ERR;
2493 }
2494
2495 static jint MonitorExit(JNIEnv* env, jobject obj) {
2496 ScopedObjectAccess soa(env);
2497 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2498 JniValueType args[2] = {{.E = env}, {.L = obj}};
2499 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002500 if (obj != nullptr) {
2501 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2502 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002503 JniValueType result;
2504 result.i = baseEnv(env)->MonitorExit(env, obj);
2505 if (sc.Check(soa, false, "i", &result)) {
2506 return result.i;
2507 }
2508 }
2509 return JNI_ERR;
2510 }
2511
2512 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2513 ScopedObjectAccess soa(env);
2514 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2515 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2516 if (sc.Check(soa, true, "Eap", args)) {
2517 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002518 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2519 if (ptr != nullptr && soa.ForceCopy()) {
2520 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002521 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002522 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002523 if (sc.Check(soa, false, "p", &result)) {
2524 return const_cast<void*>(result.p);
2525 }
2526 }
2527 return nullptr;
2528 }
2529
2530 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2531 ScopedObjectAccess soa(env);
2532 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2533 sc.CheckNonNull(carray);
2534 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2535 if (sc.Check(soa, true, "Eapr", args)) {
2536 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002537 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002538 }
2539 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2540 JniValueType result;
2541 result.V = nullptr;
2542 sc.Check(soa, false, "V", &result);
2543 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002544 }
2545
2546 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002547 ScopedObjectAccess soa(env);
2548 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2549 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2550 if (sc.Check(soa, true, "EpJ", args)) {
2551 JniValueType result;
2552 // Note: the validity of address and capacity are checked in the base implementation.
2553 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2554 if (sc.Check(soa, false, "L", &result)) {
2555 return result.L;
2556 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002557 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002558 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002559 }
2560
2561 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002562 ScopedObjectAccess soa(env);
2563 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2564 JniValueType args[2] = {{.E = env}, {.L = buf}};
2565 if (sc.Check(soa, true, "EL", args)) {
2566 JniValueType result;
2567 // Note: this is implemented in the base environment by a GetLongField which will sanity
2568 // check the type of buf in GetLongField above.
2569 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2570 if (sc.Check(soa, false, "p", &result)) {
2571 return const_cast<void*>(result.p);
2572 }
2573 }
2574 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002575 }
2576
2577 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002578 ScopedObjectAccess soa(env);
2579 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2580 JniValueType args[2] = {{.E = env}, {.L = buf}};
2581 if (sc.Check(soa, true, "EL", args)) {
2582 JniValueType result;
2583 // Note: this is implemented in the base environment by a GetIntField which will sanity
2584 // check the type of buf in GetIntField above.
2585 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2586 if (sc.Check(soa, false, "J", &result)) {
2587 return result.J;
2588 }
2589 }
2590 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002591 }
2592
2593 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002594 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2595 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2596 }
2597
2598 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002599 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2600 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002601
2602 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2603 ScopedObjectAccess soa(env);
2604 ScopedCheck sc(kFlag_Default, function_name);
2605 JniValueType args[2] = {{.E = env}, {.L = obj}};
2606 if (sc.Check(soa, true, "EL", args)) {
2607 JniValueType result;
2608 switch (kind) {
2609 case kGlobal:
2610 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2611 break;
2612 case kLocal:
2613 result.L = baseEnv(env)->NewLocalRef(env, obj);
2614 break;
2615 case kWeakGlobal:
2616 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2617 break;
2618 default:
2619 LOG(FATAL) << "Unexpected reference kind: " << kind;
2620 }
2621 if (sc.Check(soa, false, "L", &result)) {
2622 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002623 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002624 return result.L;
2625 }
2626 }
2627 return nullptr;
2628 }
2629
2630 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2631 ScopedObjectAccess soa(env);
2632 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2633 JniValueType args[2] = {{.E = env}, {.L = obj}};
2634 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002635 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002636 JniValueType result;
2637 switch (kind) {
2638 case kGlobal:
2639 baseEnv(env)->DeleteGlobalRef(env, obj);
2640 break;
2641 case kLocal:
2642 baseEnv(env)->DeleteLocalRef(env, obj);
2643 break;
2644 case kWeakGlobal:
2645 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2646 break;
2647 default:
2648 LOG(FATAL) << "Unexpected reference kind: " << kind;
2649 }
2650 result.V = nullptr;
2651 sc.Check(soa, false, "V", &result);
2652 }
2653 }
2654
2655 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2656 const char* name, const char* sig, bool is_static) {
2657 ScopedObjectAccess soa(env);
2658 ScopedCheck sc(kFlag_Default, function_name);
2659 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2660 if (sc.Check(soa, true, "Ecuu", args)) {
2661 JniValueType result;
2662 if (is_static) {
2663 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2664 } else {
2665 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2666 }
2667 if (sc.Check(soa, false, "m", &result)) {
2668 return result.m;
2669 }
2670 }
2671 return nullptr;
2672 }
2673
2674 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2675 const char* name, const char* sig, bool is_static) {
2676 ScopedObjectAccess soa(env);
2677 ScopedCheck sc(kFlag_Default, function_name);
2678 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2679 if (sc.Check(soa, true, "Ecuu", args)) {
2680 JniValueType result;
2681 if (is_static) {
2682 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2683 } else {
2684 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2685 }
2686 if (sc.Check(soa, false, "f", &result)) {
2687 return result.f;
2688 }
2689 }
2690 return nullptr;
2691 }
2692
2693 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2694 bool is_static, Primitive::Type type) {
2695 ScopedObjectAccess soa(env);
2696 ScopedCheck sc(kFlag_Default, function_name);
2697 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2698 JniValueType result;
2699 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2700 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2701 const char* result_check = nullptr;
2702 switch (type) {
2703 case Primitive::kPrimNot:
2704 if (is_static) {
2705 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2706 } else {
2707 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2708 }
2709 result_check = "L";
2710 break;
2711 case Primitive::kPrimBoolean:
2712 if (is_static) {
2713 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2714 } else {
2715 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2716 }
2717 result_check = "Z";
2718 break;
2719 case Primitive::kPrimByte:
2720 if (is_static) {
2721 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2722 } else {
2723 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2724 }
2725 result_check = "B";
2726 break;
2727 case Primitive::kPrimChar:
2728 if (is_static) {
2729 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2730 } else {
2731 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2732 }
2733 result_check = "C";
2734 break;
2735 case Primitive::kPrimShort:
2736 if (is_static) {
2737 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2738 } else {
2739 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2740 }
2741 result_check = "S";
2742 break;
2743 case Primitive::kPrimInt:
2744 if (is_static) {
2745 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2746 } else {
2747 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2748 }
2749 result_check = "I";
2750 break;
2751 case Primitive::kPrimLong:
2752 if (is_static) {
2753 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2754 } else {
2755 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2756 }
2757 result_check = "J";
2758 break;
2759 case Primitive::kPrimFloat:
2760 if (is_static) {
2761 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2762 } else {
2763 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2764 }
2765 result_check = "F";
2766 break;
2767 case Primitive::kPrimDouble:
2768 if (is_static) {
2769 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2770 } else {
2771 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2772 }
2773 result_check = "D";
2774 break;
2775 case Primitive::kPrimVoid:
2776 LOG(FATAL) << "Unexpected type: " << type;
2777 break;
2778 }
2779 if (sc.Check(soa, false, result_check, &result)) {
2780 return result;
2781 }
2782 }
2783 result.J = 0;
2784 return result;
2785 }
2786
2787 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2788 bool is_static, Primitive::Type type, JniValueType value) {
2789 ScopedObjectAccess soa(env);
2790 ScopedCheck sc(kFlag_Default, function_name);
2791 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2792 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2793 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2794 if (sc.Check(soa, true, sig, args) &&
2795 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2796 switch (type) {
2797 case Primitive::kPrimNot:
2798 if (is_static) {
2799 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2800 } else {
2801 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2802 }
2803 break;
2804 case Primitive::kPrimBoolean:
2805 if (is_static) {
2806 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2807 } else {
2808 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2809 }
2810 break;
2811 case Primitive::kPrimByte:
2812 if (is_static) {
2813 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2814 } else {
2815 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2816 }
2817 break;
2818 case Primitive::kPrimChar:
2819 if (is_static) {
2820 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2821 } else {
2822 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2823 }
2824 break;
2825 case Primitive::kPrimShort:
2826 if (is_static) {
2827 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2828 } else {
2829 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2830 }
2831 break;
2832 case Primitive::kPrimInt:
2833 if (is_static) {
2834 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2835 } else {
2836 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2837 }
2838 break;
2839 case Primitive::kPrimLong:
2840 if (is_static) {
2841 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2842 } else {
2843 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2844 }
2845 break;
2846 case Primitive::kPrimFloat:
2847 if (is_static) {
2848 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2849 } else {
2850 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2851 }
2852 break;
2853 case Primitive::kPrimDouble:
2854 if (is_static) {
2855 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2856 } else {
2857 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2858 }
2859 break;
2860 case Primitive::kPrimVoid:
2861 LOG(FATAL) << "Unexpected type: " << type;
2862 break;
2863 }
2864 JniValueType result;
2865 result.V = nullptr;
2866 sc.Check(soa, false, "V", &result);
2867 }
2868 }
2869
2870 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002871 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002872 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002873 bool checked;
2874 switch (invoke) {
2875 case kVirtual: {
2876 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002877 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2878 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002879 break;
2880 }
2881 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002882 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2883 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002884 break;
2885 }
2886 case kStatic: {
2887 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002888 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2889 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002890 break;
2891 }
2892 default:
2893 LOG(FATAL) << "Unexpected invoke: " << invoke;
2894 checked = false;
2895 break;
2896 }
2897 return checked;
2898 }
2899
2900 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2901 jmethodID mid, jvalue* vargs, Primitive::Type type,
2902 InvokeType invoke) {
2903 ScopedObjectAccess soa(env);
2904 ScopedCheck sc(kFlag_Default, function_name);
2905 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002906 VarArgs rest(mid, vargs);
2907 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002908 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2909 const char* result_check;
2910 switch (type) {
2911 case Primitive::kPrimNot:
2912 result_check = "L";
2913 switch (invoke) {
2914 case kVirtual:
2915 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2916 break;
2917 case kDirect:
2918 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2919 break;
2920 case kStatic:
2921 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2922 break;
2923 default:
2924 break;
2925 }
2926 break;
2927 case Primitive::kPrimBoolean:
2928 result_check = "Z";
2929 switch (invoke) {
2930 case kVirtual:
2931 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2932 break;
2933 case kDirect:
2934 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2935 break;
2936 case kStatic:
2937 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2938 break;
2939 default:
2940 break;
2941 }
2942 break;
2943 case Primitive::kPrimByte:
2944 result_check = "B";
2945 switch (invoke) {
2946 case kVirtual:
2947 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2948 break;
2949 case kDirect:
2950 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2951 break;
2952 case kStatic:
2953 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2954 break;
2955 default:
2956 break;
2957 }
2958 break;
2959 case Primitive::kPrimChar:
2960 result_check = "C";
2961 switch (invoke) {
2962 case kVirtual:
2963 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2964 break;
2965 case kDirect:
2966 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2967 break;
2968 case kStatic:
2969 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2970 break;
2971 default:
2972 break;
2973 }
2974 break;
2975 case Primitive::kPrimShort:
2976 result_check = "S";
2977 switch (invoke) {
2978 case kVirtual:
2979 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2980 break;
2981 case kDirect:
2982 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2983 break;
2984 case kStatic:
2985 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2986 break;
2987 default:
2988 break;
2989 }
2990 break;
2991 case Primitive::kPrimInt:
2992 result_check = "I";
2993 switch (invoke) {
2994 case kVirtual:
2995 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2996 break;
2997 case kDirect:
2998 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2999 break;
3000 case kStatic:
3001 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3002 break;
3003 default:
3004 break;
3005 }
3006 break;
3007 case Primitive::kPrimLong:
3008 result_check = "J";
3009 switch (invoke) {
3010 case kVirtual:
3011 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3012 break;
3013 case kDirect:
3014 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3015 break;
3016 case kStatic:
3017 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3018 break;
3019 default:
3020 break;
3021 }
3022 break;
3023 case Primitive::kPrimFloat:
3024 result_check = "F";
3025 switch (invoke) {
3026 case kVirtual:
3027 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3028 break;
3029 case kDirect:
3030 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3031 break;
3032 case kStatic:
3033 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3034 break;
3035 default:
3036 break;
3037 }
3038 break;
3039 case Primitive::kPrimDouble:
3040 result_check = "D";
3041 switch (invoke) {
3042 case kVirtual:
3043 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3044 break;
3045 case kDirect:
3046 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3047 break;
3048 case kStatic:
3049 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3050 break;
3051 default:
3052 break;
3053 }
3054 break;
3055 case Primitive::kPrimVoid:
3056 result_check = "V";
3057 result.V = nullptr;
3058 switch (invoke) {
3059 case kVirtual:
3060 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3061 break;
3062 case kDirect:
3063 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3064 break;
3065 case kStatic:
3066 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3067 break;
3068 default:
3069 LOG(FATAL) << "Unexpected invoke: " << invoke;
3070 }
3071 break;
3072 default:
3073 LOG(FATAL) << "Unexpected return type: " << type;
3074 result_check = nullptr;
3075 }
3076 if (sc.Check(soa, false, result_check, &result)) {
3077 return result;
3078 }
3079 }
3080 result.J = 0;
3081 return result;
3082 }
3083
3084 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3085 jmethodID mid, va_list vargs, Primitive::Type type,
3086 InvokeType invoke) {
3087 ScopedObjectAccess soa(env);
3088 ScopedCheck sc(kFlag_Default, function_name);
3089 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003090 VarArgs rest(mid, vargs);
3091 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003092 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3093 const char* result_check;
3094 switch (type) {
3095 case Primitive::kPrimNot:
3096 result_check = "L";
3097 switch (invoke) {
3098 case kVirtual:
3099 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3100 break;
3101 case kDirect:
3102 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3103 break;
3104 case kStatic:
3105 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3106 break;
3107 default:
3108 LOG(FATAL) << "Unexpected invoke: " << invoke;
3109 }
3110 break;
3111 case Primitive::kPrimBoolean:
3112 result_check = "Z";
3113 switch (invoke) {
3114 case kVirtual:
3115 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3116 break;
3117 case kDirect:
3118 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3119 break;
3120 case kStatic:
3121 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3122 break;
3123 default:
3124 LOG(FATAL) << "Unexpected invoke: " << invoke;
3125 }
3126 break;
3127 case Primitive::kPrimByte:
3128 result_check = "B";
3129 switch (invoke) {
3130 case kVirtual:
3131 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3132 break;
3133 case kDirect:
3134 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3135 break;
3136 case kStatic:
3137 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3138 break;
3139 default:
3140 LOG(FATAL) << "Unexpected invoke: " << invoke;
3141 }
3142 break;
3143 case Primitive::kPrimChar:
3144 result_check = "C";
3145 switch (invoke) {
3146 case kVirtual:
3147 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3148 break;
3149 case kDirect:
3150 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3151 break;
3152 case kStatic:
3153 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3154 break;
3155 default:
3156 LOG(FATAL) << "Unexpected invoke: " << invoke;
3157 }
3158 break;
3159 case Primitive::kPrimShort:
3160 result_check = "S";
3161 switch (invoke) {
3162 case kVirtual:
3163 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3164 break;
3165 case kDirect:
3166 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3167 break;
3168 case kStatic:
3169 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3170 break;
3171 default:
3172 LOG(FATAL) << "Unexpected invoke: " << invoke;
3173 }
3174 break;
3175 case Primitive::kPrimInt:
3176 result_check = "I";
3177 switch (invoke) {
3178 case kVirtual:
3179 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3180 break;
3181 case kDirect:
3182 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3183 break;
3184 case kStatic:
3185 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3186 break;
3187 default:
3188 LOG(FATAL) << "Unexpected invoke: " << invoke;
3189 }
3190 break;
3191 case Primitive::kPrimLong:
3192 result_check = "J";
3193 switch (invoke) {
3194 case kVirtual:
3195 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3196 break;
3197 case kDirect:
3198 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3199 break;
3200 case kStatic:
3201 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3202 break;
3203 default:
3204 LOG(FATAL) << "Unexpected invoke: " << invoke;
3205 }
3206 break;
3207 case Primitive::kPrimFloat:
3208 result_check = "F";
3209 switch (invoke) {
3210 case kVirtual:
3211 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3212 break;
3213 case kDirect:
3214 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3215 break;
3216 case kStatic:
3217 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3218 break;
3219 default:
3220 LOG(FATAL) << "Unexpected invoke: " << invoke;
3221 }
3222 break;
3223 case Primitive::kPrimDouble:
3224 result_check = "D";
3225 switch (invoke) {
3226 case kVirtual:
3227 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3228 break;
3229 case kDirect:
3230 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3231 break;
3232 case kStatic:
3233 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3234 break;
3235 default:
3236 LOG(FATAL) << "Unexpected invoke: " << invoke;
3237 }
3238 break;
3239 case Primitive::kPrimVoid:
3240 result_check = "V";
3241 result.V = nullptr;
3242 switch (invoke) {
3243 case kVirtual:
3244 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3245 break;
3246 case kDirect:
3247 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3248 break;
3249 case kStatic:
3250 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3251 break;
3252 default:
3253 LOG(FATAL) << "Unexpected invoke: " << invoke;
3254 }
3255 break;
3256 default:
3257 LOG(FATAL) << "Unexpected return type: " << type;
3258 result_check = nullptr;
3259 }
3260 if (sc.Check(soa, false, result_check, &result)) {
3261 return result;
3262 }
3263 }
3264 result.J = 0;
3265 return result;
3266 }
3267
3268 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3269 jboolean* is_copy, bool utf, bool critical) {
3270 ScopedObjectAccess soa(env);
3271 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3272 ScopedCheck sc(flags, function_name);
3273 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3274 if (sc.Check(soa, true, "Esp", args)) {
3275 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003276 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003277 if (utf) {
3278 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003279 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3280 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003281 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003282 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3283 baseEnv(env)->GetStringChars(env, string, is_copy));
3284 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003285 }
3286 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003287 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003288 if (utf) {
3289 size_t length_in_bytes = strlen(result.u) + 1;
3290 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003291 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003292 } else {
3293 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3294 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003295 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003296 }
3297 if (is_copy != nullptr) {
3298 *is_copy = JNI_TRUE;
3299 }
3300 }
3301 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3302 return utf ? result.u : result.p;
3303 }
3304 }
3305 return nullptr;
3306 }
3307
3308 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3309 const void* chars, bool utf, bool critical) {
3310 ScopedObjectAccess soa(env);
3311 int flags = kFlag_ExcepOkay | kFlag_Release;
3312 if (critical) {
3313 flags |= kFlag_CritRelease;
3314 }
3315 ScopedCheck sc(flags, function_name);
3316 sc.CheckNonNull(chars);
3317 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3318 if (force_copy_ok && soa.ForceCopy()) {
3319 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3320 }
3321 if (force_copy_ok) {
3322 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3323 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3324 if (utf) {
3325 CHECK(!critical);
3326 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3327 } else {
3328 if (critical) {
3329 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3330 } else {
3331 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3332 }
3333 }
3334 JniValueType result;
3335 sc.Check(soa, false, "V", &result);
3336 }
3337 }
3338 }
3339
3340 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3341 Primitive::Type type) {
3342 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003343 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003344 JniValueType args[2] = {{.E = env}, {.z = length}};
3345 if (sc.Check(soa, true, "Ez", args)) {
3346 JniValueType result;
3347 switch (type) {
3348 case Primitive::kPrimBoolean:
3349 result.a = baseEnv(env)->NewBooleanArray(env, length);
3350 break;
3351 case Primitive::kPrimByte:
3352 result.a = baseEnv(env)->NewByteArray(env, length);
3353 break;
3354 case Primitive::kPrimChar:
3355 result.a = baseEnv(env)->NewCharArray(env, length);
3356 break;
3357 case Primitive::kPrimShort:
3358 result.a = baseEnv(env)->NewShortArray(env, length);
3359 break;
3360 case Primitive::kPrimInt:
3361 result.a = baseEnv(env)->NewIntArray(env, length);
3362 break;
3363 case Primitive::kPrimLong:
3364 result.a = baseEnv(env)->NewLongArray(env, length);
3365 break;
3366 case Primitive::kPrimFloat:
3367 result.a = baseEnv(env)->NewFloatArray(env, length);
3368 break;
3369 case Primitive::kPrimDouble:
3370 result.a = baseEnv(env)->NewDoubleArray(env, length);
3371 break;
3372 default:
3373 LOG(FATAL) << "Unexpected primitive type: " << type;
3374 }
3375 if (sc.Check(soa, false, "a", &result)) {
3376 return result.a;
3377 }
3378 }
3379 return nullptr;
3380 }
3381
3382 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3383 JNIEnv* env, jarray array, jboolean* is_copy) {
3384 ScopedObjectAccess soa(env);
3385 ScopedCheck sc(kFlag_Default, function_name);
3386 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3387 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3388 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003389 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003390 switch (type) {
3391 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003392 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3393 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003394 break;
3395 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003396 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003397 break;
3398 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003399 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003400 break;
3401 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003402 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003403 break;
3404 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003405 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003406 break;
3407 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003408 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003409 break;
3410 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003411 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003412 break;
3413 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003414 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003415 break;
3416 default:
3417 LOG(FATAL) << "Unexpected primitive type: " << type;
3418 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003419 if (ptr != nullptr && soa.ForceCopy()) {
3420 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003421 if (is_copy != nullptr) {
3422 *is_copy = JNI_TRUE;
3423 }
3424 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003425 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003426 if (sc.Check(soa, false, "p", &result)) {
3427 return const_cast<void*>(result.p);
3428 }
3429 }
3430 return nullptr;
3431 }
3432
3433 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3434 JNIEnv* env, jarray array, void* elems, jint mode) {
3435 ScopedObjectAccess soa(env);
3436 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3437 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3438 if (soa.ForceCopy()) {
3439 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3440 }
3441 if (!soa.ForceCopy() || elems != nullptr) {
3442 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3443 if (sc.Check(soa, true, "Eapr", args)) {
3444 switch (type) {
3445 case Primitive::kPrimBoolean:
3446 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3447 reinterpret_cast<jboolean*>(elems), mode);
3448 break;
3449 case Primitive::kPrimByte:
3450 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3451 reinterpret_cast<jbyte*>(elems), mode);
3452 break;
3453 case Primitive::kPrimChar:
3454 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3455 reinterpret_cast<jchar*>(elems), mode);
3456 break;
3457 case Primitive::kPrimShort:
3458 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3459 reinterpret_cast<jshort*>(elems), mode);
3460 break;
3461 case Primitive::kPrimInt:
3462 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3463 reinterpret_cast<jint*>(elems), mode);
3464 break;
3465 case Primitive::kPrimLong:
3466 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3467 reinterpret_cast<jlong*>(elems), mode);
3468 break;
3469 case Primitive::kPrimFloat:
3470 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3471 reinterpret_cast<jfloat*>(elems), mode);
3472 break;
3473 case Primitive::kPrimDouble:
3474 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3475 reinterpret_cast<jdouble*>(elems), mode);
3476 break;
3477 default:
3478 LOG(FATAL) << "Unexpected primitive type: " << type;
3479 }
3480 JniValueType result;
3481 result.V = nullptr;
3482 sc.Check(soa, false, "V", &result);
3483 }
3484 }
3485 }
3486 }
3487
3488 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3489 jarray array, jsize start, jsize len, void* buf) {
3490 ScopedObjectAccess soa(env);
3491 ScopedCheck sc(kFlag_Default, function_name);
3492 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3493 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3494 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3495 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3496 switch (type) {
3497 case Primitive::kPrimBoolean:
3498 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3499 reinterpret_cast<jboolean*>(buf));
3500 break;
3501 case Primitive::kPrimByte:
3502 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3503 reinterpret_cast<jbyte*>(buf));
3504 break;
3505 case Primitive::kPrimChar:
3506 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3507 reinterpret_cast<jchar*>(buf));
3508 break;
3509 case Primitive::kPrimShort:
3510 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3511 reinterpret_cast<jshort*>(buf));
3512 break;
3513 case Primitive::kPrimInt:
3514 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3515 reinterpret_cast<jint*>(buf));
3516 break;
3517 case Primitive::kPrimLong:
3518 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3519 reinterpret_cast<jlong*>(buf));
3520 break;
3521 case Primitive::kPrimFloat:
3522 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3523 reinterpret_cast<jfloat*>(buf));
3524 break;
3525 case Primitive::kPrimDouble:
3526 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3527 reinterpret_cast<jdouble*>(buf));
3528 break;
3529 default:
3530 LOG(FATAL) << "Unexpected primitive type: " << type;
3531 }
3532 JniValueType result;
3533 result.V = nullptr;
3534 sc.Check(soa, false, "V", &result);
3535 }
3536 }
3537
3538 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3539 jarray array, jsize start, jsize len, const void* buf) {
3540 ScopedObjectAccess soa(env);
3541 ScopedCheck sc(kFlag_Default, function_name);
3542 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3543 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3544 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3545 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3546 switch (type) {
3547 case Primitive::kPrimBoolean:
3548 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3549 reinterpret_cast<const jboolean*>(buf));
3550 break;
3551 case Primitive::kPrimByte:
3552 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3553 reinterpret_cast<const jbyte*>(buf));
3554 break;
3555 case Primitive::kPrimChar:
3556 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3557 reinterpret_cast<const jchar*>(buf));
3558 break;
3559 case Primitive::kPrimShort:
3560 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3561 reinterpret_cast<const jshort*>(buf));
3562 break;
3563 case Primitive::kPrimInt:
3564 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3565 reinterpret_cast<const jint*>(buf));
3566 break;
3567 case Primitive::kPrimLong:
3568 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3569 reinterpret_cast<const jlong*>(buf));
3570 break;
3571 case Primitive::kPrimFloat:
3572 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3573 reinterpret_cast<const jfloat*>(buf));
3574 break;
3575 case Primitive::kPrimDouble:
3576 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3577 reinterpret_cast<const jdouble*>(buf));
3578 break;
3579 default:
3580 LOG(FATAL) << "Unexpected primitive type: " << type;
3581 }
3582 JniValueType result;
3583 result.V = nullptr;
3584 sc.Check(soa, false, "V", &result);
3585 }
3586 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003587};
3588
3589const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003590 nullptr, // reserved0.
3591 nullptr, // reserved1.
3592 nullptr, // reserved2.
3593 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003594 CheckJNI::GetVersion,
3595 CheckJNI::DefineClass,
3596 CheckJNI::FindClass,
3597 CheckJNI::FromReflectedMethod,
3598 CheckJNI::FromReflectedField,
3599 CheckJNI::ToReflectedMethod,
3600 CheckJNI::GetSuperclass,
3601 CheckJNI::IsAssignableFrom,
3602 CheckJNI::ToReflectedField,
3603 CheckJNI::Throw,
3604 CheckJNI::ThrowNew,
3605 CheckJNI::ExceptionOccurred,
3606 CheckJNI::ExceptionDescribe,
3607 CheckJNI::ExceptionClear,
3608 CheckJNI::FatalError,
3609 CheckJNI::PushLocalFrame,
3610 CheckJNI::PopLocalFrame,
3611 CheckJNI::NewGlobalRef,
3612 CheckJNI::DeleteGlobalRef,
3613 CheckJNI::DeleteLocalRef,
3614 CheckJNI::IsSameObject,
3615 CheckJNI::NewLocalRef,
3616 CheckJNI::EnsureLocalCapacity,
3617 CheckJNI::AllocObject,
3618 CheckJNI::NewObject,
3619 CheckJNI::NewObjectV,
3620 CheckJNI::NewObjectA,
3621 CheckJNI::GetObjectClass,
3622 CheckJNI::IsInstanceOf,
3623 CheckJNI::GetMethodID,
3624 CheckJNI::CallObjectMethod,
3625 CheckJNI::CallObjectMethodV,
3626 CheckJNI::CallObjectMethodA,
3627 CheckJNI::CallBooleanMethod,
3628 CheckJNI::CallBooleanMethodV,
3629 CheckJNI::CallBooleanMethodA,
3630 CheckJNI::CallByteMethod,
3631 CheckJNI::CallByteMethodV,
3632 CheckJNI::CallByteMethodA,
3633 CheckJNI::CallCharMethod,
3634 CheckJNI::CallCharMethodV,
3635 CheckJNI::CallCharMethodA,
3636 CheckJNI::CallShortMethod,
3637 CheckJNI::CallShortMethodV,
3638 CheckJNI::CallShortMethodA,
3639 CheckJNI::CallIntMethod,
3640 CheckJNI::CallIntMethodV,
3641 CheckJNI::CallIntMethodA,
3642 CheckJNI::CallLongMethod,
3643 CheckJNI::CallLongMethodV,
3644 CheckJNI::CallLongMethodA,
3645 CheckJNI::CallFloatMethod,
3646 CheckJNI::CallFloatMethodV,
3647 CheckJNI::CallFloatMethodA,
3648 CheckJNI::CallDoubleMethod,
3649 CheckJNI::CallDoubleMethodV,
3650 CheckJNI::CallDoubleMethodA,
3651 CheckJNI::CallVoidMethod,
3652 CheckJNI::CallVoidMethodV,
3653 CheckJNI::CallVoidMethodA,
3654 CheckJNI::CallNonvirtualObjectMethod,
3655 CheckJNI::CallNonvirtualObjectMethodV,
3656 CheckJNI::CallNonvirtualObjectMethodA,
3657 CheckJNI::CallNonvirtualBooleanMethod,
3658 CheckJNI::CallNonvirtualBooleanMethodV,
3659 CheckJNI::CallNonvirtualBooleanMethodA,
3660 CheckJNI::CallNonvirtualByteMethod,
3661 CheckJNI::CallNonvirtualByteMethodV,
3662 CheckJNI::CallNonvirtualByteMethodA,
3663 CheckJNI::CallNonvirtualCharMethod,
3664 CheckJNI::CallNonvirtualCharMethodV,
3665 CheckJNI::CallNonvirtualCharMethodA,
3666 CheckJNI::CallNonvirtualShortMethod,
3667 CheckJNI::CallNonvirtualShortMethodV,
3668 CheckJNI::CallNonvirtualShortMethodA,
3669 CheckJNI::CallNonvirtualIntMethod,
3670 CheckJNI::CallNonvirtualIntMethodV,
3671 CheckJNI::CallNonvirtualIntMethodA,
3672 CheckJNI::CallNonvirtualLongMethod,
3673 CheckJNI::CallNonvirtualLongMethodV,
3674 CheckJNI::CallNonvirtualLongMethodA,
3675 CheckJNI::CallNonvirtualFloatMethod,
3676 CheckJNI::CallNonvirtualFloatMethodV,
3677 CheckJNI::CallNonvirtualFloatMethodA,
3678 CheckJNI::CallNonvirtualDoubleMethod,
3679 CheckJNI::CallNonvirtualDoubleMethodV,
3680 CheckJNI::CallNonvirtualDoubleMethodA,
3681 CheckJNI::CallNonvirtualVoidMethod,
3682 CheckJNI::CallNonvirtualVoidMethodV,
3683 CheckJNI::CallNonvirtualVoidMethodA,
3684 CheckJNI::GetFieldID,
3685 CheckJNI::GetObjectField,
3686 CheckJNI::GetBooleanField,
3687 CheckJNI::GetByteField,
3688 CheckJNI::GetCharField,
3689 CheckJNI::GetShortField,
3690 CheckJNI::GetIntField,
3691 CheckJNI::GetLongField,
3692 CheckJNI::GetFloatField,
3693 CheckJNI::GetDoubleField,
3694 CheckJNI::SetObjectField,
3695 CheckJNI::SetBooleanField,
3696 CheckJNI::SetByteField,
3697 CheckJNI::SetCharField,
3698 CheckJNI::SetShortField,
3699 CheckJNI::SetIntField,
3700 CheckJNI::SetLongField,
3701 CheckJNI::SetFloatField,
3702 CheckJNI::SetDoubleField,
3703 CheckJNI::GetStaticMethodID,
3704 CheckJNI::CallStaticObjectMethod,
3705 CheckJNI::CallStaticObjectMethodV,
3706 CheckJNI::CallStaticObjectMethodA,
3707 CheckJNI::CallStaticBooleanMethod,
3708 CheckJNI::CallStaticBooleanMethodV,
3709 CheckJNI::CallStaticBooleanMethodA,
3710 CheckJNI::CallStaticByteMethod,
3711 CheckJNI::CallStaticByteMethodV,
3712 CheckJNI::CallStaticByteMethodA,
3713 CheckJNI::CallStaticCharMethod,
3714 CheckJNI::CallStaticCharMethodV,
3715 CheckJNI::CallStaticCharMethodA,
3716 CheckJNI::CallStaticShortMethod,
3717 CheckJNI::CallStaticShortMethodV,
3718 CheckJNI::CallStaticShortMethodA,
3719 CheckJNI::CallStaticIntMethod,
3720 CheckJNI::CallStaticIntMethodV,
3721 CheckJNI::CallStaticIntMethodA,
3722 CheckJNI::CallStaticLongMethod,
3723 CheckJNI::CallStaticLongMethodV,
3724 CheckJNI::CallStaticLongMethodA,
3725 CheckJNI::CallStaticFloatMethod,
3726 CheckJNI::CallStaticFloatMethodV,
3727 CheckJNI::CallStaticFloatMethodA,
3728 CheckJNI::CallStaticDoubleMethod,
3729 CheckJNI::CallStaticDoubleMethodV,
3730 CheckJNI::CallStaticDoubleMethodA,
3731 CheckJNI::CallStaticVoidMethod,
3732 CheckJNI::CallStaticVoidMethodV,
3733 CheckJNI::CallStaticVoidMethodA,
3734 CheckJNI::GetStaticFieldID,
3735 CheckJNI::GetStaticObjectField,
3736 CheckJNI::GetStaticBooleanField,
3737 CheckJNI::GetStaticByteField,
3738 CheckJNI::GetStaticCharField,
3739 CheckJNI::GetStaticShortField,
3740 CheckJNI::GetStaticIntField,
3741 CheckJNI::GetStaticLongField,
3742 CheckJNI::GetStaticFloatField,
3743 CheckJNI::GetStaticDoubleField,
3744 CheckJNI::SetStaticObjectField,
3745 CheckJNI::SetStaticBooleanField,
3746 CheckJNI::SetStaticByteField,
3747 CheckJNI::SetStaticCharField,
3748 CheckJNI::SetStaticShortField,
3749 CheckJNI::SetStaticIntField,
3750 CheckJNI::SetStaticLongField,
3751 CheckJNI::SetStaticFloatField,
3752 CheckJNI::SetStaticDoubleField,
3753 CheckJNI::NewString,
3754 CheckJNI::GetStringLength,
3755 CheckJNI::GetStringChars,
3756 CheckJNI::ReleaseStringChars,
3757 CheckJNI::NewStringUTF,
3758 CheckJNI::GetStringUTFLength,
3759 CheckJNI::GetStringUTFChars,
3760 CheckJNI::ReleaseStringUTFChars,
3761 CheckJNI::GetArrayLength,
3762 CheckJNI::NewObjectArray,
3763 CheckJNI::GetObjectArrayElement,
3764 CheckJNI::SetObjectArrayElement,
3765 CheckJNI::NewBooleanArray,
3766 CheckJNI::NewByteArray,
3767 CheckJNI::NewCharArray,
3768 CheckJNI::NewShortArray,
3769 CheckJNI::NewIntArray,
3770 CheckJNI::NewLongArray,
3771 CheckJNI::NewFloatArray,
3772 CheckJNI::NewDoubleArray,
3773 CheckJNI::GetBooleanArrayElements,
3774 CheckJNI::GetByteArrayElements,
3775 CheckJNI::GetCharArrayElements,
3776 CheckJNI::GetShortArrayElements,
3777 CheckJNI::GetIntArrayElements,
3778 CheckJNI::GetLongArrayElements,
3779 CheckJNI::GetFloatArrayElements,
3780 CheckJNI::GetDoubleArrayElements,
3781 CheckJNI::ReleaseBooleanArrayElements,
3782 CheckJNI::ReleaseByteArrayElements,
3783 CheckJNI::ReleaseCharArrayElements,
3784 CheckJNI::ReleaseShortArrayElements,
3785 CheckJNI::ReleaseIntArrayElements,
3786 CheckJNI::ReleaseLongArrayElements,
3787 CheckJNI::ReleaseFloatArrayElements,
3788 CheckJNI::ReleaseDoubleArrayElements,
3789 CheckJNI::GetBooleanArrayRegion,
3790 CheckJNI::GetByteArrayRegion,
3791 CheckJNI::GetCharArrayRegion,
3792 CheckJNI::GetShortArrayRegion,
3793 CheckJNI::GetIntArrayRegion,
3794 CheckJNI::GetLongArrayRegion,
3795 CheckJNI::GetFloatArrayRegion,
3796 CheckJNI::GetDoubleArrayRegion,
3797 CheckJNI::SetBooleanArrayRegion,
3798 CheckJNI::SetByteArrayRegion,
3799 CheckJNI::SetCharArrayRegion,
3800 CheckJNI::SetShortArrayRegion,
3801 CheckJNI::SetIntArrayRegion,
3802 CheckJNI::SetLongArrayRegion,
3803 CheckJNI::SetFloatArrayRegion,
3804 CheckJNI::SetDoubleArrayRegion,
3805 CheckJNI::RegisterNatives,
3806 CheckJNI::UnregisterNatives,
3807 CheckJNI::MonitorEnter,
3808 CheckJNI::MonitorExit,
3809 CheckJNI::GetJavaVM,
3810 CheckJNI::GetStringRegion,
3811 CheckJNI::GetStringUTFRegion,
3812 CheckJNI::GetPrimitiveArrayCritical,
3813 CheckJNI::ReleasePrimitiveArrayCritical,
3814 CheckJNI::GetStringCritical,
3815 CheckJNI::ReleaseStringCritical,
3816 CheckJNI::NewWeakGlobalRef,
3817 CheckJNI::DeleteWeakGlobalRef,
3818 CheckJNI::ExceptionCheck,
3819 CheckJNI::NewDirectByteBuffer,
3820 CheckJNI::GetDirectBufferAddress,
3821 CheckJNI::GetDirectBufferCapacity,
3822 CheckJNI::GetObjectRefType,
3823};
3824
3825const JNINativeInterface* GetCheckJniNativeInterface() {
3826 return &gCheckNativeInterface;
3827}
3828
3829class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003830 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003831 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003832 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3833 JniValueType args[1] = {{.v = vm}};
3834 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3835 JniValueType result;
3836 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003837 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3838 // which will delete the JavaVMExt.
3839 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003840 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003841 }
3842
3843 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003844 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3845 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3846 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3847 JniValueType result;
3848 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3849 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3850 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003851 }
3852
3853 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003854 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3855 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3856 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3857 JniValueType result;
3858 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3859 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3860 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003861 }
3862
3863 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003864 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3865 JniValueType args[1] = {{.v = vm}};
3866 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3867 JniValueType result;
3868 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3869 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3870 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003871 }
3872
Ian Rogers68d8b422014-07-17 11:09:10 -07003873 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3874 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3875 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3876 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3877 JniValueType result;
3878 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3879 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3880 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003881 }
3882
3883 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003884 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3885 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003886 }
3887};
3888
3889const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003890 nullptr, // reserved0
3891 nullptr, // reserved1
3892 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003893 CheckJII::DestroyJavaVM,
3894 CheckJII::AttachCurrentThread,
3895 CheckJII::DetachCurrentThread,
3896 CheckJII::GetEnv,
3897 CheckJII::AttachCurrentThreadAsDaemon
3898};
3899
3900const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3901 return &gCheckInvokeInterface;
3902}
3903
3904} // namespace art