blob: 5549122c341480d1966df45defb54107b268cd0a [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 Rogers55256cb2017-12-21 17:07:11 -080031#include "base/time_utils.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080032#include "class_linker-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070033#include "class_linker.h"
David Sehr9e734c72018-01-04 17:56:19 -080034#include "dex/dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070035#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070036#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080037#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080038#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039#include "mirror/object-inl.h"
40#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070041#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080042#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070043#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070044#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070045#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070046#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070047
48namespace art {
49
Andreas Gampe46ee31b2016-12-14 10:11:49 -080050using android::base::StringAppendF;
51using android::base::StringPrintf;
52
Elliott Hughesa2501992011-08-26 19:39:54 -070053/*
54 * ===========================================================================
55 * JNI function helpers
56 * ===========================================================================
57 */
58
Ian Rogers55256cb2017-12-21 17:07:11 -080059// Warn if a JNI critical is held for longer than 16ms.
60static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
61static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
62
Elliott Hughes3f6635a2012-06-19 13:37:49 -070063// Flags passed into ScopedCheck.
Ian Rogers55256cb2017-12-21 17:07:11 -080064static constexpr uint16_t kFlag_Default = 0x0000;
Elliott Hughesa2501992011-08-26 19:39:54 -070065
Ian Rogers55256cb2017-12-21 17:07:11 -080066// Calling while in critical is not allowed.
67static constexpr uint16_t kFlag_CritBad = 0x0000;
68// Calling while in critical is allowed.
69static constexpr uint16_t kFlag_CritOkay = 0x0001;
70// This is a critical "get".
71static constexpr uint16_t kFlag_CritGet = 0x0002;
72// This is a critical "release".
73static constexpr uint16_t kFlag_CritRelease = 0x0003;
74// Bit mask to get "crit" value.
75static constexpr uint16_t kFlag_CritMask = 0x0003;
Elliott Hughesa2501992011-08-26 19:39:54 -070076
Ian Rogers55256cb2017-12-21 17:07:11 -080077// Raised exceptions are allowed.
78static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
Elliott Hughesa2501992011-08-26 19:39:54 -070079
Ian Rogers55256cb2017-12-21 17:07:11 -080080// Are we in a non-critical release function?
81static constexpr uint16_t kFlag_Release = 0x0010;
82// Are our UTF parameters nullable?
83static constexpr uint16_t kFlag_NullableUtf = 0x0020;
Elliott Hughesa2501992011-08-26 19:39:54 -070084
Ian Rogers55256cb2017-12-21 17:07:11 -080085// Part of the invocation interface (JavaVM*).
86static constexpr uint16_t kFlag_Invocation = 0x0100;
Elliott Hughesa2501992011-08-26 19:39:54 -070087
Ian Rogers55256cb2017-12-21 17:07:11 -080088// Add this to a JNI function's flags if you want to trace every call.
89static constexpr uint16_t kFlag_ForceTrace = 0x8000;
Alex Light48ffe062015-08-19 15:23:23 -070090
91class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070092/*
93 * Java primitive types:
94 * B - jbyte
95 * C - jchar
96 * D - jdouble
97 * F - jfloat
98 * I - jint
99 * J - jlong
100 * S - jshort
101 * Z - jboolean (shown as true and false)
102 * V - void
103 *
104 * Java reference types:
105 * L - jobject
106 * a - jarray
107 * c - jclass
108 * s - jstring
109 * t - jthrowable
110 *
111 * JNI types:
112 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
113 * f - jfieldID
114 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
115 * m - jmethodID
116 * p - void*
117 * r - jint (for release mode arguments)
118 * u - const char* (Modified UTF-8)
119 * z - jsize (for lengths; use i if negative values are okay)
120 * v - JavaVM*
121 * w - jobjectRefType
122 * E - JNIEnv*
123 * . - no argument; just print "..." (used for varargs JNI calls)
124 *
125 */
126union JniValueType {
127 jarray a;
128 jboolean b;
129 jclass c;
130 jfieldID f;
131 jint i;
132 jmethodID m;
133 const void* p; // Pointer.
134 jint r; // Release mode.
135 jstring s;
136 jthrowable t;
137 const char* u; // Modified UTF-8.
138 JavaVM* v;
139 jobjectRefType w;
140 jsize z;
141 jbyte B;
142 jchar C;
143 jdouble D;
144 JNIEnv* E;
145 jfloat F;
146 jint I;
147 jlong J;
148 jobject L;
149 jshort S;
150 const void* V; // void
151 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700152 const VarArgs* va;
153};
154
155/*
156 * A structure containing all the information needed to validate varargs arguments.
157 *
158 * Note that actually getting the arguments from this structure mutates it so should only be done on
159 * owned copies.
160 */
161class VarArgs {
162 public:
163 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
164 va_copy(vargs_, var);
165 }
166
167 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
168
169 ~VarArgs() {
170 if (type_ == kTypeVaList) {
171 va_end(vargs_);
172 }
173 }
174
175 VarArgs(VarArgs&& other) {
176 m_ = other.m_;
177 cnt_ = other.cnt_;
178 type_ = other.type_;
179 if (other.type_ == kTypeVaList) {
180 va_copy(vargs_, other.vargs_);
181 } else {
182 ptr_ = other.ptr_;
183 }
184 }
185
186 // This method is const because we need to ensure that one only uses the GetValue method on an
187 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
188 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
189 // we want to use one we need to Clone() it.
190 VarArgs Clone() const {
191 if (type_ == kTypeVaList) {
192 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
193 // messed up if the source argument is not the exact type 'va_list'.
194 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
195 } else {
196 return VarArgs(m_, cnt_, ptr_);
197 }
198 }
199
200 jmethodID GetMethodID() const {
201 return m_;
202 }
203
204 JniValueType GetValue(char fmt) {
205 JniValueType o;
206 if (type_ == kTypeVaList) {
207 switch (fmt) {
208 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
209 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
210 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
211 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
212 case 'I': o.I = va_arg(vargs_, jint); break;
213 case 'J': o.J = va_arg(vargs_, jlong); break;
214 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
215 case 'D': o.D = va_arg(vargs_, jdouble); break;
216 case 'L': o.L = va_arg(vargs_, jobject); break;
217 default:
218 LOG(FATAL) << "Illegal type format char " << fmt;
219 UNREACHABLE();
220 }
221 } else {
222 CHECK(type_ == kTypePtr);
223 jvalue v = ptr_[cnt_];
224 cnt_++;
225 switch (fmt) {
226 case 'Z': o.Z = v.z; break;
227 case 'B': o.B = v.b; break;
228 case 'C': o.C = v.c; break;
229 case 'S': o.S = v.s; break;
230 case 'I': o.I = v.i; break;
231 case 'J': o.J = v.j; break;
232 case 'F': o.F = v.f; break;
233 case 'D': o.D = v.d; break;
234 case 'L': o.L = v.l; break;
235 default:
236 LOG(FATAL) << "Illegal type format char " << fmt;
237 UNREACHABLE();
238 }
239 }
240 return o;
241 }
242
243 private:
244 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
245 va_copy(vargs_, var);
246 }
247
248 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
249
250 enum VarArgsType {
251 kTypeVaList,
252 kTypePtr,
253 };
254
255 jmethodID m_;
256 VarArgsType type_;
257 uint32_t cnt_;
258 union {
259 va_list vargs_;
260 const jvalue* ptr_;
261 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700262};
263
Elliott Hughesa2501992011-08-26 19:39:54 -0700264class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800265 public:
Ian Rogers55256cb2017-12-21 17:07:11 -0800266 ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
267 : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700268 }
269
Ian Rogers68d8b422014-07-17 11:09:10 -0700270 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700271
Elliott Hughes81ff3182012-03-23 20:35:56 -0700272 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
273 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
274 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
275 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700276 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700277 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700278 AbortF("illegal class name '%s'\n"
279 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
280 class_name);
281 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700282 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700283 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700284 }
285
286 /*
287 * Verify that this instance field ID is valid for this object.
288 *
289 * Assumes "jobj" has already been validated.
290 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700291 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700292 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700293 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700294 if (o == nullptr) {
295 AbortF("field operation on NULL object: %p", java_object);
296 return false;
297 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700298 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700299 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700300 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700301 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700302 java_object);
303 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700304 }
305
Andreas Gampe08883de2016-11-08 13:20:52 -0800306 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800307 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700308 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700309 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800310 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700311 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700312 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700313 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700314 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700315 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700316 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700317 }
318
319 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700320 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700321 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700322 bool CheckNonNull(const void* ptr) {
323 if (UNLIKELY(ptr == nullptr)) {
324 AbortF("non-nullable argument was NULL");
325 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700326 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700327 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700328 }
329
330 /*
331 * Verify that the method's return type matches the type of call.
332 * 'expectedType' will be "L" for all objects, including arrays.
333 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700334 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
335 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700336 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800337 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800338 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700339 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700340 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700341 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700342 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700344 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700345 bool is_static = (invoke == kStatic);
346 if (is_static != m->IsStatic()) {
347 if (is_static) {
348 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700349 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700350 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700351 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700352 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700353 }
354 return false;
355 }
356 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700357 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700358 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700359 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700360 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700361 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700362 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700363 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700364 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700365 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700366 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700367 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700368 return false;
369 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700370 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
371 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700372 return false;
373 }
374 }
375 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700376 }
377
378 /*
379 * Verify that this static field ID is valid for this class.
380 *
381 * Assumes "java_class" has already been validated.
382 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700383 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700384 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700385 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800386 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800387 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700388 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700389 }
Alex Lighte4033fa2017-12-13 10:32:59 -0800390 if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700391 AbortF("static jfieldID %p not valid for class %s", fid,
392 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700393 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700394 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700396 }
397
398 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700399 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700400 *
401 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700402 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700403 * allow bad code in the system though.
404 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700405 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700406 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700407 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700408 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800409 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800410 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700411 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700412 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700413 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700414 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700415 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
416 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700417 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700418 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700419 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700420 }
421
422 /*
423 * Verify that "mid" is appropriate for "jobj".
424 *
425 * Make sure the object is an instance of the method's declaring class.
426 * (Note the mid might point to a declaration in an interface; this
427 * will be handled automatically by the instanceof check.)
428 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700429 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700430 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800431 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800432 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700433 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700434 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700435 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700436 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700437 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700438 return false;
439 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700440 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
441 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700442 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700443 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700444 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700445 }
446
447 /**
448 * The format string is a sequence of the following characters,
449 * and must be followed by arguments of the corresponding types
450 * in the same order.
451 *
452 * Java primitive types:
453 * B - jbyte
454 * C - jchar
455 * D - jdouble
456 * F - jfloat
457 * I - jint
458 * J - jlong
459 * S - jshort
460 * Z - jboolean (shown as true and false)
461 * V - void
462 *
463 * Java reference types:
464 * L - jobject
465 * a - jarray
466 * c - jclass
467 * s - jstring
468 *
469 * JNI types:
470 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
471 * f - jfieldID
472 * m - jmethodID
473 * p - void*
474 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700475 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700476 * z - jsize (for lengths; use i if negative values are okay)
477 * v - JavaVM*
478 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700479 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700480 *
481 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
482 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700483 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700484 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700485 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700486 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700487 // We need to guard some of the invocation interface's calls: a bad caller might
488 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700489 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800490 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
491 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700492 }
493 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700494
Ian Rogersef7d42f2014-01-06 12:55:46 -0800495 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700496 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700497 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700498 for (size_t i = 0; fmt[i] != '\0'; ++i) {
499 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
500 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700501 StringAppendF(&msg, ", ");
502 }
503 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700504
Elliott Hughes485cac42011-12-09 17:49:35 -0800505 if ((flags_ & kFlag_ForceTrace) != 0) {
506 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
507 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700508 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700509 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700510 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
511 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700512 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700513 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
514 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700515 }
516 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700517 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700518 }
519 }
520
521 // We always do the thorough checks on entry, and never on exit...
522 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700523 for (size_t i = 0; fmt[i] != '\0'; ++i) {
524 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
525 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700526 }
527 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700528 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700529 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700530 }
531
Ian Rogers68d8b422014-07-17 11:09:10 -0700532 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
533 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800534 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700535 // We need to guard some of the invocation interface's calls: a bad caller might
536 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
537 Thread* self = Thread::Current();
538 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
539 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700540 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700541 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
542 }
543 }
544 if (should_trace) {
545 std::string msg;
546 for (size_t i = 0; fmt[i] != '\0'; ++i) {
547 TraceNonHeapValue(fmt[i], args[i], &msg);
548 if (fmt[i + 1] != '\0') {
549 StringAppendF(&msg, ", ");
550 }
551 }
552
553 if ((flags_ & kFlag_ForceTrace) != 0) {
554 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
555 } else if (entry) {
556 if (has_method_) {
557 Thread* self = Thread::Current();
558 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700559 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700560 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700561 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
562 indent_ = methodName.size() + 1;
563 } else {
564 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
565 indent_ = 0;
566 }
567 } else {
568 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
569 }
570 }
571
572 // We always do the thorough checks on entry, and never on exit...
573 if (entry) {
574 for (size_t i = 0; fmt[i] != '\0'; ++i) {
575 if (!CheckNonHeapValue(fmt[i], args[i])) {
576 return false;
577 }
578 }
579 }
580 return true;
581 }
582
583 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700584 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700585 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700586 if (method == nullptr) {
587 AbortF("expected non-null method");
588 return false;
589 }
590 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700591 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
592 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700593 AbortF("expected java.lang.reflect.Method or "
594 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700595 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700596 return false;
597 }
598 return true;
599 }
600
Andreas Gampe13b27842016-11-07 16:48:23 -0800601 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
602 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700603 if (method == nullptr) {
604 AbortF("expected non-null constructor");
605 return false;
606 }
607 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700608 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700609 return false;
610 }
611 return true;
612 }
613
614 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700615 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700616 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700617 if (field == nullptr) {
618 AbortF("expected non-null java.lang.reflect.Field");
619 return false;
620 }
621 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700622 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700623 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700624 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700625 return false;
626 }
627 return true;
628 }
629
630 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700631 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700632 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700633 if (!obj->GetClass()->IsThrowableClass()) {
634 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700635 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700636 return false;
637 }
638 return true;
639 }
640
641 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700642 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700643 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700644 if (!c->IsThrowableClass()) {
645 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700646 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700647 return false;
648 }
649 return true;
650 }
651
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700652 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700653 IndirectRefKind found_kind;
654 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700655 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700656 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
657 found_kind = kLocal;
658 }
659 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700660 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700661 }
662 if (obj != nullptr && found_kind != expected_kind) {
663 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700664 GetIndirectRefKindString(expected_kind),
665 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700666 obj);
667 return false;
668 }
669 return true;
670 }
671
672 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700673 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700674 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700675 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700676 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700677 return false;
678 }
679 return true;
680 }
681
682 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700683 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700684 if (!CheckArray(soa, array)) {
685 return false;
686 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700687 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700688 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
689 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700690 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700691 return false;
692 }
693 return true;
694 }
695
696 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
697 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700698 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700699 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
700 return false;
701 }
702 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
703 return false;
704 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800705 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700706 DCHECK(field != nullptr); // Already checked by Check.
707 if (is_static != field->IsStatic()) {
708 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700709 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700710 return false;
711 }
712 if (type != field->GetTypeAsPrimitiveType()) {
713 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700714 field->PrettyField().c_str(),
715 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700716 PrettyDescriptor(type).c_str(), fid);
717 return false;
718 }
719 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700720 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700721 if (o == nullptr || !o->IsClass()) {
722 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700723 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700724 return false;
725 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700726 ObjPtr<mirror::Class> c = o->AsClass();
Alex Lighte4033fa2017-12-13 10:32:59 -0800727 if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700728 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700729 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700730 return false;
731 }
732 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700733 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700734 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
735 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700736 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700737 return false;
738 }
739 }
740 return true;
741 }
742
743 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800744 enum InstanceKind {
745 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700746 kDirectByteBuffer,
747 kObject,
748 kString,
749 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800750 };
751
752 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700753 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800754 * an instance of expectedClass.
755 *
756 * Because we're looking at an object on the GC heap, we have to switch
757 * to "running" mode before doing the checks.
758 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700759 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700760 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800761 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800762 switch (kind) {
763 case kClass:
764 what = "jclass";
765 break;
766 case kDirectByteBuffer:
767 what = "direct ByteBuffer";
768 break;
769 case kObject:
770 what = "jobject";
771 break;
772 case kString:
773 what = "jstring";
774 break;
775 case kThrowable:
776 what = "jthrowable";
777 break;
778 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700779 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800780 }
781
Ian Rogersef7d42f2014-01-06 12:55:46 -0800782 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700783 if (null_ok) {
784 return true;
785 } else {
786 AbortF("%s received NULL %s", function_name_, what);
787 return false;
788 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800789 }
790
Mathieu Chartier0795f232016-09-27 18:43:30 -0700791 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700792 if (obj == nullptr) {
793 // Either java_object is invalid or is a cleared weak.
794 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
795 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700796 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700797 okay = false;
798 } else {
799 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700800 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700801 }
802 if (!okay) {
803 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700804 what,
805 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
806 java_object,
807 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700808 return false;
809 }
810 }
811
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700812 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700813 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700814 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700815 what,
816 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
817 java_object,
818 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800819 return false;
820 }
821
822 bool okay = true;
823 switch (kind) {
824 case kClass:
825 okay = obj->IsClass();
826 break;
827 case kDirectByteBuffer:
828 UNIMPLEMENTED(FATAL);
829 break;
830 case kString:
831 okay = obj->GetClass()->IsStringClass();
832 break;
833 case kThrowable:
834 okay = obj->GetClass()->IsThrowableClass();
835 break;
836 case kObject:
837 break;
838 }
839 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700840 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800841 return false;
842 }
843
844 return true;
845 }
846
Ian Rogers68d8b422014-07-17 11:09:10 -0700847 /*
848 * Verify that the "mode" argument passed to a primitive array Release
849 * function is one of the valid values.
850 */
851 bool CheckReleaseMode(jint mode) {
852 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
853 AbortF("unknown value for release mode: %d", mode);
854 return false;
855 }
856 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700857 }
858
Ian Rogers68d8b422014-07-17 11:09:10 -0700859 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700860 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700861 switch (fmt) {
862 case 'a': // jarray
863 return CheckArray(soa, arg.a);
864 case 'c': // jclass
865 return CheckInstance(soa, kClass, arg.c, false);
866 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800867 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700868 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800869 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700870 case 'r': // release int
871 return CheckReleaseMode(arg.r);
872 case 's': // jstring
873 return CheckInstance(soa, kString, arg.s, false);
874 case 't': // jthrowable
875 return CheckInstance(soa, kThrowable, arg.t, false);
876 case 'E': // JNIEnv*
877 return CheckThread(arg.E);
878 case 'L': // jobject
879 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700880 case '.': // A VarArgs list
881 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700882 default:
883 return CheckNonHeapValue(fmt, arg);
884 }
885 }
886
Alex Light48ffe062015-08-19 15:23:23 -0700887 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700888 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700889 CHECK(args_p != nullptr);
890 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800891 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700892 if (m == nullptr) {
893 return false;
894 }
895 uint32_t len = 0;
896 const char* shorty = m->GetShorty(&len);
897 // Skip the return type
898 CHECK_GE(len, 1u);
899 len--;
900 shorty++;
901 for (uint32_t i = 0; i < len; i++) {
902 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
903 return false;
904 }
905 }
906 return true;
907 }
908
Ian Rogers68d8b422014-07-17 11:09:10 -0700909 bool CheckNonHeapValue(char fmt, JniValueType arg) {
910 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700911 case 'p': // TODO: pointer - null or readable?
912 case 'v': // JavaVM*
913 case 'B': // jbyte
914 case 'C': // jchar
915 case 'D': // jdouble
916 case 'F': // jfloat
917 case 'I': // jint
918 case 'J': // jlong
919 case 'S': // jshort
920 break; // Ignored.
921 case 'b': // jboolean, why two? Fall-through.
922 case 'Z':
923 return CheckBoolean(arg.Z);
924 case 'u': // utf8
925 if ((flags_ & kFlag_Release) != 0) {
926 return CheckNonNull(arg.u);
927 } else {
928 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
929 return CheckUtfString(arg.u, nullable);
930 }
931 case 'w': // jobjectRefType
932 switch (arg.w) {
933 case JNIInvalidRefType:
934 case JNILocalRefType:
935 case JNIGlobalRefType:
936 case JNIWeakGlobalRefType:
937 break;
938 default:
939 AbortF("Unknown reference type");
940 return false;
941 }
942 break;
943 case 'z': // jsize
944 return CheckLengthPositive(arg.z);
945 default:
946 AbortF("unknown format specifier: '%c'", fmt);
947 return false;
948 }
949 return true;
950 }
951
952 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
953 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700954 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700955 switch (fmt) {
956 case 'L': // jobject fall-through.
957 case 'a': // jarray fall-through.
958 case 's': // jstring fall-through.
959 case 't': // jthrowable fall-through.
960 if (arg.L == nullptr) {
961 *msg += "NULL";
962 } else {
963 StringAppendF(msg, "%p", arg.L);
964 }
965 break;
966 case 'c': { // jclass
967 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700968 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700969 if (c == nullptr) {
970 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700971 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700972 StringAppendF(msg, "INVALID POINTER:%p", jc);
973 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700974 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700975 } else {
David Sehr709b0702016-10-13 09:12:37 -0700976 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700977 if (!entry) {
978 StringAppendF(msg, " (%p)", jc);
979 }
980 }
981 break;
982 }
983 case 'f': { // jfieldID
984 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800985 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700986 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700987 if (!entry) {
988 StringAppendF(msg, " (%p)", fid);
989 }
990 break;
991 }
992 case 'm': { // jmethodID
993 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800994 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700995 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700996 if (!entry) {
997 StringAppendF(msg, " (%p)", mid);
998 }
999 break;
1000 }
Alex Light48ffe062015-08-19 15:23:23 -07001001 case '.': {
1002 const VarArgs* va = arg.va;
1003 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -08001004 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -07001005 uint32_t len;
1006 const char* shorty = m->GetShorty(&len);
1007 CHECK_GE(len, 1u);
1008 // Skip past return value.
1009 len--;
1010 shorty++;
1011 // Remove the previous ', ' from the message.
1012 msg->erase(msg->length() - 2);
1013 for (uint32_t i = 0; i < len; i++) {
1014 *msg += ", ";
1015 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1016 }
1017 break;
1018 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001019 default:
1020 TraceNonHeapValue(fmt, arg, msg);
1021 break;
1022 }
1023 }
1024
1025 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1026 switch (fmt) {
1027 case 'B': // jbyte
1028 if (arg.B >= 0 && arg.B < 10) {
1029 StringAppendF(msg, "%d", arg.B);
1030 } else {
1031 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1032 }
1033 break;
1034 case 'C': // jchar
1035 if (arg.C < 0x7f && arg.C >= ' ') {
1036 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1037 } else {
1038 StringAppendF(msg, "U+%x", arg.C);
1039 }
1040 break;
1041 case 'F': // jfloat
1042 StringAppendF(msg, "%g", arg.F);
1043 break;
1044 case 'D': // jdouble
1045 StringAppendF(msg, "%g", arg.D);
1046 break;
1047 case 'S': // jshort
1048 StringAppendF(msg, "%d", arg.S);
1049 break;
1050 case 'i': // jint - fall-through.
1051 case 'I': // jint
1052 StringAppendF(msg, "%d", arg.I);
1053 break;
1054 case 'J': // jlong
1055 StringAppendF(msg, "%" PRId64, arg.J);
1056 break;
1057 case 'Z': // jboolean
1058 case 'b': // jboolean (JNI-style)
1059 *msg += arg.b == JNI_TRUE ? "true" : "false";
1060 break;
1061 case 'V': // void
1062 DCHECK(arg.V == nullptr);
1063 *msg += "void";
1064 break;
1065 case 'v': // JavaVM*
1066 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1067 break;
1068 case 'E':
1069 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1070 break;
1071 case 'z': // non-negative jsize
1072 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1073 // We only treat this specially so we can do the non-negative check.
1074 // TODO: maybe this wasn't worth it?
1075 StringAppendF(msg, "%d", arg.z);
1076 break;
1077 case 'p': // void* ("pointer")
1078 if (arg.p == nullptr) {
1079 *msg += "NULL";
1080 } else {
1081 StringAppendF(msg, "(void*) %p", arg.p);
1082 }
1083 break;
1084 case 'r': { // jint (release mode)
1085 jint releaseMode = arg.r;
1086 if (releaseMode == 0) {
1087 *msg += "0";
1088 } else if (releaseMode == JNI_ABORT) {
1089 *msg += "JNI_ABORT";
1090 } else if (releaseMode == JNI_COMMIT) {
1091 *msg += "JNI_COMMIT";
1092 } else {
1093 StringAppendF(msg, "invalid release mode %d", releaseMode);
1094 }
1095 break;
1096 }
1097 case 'u': // const char* (Modified UTF-8)
1098 if (arg.u == nullptr) {
1099 *msg += "NULL";
1100 } else {
1101 StringAppendF(msg, "\"%s\"", arg.u);
1102 }
1103 break;
1104 case 'w': // jobjectRefType
1105 switch (arg.w) {
1106 case JNIInvalidRefType:
1107 *msg += "invalid reference type";
1108 break;
1109 case JNILocalRefType:
1110 *msg += "local ref type";
1111 break;
1112 case JNIGlobalRefType:
1113 *msg += "global ref type";
1114 break;
1115 case JNIWeakGlobalRefType:
1116 *msg += "weak global ref type";
1117 break;
1118 default:
1119 *msg += "unknown ref type";
1120 break;
1121 }
1122 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001123 default:
1124 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1125 }
1126 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001127 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001128 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001129 *
1130 * Since we're dealing with objects, switch to "running" mode.
1131 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001132 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001133 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001134 if (UNLIKELY(java_array == nullptr)) {
1135 AbortF("jarray was NULL");
1136 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001137 }
1138
Mathieu Chartier0795f232016-09-27 18:43:30 -07001139 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001140 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001141 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001142 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001143 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1144 java_array,
1145 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001146 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001147 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001148 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001149 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001150 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001151 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001152 }
1153
Ian Rogers68d8b422014-07-17 11:09:10 -07001154 bool CheckBoolean(jboolean z) {
1155 if (z != JNI_TRUE && z != JNI_FALSE) {
1156 AbortF("unexpected jboolean value: %d", z);
1157 return false;
1158 }
1159 return true;
1160 }
1161
1162 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001163 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001164 AbortF("negative jsize: %d", length);
1165 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001166 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001167 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001168 }
1169
Andreas Gampe08883de2016-11-08 13:20:52 -08001170 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001171 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001172 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001173 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001174 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001175 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001176 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001177 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001178 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001179 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001180 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001181 }
1182 return f;
1183 }
1184
Andreas Gampe13b27842016-11-07 16:48:23 -08001185 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001186 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001187 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001188 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001189 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001190 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001191 // TODO: Better check here.
1192 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001193 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001194 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001195 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001196 }
1197 return m;
1198 }
1199
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001200 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001201 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001202 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001203 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1204 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001205 }
1206
Daniel Erat35e827a2016-05-10 18:07:18 -06001207 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001208 JNIEnvExt* threadEnv = self->GetJniEnv();
1209
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001210 // Verify that the current thread is (a) attached and (b) associated with
1211 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001212 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001213 // Get the thread owning the JNIEnv that's being used.
Ian Rogers55256cb2017-12-21 17:07:11 -08001214 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001215 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001216 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001217 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001218 }
1219
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001220 // Verify that, if this thread previously made a critical "get" call, we
1221 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001222 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001223 case kFlag_CritOkay: // okay to call this method
1224 break;
1225 case kFlag_CritBad: // not okay to call
Ian Rogers55256cb2017-12-21 17:07:11 -08001226 if (threadEnv->critical_ > 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001227 AbortF("thread %s using JNI after critical get",
1228 ToStr<Thread>(*self).c_str());
1229 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001230 }
1231 break;
1232 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001233 // Don't check here; we allow nested gets.
Ian Rogers55256cb2017-12-21 17:07:11 -08001234 if (threadEnv->critical_ == 0) {
1235 threadEnv->critical_start_us_ = self->GetCpuMicroTime();
1236 }
1237 threadEnv->critical_++;
Elliott Hughesa2501992011-08-26 19:39:54 -07001238 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001239 case kFlag_CritRelease: // this is a "release" call
Ian Rogers55256cb2017-12-21 17:07:11 -08001240 if (threadEnv->critical_ == 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001241 AbortF("thread %s called too many critical releases",
1242 ToStr<Thread>(*self).c_str());
1243 return false;
Ian Rogers55256cb2017-12-21 17:07:11 -08001244 } else if (threadEnv->critical_ == 1) {
1245 // Leaving the critical region, possibly warn about long critical regions.
1246 uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->critical_start_us_;
1247 if (critical_duration_us > kCriticalWarnTimeUs) {
1248 LOG(WARNING) << "JNI critical lock held for "
1249 << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1250 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001251 }
Ian Rogers55256cb2017-12-21 17:07:11 -08001252 threadEnv->critical_--;
Elliott Hughesa2501992011-08-26 19:39:54 -07001253 break;
1254 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001255 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001256 }
1257
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001258 // Verify that, if an exception has been raised, the native code doesn't
1259 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001260 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001261 mirror::Throwable* exception = self->GetException();
1262 AbortF("JNI %s called with pending exception %s",
1263 function_name_,
1264 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001265 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001266 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001267 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001268 }
1269
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001270 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001271 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001272 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001273 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001274 AbortF("non-nullable const char* was NULL");
1275 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001276 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001277 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001278 }
1279
Ian Rogersef7d42f2014-01-06 12:55:46 -08001280 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001281 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001282 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001283 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1284 // practice anyways.
1285 std::ostringstream oss;
1286 oss << std::hex;
1287 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1288 while (*tmp != 0) {
1289 if (tmp == utf8) {
1290 oss << "<";
1291 }
1292 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1293 if (tmp == utf8) {
1294 oss << '>';
1295 }
1296 tmp++;
1297 if (*tmp != 0) {
1298 oss << ' ';
1299 }
1300 }
1301
Ian Rogers68d8b422014-07-17 11:09:10 -07001302 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001303 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001304 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001305 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001306 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001307 }
1308
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001309 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1310 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001311 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001312 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001313 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001314 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001315 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001316 case 0x00:
1317 case 0x01:
1318 case 0x02:
1319 case 0x03:
1320 case 0x04:
1321 case 0x05:
1322 case 0x06:
1323 case 0x07:
1324 // Bit pattern 0xxx. No need for any extra bytes.
1325 break;
1326 case 0x08:
1327 case 0x09:
1328 case 0x0a:
1329 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001330 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001331 *errorKind = "start";
1332 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001333 case 0x0f:
1334 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001335 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001336 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1337 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001338 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1339 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001340 *errorKind = "continuation";
1341 return utf8;
1342 }
1343 } else {
1344 *errorKind = "start";
1345 return utf8;
1346 }
1347
1348 // Fall through to the cases below to consume two more continuation bytes.
1349 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001350 case 0x0e:
1351 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001352 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1353 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001354 *errorKind = "continuation";
1355 return utf8;
1356 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001357
1358 // Fall through to consume one more continuation byte.
1359 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001360 case 0x0c:
1361 case 0x0d:
1362 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001363 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1364 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001365 *errorKind = "continuation";
1366 return utf8;
1367 }
1368 break;
1369 }
1370 }
1371 return 0;
1372 }
1373
Ian Rogers68d8b422014-07-17 11:09:10 -07001374 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1375 va_list args;
1376 va_start(args, fmt);
1377 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1378 va_end(args);
1379 }
1380
1381 // The name of the JNI function being checked.
1382 const char* const function_name_;
1383
Elliott Hughes92cb4982011-12-16 16:57:28 -08001384 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001385
Ian Rogers55256cb2017-12-21 17:07:11 -08001386 const uint16_t flags_;
1387
Ian Rogers68d8b422014-07-17 11:09:10 -07001388 const bool has_method_;
1389
Elliott Hughesa2501992011-08-26 19:39:54 -07001390 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1391};
1392
Elliott Hughesa2501992011-08-26 19:39:54 -07001393/*
1394 * ===========================================================================
1395 * Guarded arrays
1396 * ===========================================================================
1397 */
1398
Elliott Hughesa2501992011-08-26 19:39:54 -07001399/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001400class GuardedCopy {
1401 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001402 /*
1403 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1404 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001405 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001406 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001407 const size_t new_len = LengthIncludingRedZones(len);
1408 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001409
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001410 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001411 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001412 if (!mod_okay) {
1413 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001414 }
1415
Ian Rogers68d8b422014-07-17 11:09:10 -07001416 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001417
Ian Rogers68d8b422014-07-17 11:09:10 -07001418 // Fill begin region with canary pattern.
1419 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1420 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1421 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1422 if (kCanary[j] == '\0') {
1423 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001424 } else {
1425 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001426 }
1427 }
1428
1429 // Copy the data in; note "len" could be zero.
1430 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1431
1432 // Fill end region with canary pattern.
1433 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1434 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1435 if (kCanary[j] == '\0') {
1436 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001437 } else {
1438 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001439 }
1440 }
1441
1442 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001443 }
1444
1445 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001446 * Create a guarded copy of a primitive array. Modifications to the copied
1447 * data are allowed. Returns a pointer to the copied data.
1448 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001449 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1450 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001451 ScopedObjectAccess soa(env);
1452
Mathieu Chartier0795f232016-09-27 18:43:30 -07001453 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001454 size_t component_size = a->GetClass()->GetComponentSize();
1455 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001456 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001457 if (is_copy != nullptr) {
1458 *is_copy = JNI_TRUE;
1459 }
1460 return result;
1461 }
1462
1463 /*
1464 * Perform the array "release" operation, which may or may not copy data
1465 * back into the managed heap, and may or may not release the underlying storage.
1466 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001467 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1468 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1469 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001470 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001471 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1472 return nullptr;
1473 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001474 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1475 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001476 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001477 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001478 }
1479 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001480 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001481 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001482 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001483 }
1484
1485
1486 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001487 * Free up the guard buffer, scrub it, and return the original pointer.
1488 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001489 static void* Destroy(void* embedded_buf) {
1490 GuardedCopy* copy = FromEmbedded(embedded_buf);
1491 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1492 size_t len = LengthIncludingRedZones(copy->original_length_);
1493 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001494 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001495 }
1496
1497 /*
1498 * Verify the guard area and, if "modOkay" is false, that the data itself
1499 * has not been altered.
1500 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001501 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001502 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001503 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1504 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1505 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001506 }
1507
1508 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001509 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001510 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1511 }
1512
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001513 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001514 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001515 if (result == MAP_FAILED) {
1516 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1517 }
1518 return reinterpret_cast<uint8_t*>(result);
1519 }
1520
Ian Rogers68d8b422014-07-17 11:09:10 -07001521 static void DebugFree(void* buf, size_t len) {
1522 if (munmap(buf, len) != 0) {
1523 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001524 }
1525 }
1526
Ian Rogers68d8b422014-07-17 11:09:10 -07001527 static size_t LengthIncludingRedZones(size_t len) {
1528 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001529 }
1530
Ian Rogers68d8b422014-07-17 11:09:10 -07001531 // Get the GuardedCopy from the interior pointer.
1532 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1533 return reinterpret_cast<GuardedCopy*>(
1534 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001535 }
1536
Ian Rogers68d8b422014-07-17 11:09:10 -07001537 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1538 return reinterpret_cast<const GuardedCopy*>(
1539 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001540 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001541
1542 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1543 va_list args;
1544 va_start(args, fmt);
1545 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1546 va_end(args);
1547 }
1548
1549 bool CheckHeader(const char* function_name, bool mod_okay) const {
1550 static const uint32_t kMagicCmp = kGuardMagic;
1551
1552 // Before we do anything with "pExtra", check the magic number. We
1553 // do the check with memcmp rather than "==" in case the pointer is
1554 // unaligned. If it points to completely bogus memory we're going
1555 // to crash, but there's no easy way around that.
1556 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1557 uint8_t buf[4];
1558 memcpy(buf, &magic_, 4);
1559 AbortF(function_name,
1560 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1561 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1562 return false;
1563 }
1564
1565 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1566 // told the client that we made a copy, there's no reason they can't alter the buffer.
1567 if (!mod_okay) {
1568 uLong computed_adler =
1569 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1570 if (computed_adler != adler_) {
1571 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1572 computed_adler, adler_, this);
1573 return false;
1574 }
1575 }
1576 return true;
1577 }
1578
1579 bool CheckRedZones(const char* function_name) const {
1580 // Check the begin red zone.
1581 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1582 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1583 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1584 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1585 return false;
1586 }
1587 if (kCanary[j] == '\0') {
1588 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001589 } else {
1590 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001591 }
1592 }
1593
1594 // Check end region.
1595 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1596 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1597 size_t offset_from_buffer_start =
1598 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1599 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1600 offset_from_buffer_start);
1601 return false;
1602 }
1603 if (kCanary[j] == '\0') {
1604 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001605 } else {
1606 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001607 }
1608 }
1609 return true;
1610 }
1611
1612 // Location that canary value will be written before the guarded region.
1613 const char* StartRedZone() const {
1614 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1615 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1616 }
1617
1618 // Return the interior embedded buffer.
1619 const uint8_t* BufferWithinRedZones() const {
1620 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1621 return embedded_buf;
1622 }
1623
1624 // Location that canary value will be written after the guarded region.
1625 const char* EndRedZone() const {
1626 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1627 size_t buf_len = LengthIncludingRedZones(original_length_);
1628 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1629 }
1630
1631 static constexpr size_t kRedZoneSize = 512;
1632 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1633
1634 // Value written before and after the guarded array.
1635 static const char* const kCanary;
1636
1637 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1638
1639 const uint32_t magic_;
1640 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001641 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001642 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001643};
Ian Rogers68d8b422014-07-17 11:09:10 -07001644const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001645
1646/*
1647 * ===========================================================================
1648 * JNI functions
1649 * ===========================================================================
1650 */
1651
1652class CheckJNI {
1653 public:
1654 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001655 ScopedObjectAccess soa(env);
1656 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1657 JniValueType args[1] = {{.E = env }};
1658 if (sc.Check(soa, true, "E", args)) {
1659 JniValueType result;
1660 result.I = baseEnv(env)->GetVersion(env);
1661 if (sc.Check(soa, false, "I", &result)) {
1662 return result.I;
1663 }
1664 }
1665 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001666 }
1667
Ian Rogers68d8b422014-07-17 11:09:10 -07001668 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1669 ScopedObjectAccess soa(env);
1670 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1671 JniValueType args[2] = {{.E = env }, {.p = vm}};
1672 if (sc.Check(soa, true, "Ep", args)) {
1673 JniValueType result;
1674 result.i = baseEnv(env)->GetJavaVM(env, vm);
1675 if (sc.Check(soa, false, "i", &result)) {
1676 return result.i;
1677 }
1678 }
1679 return JNI_ERR;
1680 }
1681
1682 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1683 ScopedObjectAccess soa(env);
1684 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1685 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1686 if (sc.Check(soa, true, "EcpI", args)) {
1687 JniValueType result;
1688 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1689 if (sc.Check(soa, false, "i", &result)) {
1690 return result.i;
1691 }
1692 }
1693 return JNI_ERR;
1694 }
1695
1696 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1697 ScopedObjectAccess soa(env);
1698 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1699 JniValueType args[2] = {{.E = env }, {.c = c}};
1700 if (sc.Check(soa, true, "Ec", args)) {
1701 JniValueType result;
1702 result.i = baseEnv(env)->UnregisterNatives(env, c);
1703 if (sc.Check(soa, false, "i", &result)) {
1704 return result.i;
1705 }
1706 }
1707 return JNI_ERR;
1708 }
1709
1710 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001711 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1712 // know the object is invalid. The spec says that passing invalid objects or even ones that
1713 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001714 ScopedObjectAccess soa(env);
1715 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001716 JniValueType args[2] = {{.E = env }, {.L = obj}};
1717 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001718 JniValueType result;
1719 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1720 if (sc.Check(soa, false, "w", &result)) {
1721 return result.w;
1722 }
1723 }
1724 return JNIInvalidRefType;
1725 }
1726
1727 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1728 jsize bufLen) {
1729 ScopedObjectAccess soa(env);
1730 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1731 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1732 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1733 JniValueType result;
1734 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1735 if (sc.Check(soa, false, "c", &result)) {
1736 return result.c;
1737 }
1738 }
1739 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001740 }
1741
1742 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001743 ScopedObjectAccess soa(env);
1744 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1745 JniValueType args[2] = {{.E = env}, {.u = name}};
1746 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1747 JniValueType result;
1748 result.c = baseEnv(env)->FindClass(env, name);
1749 if (sc.Check(soa, false, "c", &result)) {
1750 return result.c;
1751 }
1752 }
1753 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001754 }
1755
Elliott Hughese84278b2012-03-22 10:06:53 -07001756 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001757 ScopedObjectAccess soa(env);
1758 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1759 JniValueType args[2] = {{.E = env}, {.c = c}};
1760 if (sc.Check(soa, true, "Ec", args)) {
1761 JniValueType result;
1762 result.c = baseEnv(env)->GetSuperclass(env, c);
1763 if (sc.Check(soa, false, "c", &result)) {
1764 return result.c;
1765 }
1766 }
1767 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001768 }
1769
Elliott Hughese84278b2012-03-22 10:06:53 -07001770 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001771 ScopedObjectAccess soa(env);
1772 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1773 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1774 if (sc.Check(soa, true, "Ecc", args)) {
1775 JniValueType result;
1776 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1777 if (sc.Check(soa, false, "b", &result)) {
1778 return result.b;
1779 }
1780 }
1781 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001782 }
1783
1784 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001785 ScopedObjectAccess soa(env);
1786 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1787 JniValueType args[2] = {{.E = env}, {.L = method}};
1788 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1789 JniValueType result;
1790 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1791 if (sc.Check(soa, false, "m", &result)) {
1792 return result.m;
1793 }
1794 }
1795 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001796 }
1797
1798 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001799 ScopedObjectAccess soa(env);
1800 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1801 JniValueType args[2] = {{.E = env}, {.L = field}};
1802 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1803 JniValueType result;
1804 result.f = baseEnv(env)->FromReflectedField(env, field);
1805 if (sc.Check(soa, false, "f", &result)) {
1806 return result.f;
1807 }
1808 }
1809 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001810 }
1811
1812 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001813 ScopedObjectAccess soa(env);
1814 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1815 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1816 if (sc.Check(soa, true, "Ecmb", args)) {
1817 JniValueType result;
1818 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1819 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1820 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1821 return result.L;
1822 }
1823 }
1824 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001825 }
1826
1827 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001828 ScopedObjectAccess soa(env);
1829 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1830 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1831 if (sc.Check(soa, true, "Ecfb", args)) {
1832 JniValueType result;
1833 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1834 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1835 DCHECK(sc.CheckReflectedField(soa, result.L));
1836 return result.L;
1837 }
1838 }
1839 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001840 }
1841
1842 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001843 ScopedObjectAccess soa(env);
1844 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1845 JniValueType args[2] = {{.E = env}, {.t = obj}};
1846 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1847 JniValueType result;
1848 result.i = baseEnv(env)->Throw(env, obj);
1849 if (sc.Check(soa, false, "i", &result)) {
1850 return result.i;
1851 }
1852 }
1853 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001854 }
1855
Elliott Hughese84278b2012-03-22 10:06:53 -07001856 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001857 ScopedObjectAccess soa(env);
1858 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001859 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001860 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1861 JniValueType result;
1862 result.i = baseEnv(env)->ThrowNew(env, c, message);
1863 if (sc.Check(soa, false, "i", &result)) {
1864 return result.i;
1865 }
1866 }
1867 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001868 }
1869
1870 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001871 ScopedObjectAccess soa(env);
1872 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1873 JniValueType args[1] = {{.E = env}};
1874 if (sc.Check(soa, true, "E", args)) {
1875 JniValueType result;
1876 result.t = baseEnv(env)->ExceptionOccurred(env);
1877 if (sc.Check(soa, false, "t", &result)) {
1878 return result.t;
1879 }
1880 }
1881 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001882 }
1883
1884 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001885 ScopedObjectAccess soa(env);
1886 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1887 JniValueType args[1] = {{.E = env}};
1888 if (sc.Check(soa, true, "E", args)) {
1889 JniValueType result;
1890 baseEnv(env)->ExceptionDescribe(env);
1891 result.V = nullptr;
1892 sc.Check(soa, false, "V", &result);
1893 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001894 }
1895
1896 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001897 ScopedObjectAccess soa(env);
1898 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1899 JniValueType args[1] = {{.E = env}};
1900 if (sc.Check(soa, true, "E", args)) {
1901 JniValueType result;
1902 baseEnv(env)->ExceptionClear(env);
1903 result.V = nullptr;
1904 sc.Check(soa, false, "V", &result);
1905 }
1906 }
1907
1908 static jboolean ExceptionCheck(JNIEnv* env) {
1909 ScopedObjectAccess soa(env);
1910 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1911 JniValueType args[1] = {{.E = env}};
1912 if (sc.Check(soa, true, "E", args)) {
1913 JniValueType result;
1914 result.b = baseEnv(env)->ExceptionCheck(env);
1915 if (sc.Check(soa, false, "b", &result)) {
1916 return result.b;
1917 }
1918 }
1919 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001920 }
1921
1922 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001923 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1924 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1925 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001926 ScopedObjectAccess soa(env);
1927 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1928 JniValueType args[2] = {{.E = env}, {.u = msg}};
1929 if (sc.Check(soa, true, "Eu", args)) {
1930 JniValueType result;
1931 baseEnv(env)->FatalError(env, msg);
1932 // Unreachable.
1933 result.V = nullptr;
1934 sc.Check(soa, false, "V", &result);
1935 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001936 }
1937
1938 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001939 ScopedObjectAccess soa(env);
1940 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1941 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1942 if (sc.Check(soa, true, "EI", args)) {
1943 JniValueType result;
1944 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1945 if (sc.Check(soa, false, "i", &result)) {
1946 return result.i;
1947 }
1948 }
1949 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001950 }
1951
1952 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001953 ScopedObjectAccess soa(env);
1954 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1955 JniValueType args[2] = {{.E = env}, {.L = res}};
1956 if (sc.Check(soa, true, "EL", args)) {
1957 JniValueType result;
1958 result.L = baseEnv(env)->PopLocalFrame(env, res);
1959 sc.Check(soa, false, "L", &result);
1960 return result.L;
1961 }
1962 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001963 }
1964
1965 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001966 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001967 }
1968
Ian Rogers68d8b422014-07-17 11:09:10 -07001969 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1970 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001971 }
1972
1973 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001974 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001975 }
1976
Ian Rogers68d8b422014-07-17 11:09:10 -07001977 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1978 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001979 }
1980
Ian Rogers68d8b422014-07-17 11:09:10 -07001981 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1982 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1983 }
1984
1985 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1986 DeleteRef(__FUNCTION__, env, obj, kLocal);
1987 }
1988
1989 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1990 ScopedObjectAccess soa(env);
1991 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1992 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1993 if (sc.Check(soa, true, "EI", args)) {
1994 JniValueType result;
1995 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1996 if (sc.Check(soa, false, "i", &result)) {
1997 return result.i;
1998 }
1999 }
2000 return JNI_ERR;
2001 }
2002
2003 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
2004 ScopedObjectAccess soa(env);
2005 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2006 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2007 if (sc.Check(soa, true, "ELL", args)) {
2008 JniValueType result;
2009 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2010 if (sc.Check(soa, false, "b", &result)) {
2011 return result.b;
2012 }
2013 }
2014 return JNI_FALSE;
2015 }
2016
2017 static jobject AllocObject(JNIEnv* env, jclass c) {
2018 ScopedObjectAccess soa(env);
2019 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2020 JniValueType args[2] = {{.E = env}, {.c = c}};
2021 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2022 JniValueType result;
2023 result.L = baseEnv(env)->AllocObject(env, c);
2024 if (sc.Check(soa, false, "L", &result)) {
2025 return result.L;
2026 }
2027 }
2028 return nullptr;
2029 }
2030
2031 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2032 ScopedObjectAccess soa(env);
2033 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002034 VarArgs rest(mid, vargs);
2035 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2036 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002037 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002038 JniValueType result;
2039 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2040 if (sc.Check(soa, false, "L", &result)) {
2041 return result.L;
2042 }
2043 }
2044 return nullptr;
2045 }
2046
2047 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2048 va_list args;
2049 va_start(args, mid);
2050 jobject result = NewObjectV(env, c, mid, args);
2051 va_end(args);
2052 return result;
2053 }
2054
2055 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2056 ScopedObjectAccess soa(env);
2057 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002058 VarArgs rest(mid, vargs);
2059 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2060 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002061 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002062 JniValueType result;
2063 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2064 if (sc.Check(soa, false, "L", &result)) {
2065 return result.L;
2066 }
2067 }
2068 return nullptr;
2069 }
2070
2071 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2072 ScopedObjectAccess soa(env);
2073 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2074 JniValueType args[2] = {{.E = env}, {.L = obj}};
2075 if (sc.Check(soa, true, "EL", args)) {
2076 JniValueType result;
2077 result.c = baseEnv(env)->GetObjectClass(env, obj);
2078 if (sc.Check(soa, false, "c", &result)) {
2079 return result.c;
2080 }
2081 }
2082 return nullptr;
2083 }
2084
2085 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2086 ScopedObjectAccess soa(env);
2087 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2088 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2089 if (sc.Check(soa, true, "ELc", args)) {
2090 JniValueType result;
2091 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2092 if (sc.Check(soa, false, "b", &result)) {
2093 return result.b;
2094 }
2095 }
2096 return JNI_FALSE;
2097 }
2098
2099 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2100 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2101 }
2102
2103 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2104 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2105 }
2106
2107 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2108 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2109 }
2110
2111 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2112 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2113 }
2114
2115#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2116 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2117 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2118 } \
2119 \
2120 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2121 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2122 } \
2123 \
2124 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2125 JniValueType value; \
2126 value.shorty = v; \
2127 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2128 } \
2129 \
2130 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2131 JniValueType value; \
2132 value.shorty = v; \
2133 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2134 }
2135
2136 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2137 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2138 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2139 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2140 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2141 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2142 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2143 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2144 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2145#undef FIELD_ACCESSORS
2146
2147 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2148 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2149 }
2150
2151 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2152 jvalue* vargs) {
2153 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2154 }
2155
2156 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002157 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002158 }
2159
2160 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2161 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2162 }
2163
2164 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2165 va_list vargs) {
2166 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2167 }
2168
2169 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2170 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2171 }
2172
2173 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2174 va_list vargs;
2175 va_start(vargs, mid);
2176 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2177 va_end(vargs);
2178 }
2179
2180 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2181 va_list vargs;
2182 va_start(vargs, mid);
2183 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2184 va_end(vargs);
2185 }
2186
2187 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2188 va_list vargs;
2189 va_start(vargs, mid);
2190 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2191 va_end(vargs);
2192 }
2193
2194#define CALL(rtype, name, ptype, shorty) \
2195 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2196 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2197 } \
2198 \
2199 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2200 jvalue* vargs) { \
2201 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2202 } \
2203 \
2204 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2205 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2206 } \
2207 \
2208 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2209 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2210 } \
2211 \
2212 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2213 va_list vargs) { \
2214 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2215 } \
2216 \
2217 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2218 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2219 } \
2220 \
2221 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2222 va_list vargs; \
2223 va_start(vargs, mid); \
2224 rtype result = \
2225 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2226 va_end(vargs); \
2227 return result; \
2228 } \
2229 \
2230 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2231 ...) { \
2232 va_list vargs; \
2233 va_start(vargs, mid); \
2234 rtype result = \
2235 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2236 va_end(vargs); \
2237 return result; \
2238 } \
2239 \
2240 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2241 va_list vargs; \
2242 va_start(vargs, mid); \
2243 rtype result = \
2244 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2245 va_end(vargs); \
2246 return result; \
2247 }
2248
2249 CALL(jobject, Object, Primitive::kPrimNot, L)
2250 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2251 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2252 CALL(jchar, Char, Primitive::kPrimChar, C)
2253 CALL(jshort, Short, Primitive::kPrimShort, S)
2254 CALL(jint, Int, Primitive::kPrimInt, I)
2255 CALL(jlong, Long, Primitive::kPrimLong, J)
2256 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2257 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2258#undef CALL
2259
2260 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2261 ScopedObjectAccess soa(env);
2262 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2263 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2264 if (sc.Check(soa, true, "Epz", args)) {
2265 JniValueType result;
2266 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2267 if (sc.Check(soa, false, "s", &result)) {
2268 return result.s;
2269 }
2270 }
2271 return nullptr;
2272 }
2273
2274 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2275 ScopedObjectAccess soa(env);
2276 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2277 JniValueType args[2] = {{.E = env}, {.u = chars}};
2278 if (sc.Check(soa, true, "Eu", args)) {
2279 JniValueType result;
2280 // TODO: stale? show pointer and truncate string.
2281 result.s = baseEnv(env)->NewStringUTF(env, chars);
2282 if (sc.Check(soa, false, "s", &result)) {
2283 return result.s;
2284 }
2285 }
2286 return nullptr;
2287 }
2288
2289 static jsize GetStringLength(JNIEnv* env, jstring string) {
2290 ScopedObjectAccess soa(env);
2291 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2292 JniValueType args[2] = {{.E = env}, {.s = string}};
2293 if (sc.Check(soa, true, "Es", args)) {
2294 JniValueType result;
2295 result.z = baseEnv(env)->GetStringLength(env, string);
2296 if (sc.Check(soa, false, "z", &result)) {
2297 return result.z;
2298 }
2299 }
2300 return JNI_ERR;
2301 }
2302
2303 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2304 ScopedObjectAccess soa(env);
2305 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2306 JniValueType args[2] = {{.E = env}, {.s = string}};
2307 if (sc.Check(soa, true, "Es", args)) {
2308 JniValueType result;
2309 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2310 if (sc.Check(soa, false, "z", &result)) {
2311 return result.z;
2312 }
2313 }
2314 return JNI_ERR;
2315 }
2316
2317 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2318 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2319 is_copy, false, false));
2320 }
2321
2322 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2323 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2324 is_copy, true, false));
2325 }
2326
2327 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2328 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2329 is_copy, false, true));
2330 }
2331
2332 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2333 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2334 }
2335
2336 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2337 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2338 }
2339
2340 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2341 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2342 }
2343
2344 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2345 ScopedObjectAccess soa(env);
2346 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2347 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2348 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2349 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2350 if (sc.Check(soa, true, "EsIIp", args)) {
2351 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2352 JniValueType result;
2353 result.V = nullptr;
2354 sc.Check(soa, false, "V", &result);
2355 }
2356 }
2357
2358 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2359 ScopedObjectAccess soa(env);
2360 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2361 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2362 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2363 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2364 if (sc.Check(soa, true, "EsIIp", args)) {
2365 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2366 JniValueType result;
2367 result.V = nullptr;
2368 sc.Check(soa, false, "V", &result);
2369 }
2370 }
2371
2372 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2373 ScopedObjectAccess soa(env);
2374 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2375 JniValueType args[2] = {{.E = env}, {.a = array}};
2376 if (sc.Check(soa, true, "Ea", args)) {
2377 JniValueType result;
2378 result.z = baseEnv(env)->GetArrayLength(env, array);
2379 if (sc.Check(soa, false, "z", &result)) {
2380 return result.z;
2381 }
2382 }
2383 return JNI_ERR;
2384 }
2385
2386 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2387 jobject initial_element) {
2388 ScopedObjectAccess soa(env);
2389 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2390 JniValueType args[4] =
2391 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2392 if (sc.Check(soa, true, "EzcL", args)) {
2393 JniValueType result;
2394 // Note: assignability tests of initial_element are done in the base implementation.
2395 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2396 if (sc.Check(soa, false, "a", &result)) {
2397 return down_cast<jobjectArray>(result.a);
2398 }
2399 }
2400 return nullptr;
2401 }
2402
2403 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2404 ScopedObjectAccess soa(env);
2405 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2406 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2407 if (sc.Check(soa, true, "Eaz", args)) {
2408 JniValueType result;
2409 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2410 if (sc.Check(soa, false, "L", &result)) {
2411 return result.L;
2412 }
2413 }
2414 return nullptr;
2415 }
2416
2417 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2418 ScopedObjectAccess soa(env);
2419 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2420 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2421 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2422 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2423 // in ArrayStoreExceptions.
2424 if (sc.Check(soa, true, "EaIL", args)) {
2425 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2426 JniValueType result;
2427 result.V = nullptr;
2428 sc.Check(soa, false, "V", &result);
2429 }
2430 }
2431
2432 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2433 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2434 Primitive::kPrimBoolean));
2435 }
2436
2437 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2438 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2439 Primitive::kPrimByte));
2440 }
2441
2442 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2443 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2444 Primitive::kPrimChar));
2445 }
2446
2447 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2448 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2449 Primitive::kPrimShort));
2450 }
2451
2452 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2453 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2454 }
2455
2456 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2457 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2458 Primitive::kPrimLong));
2459 }
2460
2461 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2462 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2463 Primitive::kPrimFloat));
2464 }
2465
2466 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2467 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2468 Primitive::kPrimDouble));
2469 }
2470
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002471// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002472#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002473 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2474 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002475 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2476 } \
2477 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002478 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002479 jint mode) { \
2480 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2481 } \
2482 \
2483 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002484 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002485 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2486 } \
2487 \
2488 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2489 const ctype* buf) { \
2490 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2491 }
2492
2493 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2494 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2495 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2496 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2497 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2498 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2499 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2500 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2501#undef PRIMITIVE_ARRAY_FUNCTIONS
2502
2503 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2504 ScopedObjectAccess soa(env);
2505 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2506 JniValueType args[2] = {{.E = env}, {.L = obj}};
2507 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002508 if (obj != nullptr) {
2509 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2510 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002511 JniValueType result;
2512 result.i = baseEnv(env)->MonitorEnter(env, obj);
2513 if (sc.Check(soa, false, "i", &result)) {
2514 return result.i;
2515 }
2516 }
2517 return JNI_ERR;
2518 }
2519
2520 static jint MonitorExit(JNIEnv* env, jobject obj) {
2521 ScopedObjectAccess soa(env);
2522 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2523 JniValueType args[2] = {{.E = env}, {.L = obj}};
2524 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002525 if (obj != nullptr) {
2526 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2527 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002528 JniValueType result;
2529 result.i = baseEnv(env)->MonitorExit(env, obj);
2530 if (sc.Check(soa, false, "i", &result)) {
2531 return result.i;
2532 }
2533 }
2534 return JNI_ERR;
2535 }
2536
2537 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2538 ScopedObjectAccess soa(env);
2539 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2540 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2541 if (sc.Check(soa, true, "Eap", args)) {
2542 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002543 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2544 if (ptr != nullptr && soa.ForceCopy()) {
2545 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002546 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002547 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002548 if (sc.Check(soa, false, "p", &result)) {
2549 return const_cast<void*>(result.p);
2550 }
2551 }
2552 return nullptr;
2553 }
2554
2555 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2556 ScopedObjectAccess soa(env);
2557 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2558 sc.CheckNonNull(carray);
2559 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2560 if (sc.Check(soa, true, "Eapr", args)) {
2561 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002562 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002563 }
2564 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2565 JniValueType result;
2566 result.V = nullptr;
2567 sc.Check(soa, false, "V", &result);
2568 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002569 }
2570
2571 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002572 ScopedObjectAccess soa(env);
2573 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2574 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2575 if (sc.Check(soa, true, "EpJ", args)) {
2576 JniValueType result;
2577 // Note: the validity of address and capacity are checked in the base implementation.
2578 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2579 if (sc.Check(soa, false, "L", &result)) {
2580 return result.L;
2581 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002582 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002583 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002584 }
2585
2586 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002587 ScopedObjectAccess soa(env);
2588 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2589 JniValueType args[2] = {{.E = env}, {.L = buf}};
2590 if (sc.Check(soa, true, "EL", args)) {
2591 JniValueType result;
2592 // Note: this is implemented in the base environment by a GetLongField which will sanity
2593 // check the type of buf in GetLongField above.
2594 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2595 if (sc.Check(soa, false, "p", &result)) {
2596 return const_cast<void*>(result.p);
2597 }
2598 }
2599 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002600 }
2601
2602 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002603 ScopedObjectAccess soa(env);
2604 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2605 JniValueType args[2] = {{.E = env}, {.L = buf}};
2606 if (sc.Check(soa, true, "EL", args)) {
2607 JniValueType result;
2608 // Note: this is implemented in the base environment by a GetIntField which will sanity
2609 // check the type of buf in GetIntField above.
2610 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2611 if (sc.Check(soa, false, "J", &result)) {
2612 return result.J;
2613 }
2614 }
2615 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002616 }
2617
2618 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002619 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002620 return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
Ian Rogers68d8b422014-07-17 11:09:10 -07002621 }
2622
2623 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Ian Rogers55256cb2017-12-21 17:07:11 -08002624 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions_;
Elliott Hughesa2501992011-08-26 19:39:54 -07002625 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002626
2627 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2628 ScopedObjectAccess soa(env);
2629 ScopedCheck sc(kFlag_Default, function_name);
2630 JniValueType args[2] = {{.E = env}, {.L = obj}};
2631 if (sc.Check(soa, true, "EL", args)) {
2632 JniValueType result;
2633 switch (kind) {
2634 case kGlobal:
2635 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2636 break;
2637 case kLocal:
2638 result.L = baseEnv(env)->NewLocalRef(env, obj);
2639 break;
2640 case kWeakGlobal:
2641 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2642 break;
2643 default:
2644 LOG(FATAL) << "Unexpected reference kind: " << kind;
2645 }
2646 if (sc.Check(soa, false, "L", &result)) {
2647 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002648 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002649 return result.L;
2650 }
2651 }
2652 return nullptr;
2653 }
2654
2655 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2656 ScopedObjectAccess soa(env);
2657 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2658 JniValueType args[2] = {{.E = env}, {.L = obj}};
2659 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002660 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002661 JniValueType result;
2662 switch (kind) {
2663 case kGlobal:
2664 baseEnv(env)->DeleteGlobalRef(env, obj);
2665 break;
2666 case kLocal:
2667 baseEnv(env)->DeleteLocalRef(env, obj);
2668 break;
2669 case kWeakGlobal:
2670 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2671 break;
2672 default:
2673 LOG(FATAL) << "Unexpected reference kind: " << kind;
2674 }
2675 result.V = nullptr;
2676 sc.Check(soa, false, "V", &result);
2677 }
2678 }
2679
2680 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2681 const char* name, const char* sig, bool is_static) {
2682 ScopedObjectAccess soa(env);
2683 ScopedCheck sc(kFlag_Default, function_name);
2684 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2685 if (sc.Check(soa, true, "Ecuu", args)) {
2686 JniValueType result;
2687 if (is_static) {
2688 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2689 } else {
2690 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2691 }
2692 if (sc.Check(soa, false, "m", &result)) {
2693 return result.m;
2694 }
2695 }
2696 return nullptr;
2697 }
2698
2699 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2700 const char* name, const char* sig, bool is_static) {
2701 ScopedObjectAccess soa(env);
2702 ScopedCheck sc(kFlag_Default, function_name);
2703 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2704 if (sc.Check(soa, true, "Ecuu", args)) {
2705 JniValueType result;
2706 if (is_static) {
2707 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2708 } else {
2709 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2710 }
2711 if (sc.Check(soa, false, "f", &result)) {
2712 return result.f;
2713 }
2714 }
2715 return nullptr;
2716 }
2717
2718 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2719 bool is_static, Primitive::Type type) {
2720 ScopedObjectAccess soa(env);
2721 ScopedCheck sc(kFlag_Default, function_name);
2722 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2723 JniValueType result;
2724 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2725 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2726 const char* result_check = nullptr;
2727 switch (type) {
2728 case Primitive::kPrimNot:
2729 if (is_static) {
2730 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2731 } else {
2732 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2733 }
2734 result_check = "L";
2735 break;
2736 case Primitive::kPrimBoolean:
2737 if (is_static) {
2738 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2739 } else {
2740 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2741 }
2742 result_check = "Z";
2743 break;
2744 case Primitive::kPrimByte:
2745 if (is_static) {
2746 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2747 } else {
2748 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2749 }
2750 result_check = "B";
2751 break;
2752 case Primitive::kPrimChar:
2753 if (is_static) {
2754 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2755 } else {
2756 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2757 }
2758 result_check = "C";
2759 break;
2760 case Primitive::kPrimShort:
2761 if (is_static) {
2762 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2763 } else {
2764 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2765 }
2766 result_check = "S";
2767 break;
2768 case Primitive::kPrimInt:
2769 if (is_static) {
2770 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2771 } else {
2772 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2773 }
2774 result_check = "I";
2775 break;
2776 case Primitive::kPrimLong:
2777 if (is_static) {
2778 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2779 } else {
2780 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2781 }
2782 result_check = "J";
2783 break;
2784 case Primitive::kPrimFloat:
2785 if (is_static) {
2786 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2787 } else {
2788 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2789 }
2790 result_check = "F";
2791 break;
2792 case Primitive::kPrimDouble:
2793 if (is_static) {
2794 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2795 } else {
2796 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2797 }
2798 result_check = "D";
2799 break;
2800 case Primitive::kPrimVoid:
2801 LOG(FATAL) << "Unexpected type: " << type;
2802 break;
2803 }
2804 if (sc.Check(soa, false, result_check, &result)) {
2805 return result;
2806 }
2807 }
2808 result.J = 0;
2809 return result;
2810 }
2811
2812 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2813 bool is_static, Primitive::Type type, JniValueType value) {
2814 ScopedObjectAccess soa(env);
2815 ScopedCheck sc(kFlag_Default, function_name);
2816 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2817 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2818 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2819 if (sc.Check(soa, true, sig, args) &&
2820 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2821 switch (type) {
2822 case Primitive::kPrimNot:
2823 if (is_static) {
2824 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2825 } else {
2826 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2827 }
2828 break;
2829 case Primitive::kPrimBoolean:
2830 if (is_static) {
2831 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2832 } else {
2833 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2834 }
2835 break;
2836 case Primitive::kPrimByte:
2837 if (is_static) {
2838 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2839 } else {
2840 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2841 }
2842 break;
2843 case Primitive::kPrimChar:
2844 if (is_static) {
2845 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2846 } else {
2847 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2848 }
2849 break;
2850 case Primitive::kPrimShort:
2851 if (is_static) {
2852 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2853 } else {
2854 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2855 }
2856 break;
2857 case Primitive::kPrimInt:
2858 if (is_static) {
2859 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2860 } else {
2861 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2862 }
2863 break;
2864 case Primitive::kPrimLong:
2865 if (is_static) {
2866 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2867 } else {
2868 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2869 }
2870 break;
2871 case Primitive::kPrimFloat:
2872 if (is_static) {
2873 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2874 } else {
2875 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2876 }
2877 break;
2878 case Primitive::kPrimDouble:
2879 if (is_static) {
2880 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2881 } else {
2882 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2883 }
2884 break;
2885 case Primitive::kPrimVoid:
2886 LOG(FATAL) << "Unexpected type: " << type;
2887 break;
2888 }
2889 JniValueType result;
2890 result.V = nullptr;
2891 sc.Check(soa, false, "V", &result);
2892 }
2893 }
2894
2895 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002896 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002897 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002898 bool checked;
2899 switch (invoke) {
2900 case kVirtual: {
2901 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002902 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2903 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002904 break;
2905 }
2906 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002907 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2908 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002909 break;
2910 }
2911 case kStatic: {
2912 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002913 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2914 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002915 break;
2916 }
2917 default:
2918 LOG(FATAL) << "Unexpected invoke: " << invoke;
2919 checked = false;
2920 break;
2921 }
2922 return checked;
2923 }
2924
2925 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2926 jmethodID mid, jvalue* vargs, Primitive::Type type,
2927 InvokeType invoke) {
2928 ScopedObjectAccess soa(env);
2929 ScopedCheck sc(kFlag_Default, function_name);
2930 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002931 VarArgs rest(mid, vargs);
2932 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002933 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2934 const char* result_check;
2935 switch (type) {
2936 case Primitive::kPrimNot:
2937 result_check = "L";
2938 switch (invoke) {
2939 case kVirtual:
2940 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2941 break;
2942 case kDirect:
2943 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2944 break;
2945 case kStatic:
2946 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2947 break;
2948 default:
2949 break;
2950 }
2951 break;
2952 case Primitive::kPrimBoolean:
2953 result_check = "Z";
2954 switch (invoke) {
2955 case kVirtual:
2956 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2957 break;
2958 case kDirect:
2959 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2960 break;
2961 case kStatic:
2962 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2963 break;
2964 default:
2965 break;
2966 }
2967 break;
2968 case Primitive::kPrimByte:
2969 result_check = "B";
2970 switch (invoke) {
2971 case kVirtual:
2972 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2973 break;
2974 case kDirect:
2975 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2976 break;
2977 case kStatic:
2978 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2979 break;
2980 default:
2981 break;
2982 }
2983 break;
2984 case Primitive::kPrimChar:
2985 result_check = "C";
2986 switch (invoke) {
2987 case kVirtual:
2988 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2989 break;
2990 case kDirect:
2991 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2992 break;
2993 case kStatic:
2994 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2995 break;
2996 default:
2997 break;
2998 }
2999 break;
3000 case Primitive::kPrimShort:
3001 result_check = "S";
3002 switch (invoke) {
3003 case kVirtual:
3004 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3005 break;
3006 case kDirect:
3007 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3008 break;
3009 case kStatic:
3010 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3011 break;
3012 default:
3013 break;
3014 }
3015 break;
3016 case Primitive::kPrimInt:
3017 result_check = "I";
3018 switch (invoke) {
3019 case kVirtual:
3020 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3021 break;
3022 case kDirect:
3023 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3024 break;
3025 case kStatic:
3026 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3027 break;
3028 default:
3029 break;
3030 }
3031 break;
3032 case Primitive::kPrimLong:
3033 result_check = "J";
3034 switch (invoke) {
3035 case kVirtual:
3036 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3037 break;
3038 case kDirect:
3039 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3040 break;
3041 case kStatic:
3042 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3043 break;
3044 default:
3045 break;
3046 }
3047 break;
3048 case Primitive::kPrimFloat:
3049 result_check = "F";
3050 switch (invoke) {
3051 case kVirtual:
3052 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3053 break;
3054 case kDirect:
3055 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3056 break;
3057 case kStatic:
3058 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3059 break;
3060 default:
3061 break;
3062 }
3063 break;
3064 case Primitive::kPrimDouble:
3065 result_check = "D";
3066 switch (invoke) {
3067 case kVirtual:
3068 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3069 break;
3070 case kDirect:
3071 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3072 break;
3073 case kStatic:
3074 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3075 break;
3076 default:
3077 break;
3078 }
3079 break;
3080 case Primitive::kPrimVoid:
3081 result_check = "V";
3082 result.V = nullptr;
3083 switch (invoke) {
3084 case kVirtual:
3085 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3086 break;
3087 case kDirect:
3088 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3089 break;
3090 case kStatic:
3091 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3092 break;
3093 default:
3094 LOG(FATAL) << "Unexpected invoke: " << invoke;
3095 }
3096 break;
3097 default:
3098 LOG(FATAL) << "Unexpected return type: " << type;
3099 result_check = nullptr;
3100 }
3101 if (sc.Check(soa, false, result_check, &result)) {
3102 return result;
3103 }
3104 }
3105 result.J = 0;
3106 return result;
3107 }
3108
3109 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3110 jmethodID mid, va_list vargs, Primitive::Type type,
3111 InvokeType invoke) {
3112 ScopedObjectAccess soa(env);
3113 ScopedCheck sc(kFlag_Default, function_name);
3114 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003115 VarArgs rest(mid, vargs);
3116 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003117 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3118 const char* result_check;
3119 switch (type) {
3120 case Primitive::kPrimNot:
3121 result_check = "L";
3122 switch (invoke) {
3123 case kVirtual:
3124 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3125 break;
3126 case kDirect:
3127 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3128 break;
3129 case kStatic:
3130 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3131 break;
3132 default:
3133 LOG(FATAL) << "Unexpected invoke: " << invoke;
3134 }
3135 break;
3136 case Primitive::kPrimBoolean:
3137 result_check = "Z";
3138 switch (invoke) {
3139 case kVirtual:
3140 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3141 break;
3142 case kDirect:
3143 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3144 break;
3145 case kStatic:
3146 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3147 break;
3148 default:
3149 LOG(FATAL) << "Unexpected invoke: " << invoke;
3150 }
3151 break;
3152 case Primitive::kPrimByte:
3153 result_check = "B";
3154 switch (invoke) {
3155 case kVirtual:
3156 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3157 break;
3158 case kDirect:
3159 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3160 break;
3161 case kStatic:
3162 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3163 break;
3164 default:
3165 LOG(FATAL) << "Unexpected invoke: " << invoke;
3166 }
3167 break;
3168 case Primitive::kPrimChar:
3169 result_check = "C";
3170 switch (invoke) {
3171 case kVirtual:
3172 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3173 break;
3174 case kDirect:
3175 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3176 break;
3177 case kStatic:
3178 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3179 break;
3180 default:
3181 LOG(FATAL) << "Unexpected invoke: " << invoke;
3182 }
3183 break;
3184 case Primitive::kPrimShort:
3185 result_check = "S";
3186 switch (invoke) {
3187 case kVirtual:
3188 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3189 break;
3190 case kDirect:
3191 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3192 break;
3193 case kStatic:
3194 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3195 break;
3196 default:
3197 LOG(FATAL) << "Unexpected invoke: " << invoke;
3198 }
3199 break;
3200 case Primitive::kPrimInt:
3201 result_check = "I";
3202 switch (invoke) {
3203 case kVirtual:
3204 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3205 break;
3206 case kDirect:
3207 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3208 break;
3209 case kStatic:
3210 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3211 break;
3212 default:
3213 LOG(FATAL) << "Unexpected invoke: " << invoke;
3214 }
3215 break;
3216 case Primitive::kPrimLong:
3217 result_check = "J";
3218 switch (invoke) {
3219 case kVirtual:
3220 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3221 break;
3222 case kDirect:
3223 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3224 break;
3225 case kStatic:
3226 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3227 break;
3228 default:
3229 LOG(FATAL) << "Unexpected invoke: " << invoke;
3230 }
3231 break;
3232 case Primitive::kPrimFloat:
3233 result_check = "F";
3234 switch (invoke) {
3235 case kVirtual:
3236 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3237 break;
3238 case kDirect:
3239 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3240 break;
3241 case kStatic:
3242 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3243 break;
3244 default:
3245 LOG(FATAL) << "Unexpected invoke: " << invoke;
3246 }
3247 break;
3248 case Primitive::kPrimDouble:
3249 result_check = "D";
3250 switch (invoke) {
3251 case kVirtual:
3252 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3253 break;
3254 case kDirect:
3255 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3256 break;
3257 case kStatic:
3258 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3259 break;
3260 default:
3261 LOG(FATAL) << "Unexpected invoke: " << invoke;
3262 }
3263 break;
3264 case Primitive::kPrimVoid:
3265 result_check = "V";
3266 result.V = nullptr;
3267 switch (invoke) {
3268 case kVirtual:
3269 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3270 break;
3271 case kDirect:
3272 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3273 break;
3274 case kStatic:
3275 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3276 break;
3277 default:
3278 LOG(FATAL) << "Unexpected invoke: " << invoke;
3279 }
3280 break;
3281 default:
3282 LOG(FATAL) << "Unexpected return type: " << type;
3283 result_check = nullptr;
3284 }
3285 if (sc.Check(soa, false, result_check, &result)) {
3286 return result;
3287 }
3288 }
3289 result.J = 0;
3290 return result;
3291 }
3292
3293 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3294 jboolean* is_copy, bool utf, bool critical) {
3295 ScopedObjectAccess soa(env);
3296 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3297 ScopedCheck sc(flags, function_name);
3298 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3299 if (sc.Check(soa, true, "Esp", args)) {
3300 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003301 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003302 if (utf) {
3303 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003304 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3305 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003306 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003307 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3308 baseEnv(env)->GetStringChars(env, string, is_copy));
3309 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003310 }
3311 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003312 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003313 if (utf) {
3314 size_t length_in_bytes = strlen(result.u) + 1;
3315 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003316 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003317 } else {
3318 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3319 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003320 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003321 }
3322 if (is_copy != nullptr) {
3323 *is_copy = JNI_TRUE;
3324 }
3325 }
3326 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3327 return utf ? result.u : result.p;
3328 }
3329 }
3330 return nullptr;
3331 }
3332
3333 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3334 const void* chars, bool utf, bool critical) {
3335 ScopedObjectAccess soa(env);
3336 int flags = kFlag_ExcepOkay | kFlag_Release;
3337 if (critical) {
3338 flags |= kFlag_CritRelease;
3339 }
3340 ScopedCheck sc(flags, function_name);
3341 sc.CheckNonNull(chars);
3342 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3343 if (force_copy_ok && soa.ForceCopy()) {
3344 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3345 }
3346 if (force_copy_ok) {
3347 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3348 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3349 if (utf) {
3350 CHECK(!critical);
3351 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3352 } else {
3353 if (critical) {
3354 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3355 } else {
3356 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3357 }
3358 }
3359 JniValueType result;
3360 sc.Check(soa, false, "V", &result);
3361 }
3362 }
3363 }
3364
3365 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3366 Primitive::Type type) {
3367 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003368 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003369 JniValueType args[2] = {{.E = env}, {.z = length}};
3370 if (sc.Check(soa, true, "Ez", args)) {
3371 JniValueType result;
3372 switch (type) {
3373 case Primitive::kPrimBoolean:
3374 result.a = baseEnv(env)->NewBooleanArray(env, length);
3375 break;
3376 case Primitive::kPrimByte:
3377 result.a = baseEnv(env)->NewByteArray(env, length);
3378 break;
3379 case Primitive::kPrimChar:
3380 result.a = baseEnv(env)->NewCharArray(env, length);
3381 break;
3382 case Primitive::kPrimShort:
3383 result.a = baseEnv(env)->NewShortArray(env, length);
3384 break;
3385 case Primitive::kPrimInt:
3386 result.a = baseEnv(env)->NewIntArray(env, length);
3387 break;
3388 case Primitive::kPrimLong:
3389 result.a = baseEnv(env)->NewLongArray(env, length);
3390 break;
3391 case Primitive::kPrimFloat:
3392 result.a = baseEnv(env)->NewFloatArray(env, length);
3393 break;
3394 case Primitive::kPrimDouble:
3395 result.a = baseEnv(env)->NewDoubleArray(env, length);
3396 break;
3397 default:
3398 LOG(FATAL) << "Unexpected primitive type: " << type;
3399 }
3400 if (sc.Check(soa, false, "a", &result)) {
3401 return result.a;
3402 }
3403 }
3404 return nullptr;
3405 }
3406
3407 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3408 JNIEnv* env, jarray array, jboolean* is_copy) {
3409 ScopedObjectAccess soa(env);
3410 ScopedCheck sc(kFlag_Default, function_name);
3411 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3412 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3413 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003414 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003415 switch (type) {
3416 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003417 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3418 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003419 break;
3420 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003421 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003422 break;
3423 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003424 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003425 break;
3426 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003427 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003428 break;
3429 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003430 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003431 break;
3432 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003433 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003434 break;
3435 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003436 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003437 break;
3438 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003439 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003440 break;
3441 default:
3442 LOG(FATAL) << "Unexpected primitive type: " << type;
3443 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003444 if (ptr != nullptr && soa.ForceCopy()) {
3445 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003446 if (is_copy != nullptr) {
3447 *is_copy = JNI_TRUE;
3448 }
3449 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003450 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003451 if (sc.Check(soa, false, "p", &result)) {
3452 return const_cast<void*>(result.p);
3453 }
3454 }
3455 return nullptr;
3456 }
3457
3458 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3459 JNIEnv* env, jarray array, void* elems, jint mode) {
3460 ScopedObjectAccess soa(env);
3461 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3462 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3463 if (soa.ForceCopy()) {
3464 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3465 }
3466 if (!soa.ForceCopy() || elems != nullptr) {
3467 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3468 if (sc.Check(soa, true, "Eapr", args)) {
3469 switch (type) {
3470 case Primitive::kPrimBoolean:
3471 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3472 reinterpret_cast<jboolean*>(elems), mode);
3473 break;
3474 case Primitive::kPrimByte:
3475 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3476 reinterpret_cast<jbyte*>(elems), mode);
3477 break;
3478 case Primitive::kPrimChar:
3479 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3480 reinterpret_cast<jchar*>(elems), mode);
3481 break;
3482 case Primitive::kPrimShort:
3483 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3484 reinterpret_cast<jshort*>(elems), mode);
3485 break;
3486 case Primitive::kPrimInt:
3487 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3488 reinterpret_cast<jint*>(elems), mode);
3489 break;
3490 case Primitive::kPrimLong:
3491 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3492 reinterpret_cast<jlong*>(elems), mode);
3493 break;
3494 case Primitive::kPrimFloat:
3495 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3496 reinterpret_cast<jfloat*>(elems), mode);
3497 break;
3498 case Primitive::kPrimDouble:
3499 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3500 reinterpret_cast<jdouble*>(elems), mode);
3501 break;
3502 default:
3503 LOG(FATAL) << "Unexpected primitive type: " << type;
3504 }
3505 JniValueType result;
3506 result.V = nullptr;
3507 sc.Check(soa, false, "V", &result);
3508 }
3509 }
3510 }
3511 }
3512
3513 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3514 jarray array, jsize start, jsize len, void* buf) {
3515 ScopedObjectAccess soa(env);
3516 ScopedCheck sc(kFlag_Default, function_name);
3517 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3518 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3519 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3520 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3521 switch (type) {
3522 case Primitive::kPrimBoolean:
3523 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3524 reinterpret_cast<jboolean*>(buf));
3525 break;
3526 case Primitive::kPrimByte:
3527 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3528 reinterpret_cast<jbyte*>(buf));
3529 break;
3530 case Primitive::kPrimChar:
3531 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3532 reinterpret_cast<jchar*>(buf));
3533 break;
3534 case Primitive::kPrimShort:
3535 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3536 reinterpret_cast<jshort*>(buf));
3537 break;
3538 case Primitive::kPrimInt:
3539 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3540 reinterpret_cast<jint*>(buf));
3541 break;
3542 case Primitive::kPrimLong:
3543 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3544 reinterpret_cast<jlong*>(buf));
3545 break;
3546 case Primitive::kPrimFloat:
3547 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3548 reinterpret_cast<jfloat*>(buf));
3549 break;
3550 case Primitive::kPrimDouble:
3551 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3552 reinterpret_cast<jdouble*>(buf));
3553 break;
3554 default:
3555 LOG(FATAL) << "Unexpected primitive type: " << type;
3556 }
3557 JniValueType result;
3558 result.V = nullptr;
3559 sc.Check(soa, false, "V", &result);
3560 }
3561 }
3562
3563 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3564 jarray array, jsize start, jsize len, const void* buf) {
3565 ScopedObjectAccess soa(env);
3566 ScopedCheck sc(kFlag_Default, function_name);
3567 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3568 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3569 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3570 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3571 switch (type) {
3572 case Primitive::kPrimBoolean:
3573 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3574 reinterpret_cast<const jboolean*>(buf));
3575 break;
3576 case Primitive::kPrimByte:
3577 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3578 reinterpret_cast<const jbyte*>(buf));
3579 break;
3580 case Primitive::kPrimChar:
3581 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3582 reinterpret_cast<const jchar*>(buf));
3583 break;
3584 case Primitive::kPrimShort:
3585 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3586 reinterpret_cast<const jshort*>(buf));
3587 break;
3588 case Primitive::kPrimInt:
3589 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3590 reinterpret_cast<const jint*>(buf));
3591 break;
3592 case Primitive::kPrimLong:
3593 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3594 reinterpret_cast<const jlong*>(buf));
3595 break;
3596 case Primitive::kPrimFloat:
3597 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3598 reinterpret_cast<const jfloat*>(buf));
3599 break;
3600 case Primitive::kPrimDouble:
3601 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3602 reinterpret_cast<const jdouble*>(buf));
3603 break;
3604 default:
3605 LOG(FATAL) << "Unexpected primitive type: " << type;
3606 }
3607 JniValueType result;
3608 result.V = nullptr;
3609 sc.Check(soa, false, "V", &result);
3610 }
3611 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003612};
3613
3614const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003615 nullptr, // reserved0.
3616 nullptr, // reserved1.
3617 nullptr, // reserved2.
3618 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003619 CheckJNI::GetVersion,
3620 CheckJNI::DefineClass,
3621 CheckJNI::FindClass,
3622 CheckJNI::FromReflectedMethod,
3623 CheckJNI::FromReflectedField,
3624 CheckJNI::ToReflectedMethod,
3625 CheckJNI::GetSuperclass,
3626 CheckJNI::IsAssignableFrom,
3627 CheckJNI::ToReflectedField,
3628 CheckJNI::Throw,
3629 CheckJNI::ThrowNew,
3630 CheckJNI::ExceptionOccurred,
3631 CheckJNI::ExceptionDescribe,
3632 CheckJNI::ExceptionClear,
3633 CheckJNI::FatalError,
3634 CheckJNI::PushLocalFrame,
3635 CheckJNI::PopLocalFrame,
3636 CheckJNI::NewGlobalRef,
3637 CheckJNI::DeleteGlobalRef,
3638 CheckJNI::DeleteLocalRef,
3639 CheckJNI::IsSameObject,
3640 CheckJNI::NewLocalRef,
3641 CheckJNI::EnsureLocalCapacity,
3642 CheckJNI::AllocObject,
3643 CheckJNI::NewObject,
3644 CheckJNI::NewObjectV,
3645 CheckJNI::NewObjectA,
3646 CheckJNI::GetObjectClass,
3647 CheckJNI::IsInstanceOf,
3648 CheckJNI::GetMethodID,
3649 CheckJNI::CallObjectMethod,
3650 CheckJNI::CallObjectMethodV,
3651 CheckJNI::CallObjectMethodA,
3652 CheckJNI::CallBooleanMethod,
3653 CheckJNI::CallBooleanMethodV,
3654 CheckJNI::CallBooleanMethodA,
3655 CheckJNI::CallByteMethod,
3656 CheckJNI::CallByteMethodV,
3657 CheckJNI::CallByteMethodA,
3658 CheckJNI::CallCharMethod,
3659 CheckJNI::CallCharMethodV,
3660 CheckJNI::CallCharMethodA,
3661 CheckJNI::CallShortMethod,
3662 CheckJNI::CallShortMethodV,
3663 CheckJNI::CallShortMethodA,
3664 CheckJNI::CallIntMethod,
3665 CheckJNI::CallIntMethodV,
3666 CheckJNI::CallIntMethodA,
3667 CheckJNI::CallLongMethod,
3668 CheckJNI::CallLongMethodV,
3669 CheckJNI::CallLongMethodA,
3670 CheckJNI::CallFloatMethod,
3671 CheckJNI::CallFloatMethodV,
3672 CheckJNI::CallFloatMethodA,
3673 CheckJNI::CallDoubleMethod,
3674 CheckJNI::CallDoubleMethodV,
3675 CheckJNI::CallDoubleMethodA,
3676 CheckJNI::CallVoidMethod,
3677 CheckJNI::CallVoidMethodV,
3678 CheckJNI::CallVoidMethodA,
3679 CheckJNI::CallNonvirtualObjectMethod,
3680 CheckJNI::CallNonvirtualObjectMethodV,
3681 CheckJNI::CallNonvirtualObjectMethodA,
3682 CheckJNI::CallNonvirtualBooleanMethod,
3683 CheckJNI::CallNonvirtualBooleanMethodV,
3684 CheckJNI::CallNonvirtualBooleanMethodA,
3685 CheckJNI::CallNonvirtualByteMethod,
3686 CheckJNI::CallNonvirtualByteMethodV,
3687 CheckJNI::CallNonvirtualByteMethodA,
3688 CheckJNI::CallNonvirtualCharMethod,
3689 CheckJNI::CallNonvirtualCharMethodV,
3690 CheckJNI::CallNonvirtualCharMethodA,
3691 CheckJNI::CallNonvirtualShortMethod,
3692 CheckJNI::CallNonvirtualShortMethodV,
3693 CheckJNI::CallNonvirtualShortMethodA,
3694 CheckJNI::CallNonvirtualIntMethod,
3695 CheckJNI::CallNonvirtualIntMethodV,
3696 CheckJNI::CallNonvirtualIntMethodA,
3697 CheckJNI::CallNonvirtualLongMethod,
3698 CheckJNI::CallNonvirtualLongMethodV,
3699 CheckJNI::CallNonvirtualLongMethodA,
3700 CheckJNI::CallNonvirtualFloatMethod,
3701 CheckJNI::CallNonvirtualFloatMethodV,
3702 CheckJNI::CallNonvirtualFloatMethodA,
3703 CheckJNI::CallNonvirtualDoubleMethod,
3704 CheckJNI::CallNonvirtualDoubleMethodV,
3705 CheckJNI::CallNonvirtualDoubleMethodA,
3706 CheckJNI::CallNonvirtualVoidMethod,
3707 CheckJNI::CallNonvirtualVoidMethodV,
3708 CheckJNI::CallNonvirtualVoidMethodA,
3709 CheckJNI::GetFieldID,
3710 CheckJNI::GetObjectField,
3711 CheckJNI::GetBooleanField,
3712 CheckJNI::GetByteField,
3713 CheckJNI::GetCharField,
3714 CheckJNI::GetShortField,
3715 CheckJNI::GetIntField,
3716 CheckJNI::GetLongField,
3717 CheckJNI::GetFloatField,
3718 CheckJNI::GetDoubleField,
3719 CheckJNI::SetObjectField,
3720 CheckJNI::SetBooleanField,
3721 CheckJNI::SetByteField,
3722 CheckJNI::SetCharField,
3723 CheckJNI::SetShortField,
3724 CheckJNI::SetIntField,
3725 CheckJNI::SetLongField,
3726 CheckJNI::SetFloatField,
3727 CheckJNI::SetDoubleField,
3728 CheckJNI::GetStaticMethodID,
3729 CheckJNI::CallStaticObjectMethod,
3730 CheckJNI::CallStaticObjectMethodV,
3731 CheckJNI::CallStaticObjectMethodA,
3732 CheckJNI::CallStaticBooleanMethod,
3733 CheckJNI::CallStaticBooleanMethodV,
3734 CheckJNI::CallStaticBooleanMethodA,
3735 CheckJNI::CallStaticByteMethod,
3736 CheckJNI::CallStaticByteMethodV,
3737 CheckJNI::CallStaticByteMethodA,
3738 CheckJNI::CallStaticCharMethod,
3739 CheckJNI::CallStaticCharMethodV,
3740 CheckJNI::CallStaticCharMethodA,
3741 CheckJNI::CallStaticShortMethod,
3742 CheckJNI::CallStaticShortMethodV,
3743 CheckJNI::CallStaticShortMethodA,
3744 CheckJNI::CallStaticIntMethod,
3745 CheckJNI::CallStaticIntMethodV,
3746 CheckJNI::CallStaticIntMethodA,
3747 CheckJNI::CallStaticLongMethod,
3748 CheckJNI::CallStaticLongMethodV,
3749 CheckJNI::CallStaticLongMethodA,
3750 CheckJNI::CallStaticFloatMethod,
3751 CheckJNI::CallStaticFloatMethodV,
3752 CheckJNI::CallStaticFloatMethodA,
3753 CheckJNI::CallStaticDoubleMethod,
3754 CheckJNI::CallStaticDoubleMethodV,
3755 CheckJNI::CallStaticDoubleMethodA,
3756 CheckJNI::CallStaticVoidMethod,
3757 CheckJNI::CallStaticVoidMethodV,
3758 CheckJNI::CallStaticVoidMethodA,
3759 CheckJNI::GetStaticFieldID,
3760 CheckJNI::GetStaticObjectField,
3761 CheckJNI::GetStaticBooleanField,
3762 CheckJNI::GetStaticByteField,
3763 CheckJNI::GetStaticCharField,
3764 CheckJNI::GetStaticShortField,
3765 CheckJNI::GetStaticIntField,
3766 CheckJNI::GetStaticLongField,
3767 CheckJNI::GetStaticFloatField,
3768 CheckJNI::GetStaticDoubleField,
3769 CheckJNI::SetStaticObjectField,
3770 CheckJNI::SetStaticBooleanField,
3771 CheckJNI::SetStaticByteField,
3772 CheckJNI::SetStaticCharField,
3773 CheckJNI::SetStaticShortField,
3774 CheckJNI::SetStaticIntField,
3775 CheckJNI::SetStaticLongField,
3776 CheckJNI::SetStaticFloatField,
3777 CheckJNI::SetStaticDoubleField,
3778 CheckJNI::NewString,
3779 CheckJNI::GetStringLength,
3780 CheckJNI::GetStringChars,
3781 CheckJNI::ReleaseStringChars,
3782 CheckJNI::NewStringUTF,
3783 CheckJNI::GetStringUTFLength,
3784 CheckJNI::GetStringUTFChars,
3785 CheckJNI::ReleaseStringUTFChars,
3786 CheckJNI::GetArrayLength,
3787 CheckJNI::NewObjectArray,
3788 CheckJNI::GetObjectArrayElement,
3789 CheckJNI::SetObjectArrayElement,
3790 CheckJNI::NewBooleanArray,
3791 CheckJNI::NewByteArray,
3792 CheckJNI::NewCharArray,
3793 CheckJNI::NewShortArray,
3794 CheckJNI::NewIntArray,
3795 CheckJNI::NewLongArray,
3796 CheckJNI::NewFloatArray,
3797 CheckJNI::NewDoubleArray,
3798 CheckJNI::GetBooleanArrayElements,
3799 CheckJNI::GetByteArrayElements,
3800 CheckJNI::GetCharArrayElements,
3801 CheckJNI::GetShortArrayElements,
3802 CheckJNI::GetIntArrayElements,
3803 CheckJNI::GetLongArrayElements,
3804 CheckJNI::GetFloatArrayElements,
3805 CheckJNI::GetDoubleArrayElements,
3806 CheckJNI::ReleaseBooleanArrayElements,
3807 CheckJNI::ReleaseByteArrayElements,
3808 CheckJNI::ReleaseCharArrayElements,
3809 CheckJNI::ReleaseShortArrayElements,
3810 CheckJNI::ReleaseIntArrayElements,
3811 CheckJNI::ReleaseLongArrayElements,
3812 CheckJNI::ReleaseFloatArrayElements,
3813 CheckJNI::ReleaseDoubleArrayElements,
3814 CheckJNI::GetBooleanArrayRegion,
3815 CheckJNI::GetByteArrayRegion,
3816 CheckJNI::GetCharArrayRegion,
3817 CheckJNI::GetShortArrayRegion,
3818 CheckJNI::GetIntArrayRegion,
3819 CheckJNI::GetLongArrayRegion,
3820 CheckJNI::GetFloatArrayRegion,
3821 CheckJNI::GetDoubleArrayRegion,
3822 CheckJNI::SetBooleanArrayRegion,
3823 CheckJNI::SetByteArrayRegion,
3824 CheckJNI::SetCharArrayRegion,
3825 CheckJNI::SetShortArrayRegion,
3826 CheckJNI::SetIntArrayRegion,
3827 CheckJNI::SetLongArrayRegion,
3828 CheckJNI::SetFloatArrayRegion,
3829 CheckJNI::SetDoubleArrayRegion,
3830 CheckJNI::RegisterNatives,
3831 CheckJNI::UnregisterNatives,
3832 CheckJNI::MonitorEnter,
3833 CheckJNI::MonitorExit,
3834 CheckJNI::GetJavaVM,
3835 CheckJNI::GetStringRegion,
3836 CheckJNI::GetStringUTFRegion,
3837 CheckJNI::GetPrimitiveArrayCritical,
3838 CheckJNI::ReleasePrimitiveArrayCritical,
3839 CheckJNI::GetStringCritical,
3840 CheckJNI::ReleaseStringCritical,
3841 CheckJNI::NewWeakGlobalRef,
3842 CheckJNI::DeleteWeakGlobalRef,
3843 CheckJNI::ExceptionCheck,
3844 CheckJNI::NewDirectByteBuffer,
3845 CheckJNI::GetDirectBufferAddress,
3846 CheckJNI::GetDirectBufferCapacity,
3847 CheckJNI::GetObjectRefType,
3848};
3849
3850const JNINativeInterface* GetCheckJniNativeInterface() {
3851 return &gCheckNativeInterface;
3852}
3853
3854class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003855 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003856 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003857 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3858 JniValueType args[1] = {{.v = vm}};
3859 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3860 JniValueType result;
3861 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003862 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3863 // which will delete the JavaVMExt.
3864 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003865 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003866 }
3867
3868 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003869 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3870 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3871 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3872 JniValueType result;
3873 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3874 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3875 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003876 }
3877
3878 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003879 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3880 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3881 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3882 JniValueType result;
3883 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3884 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3885 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003886 }
3887
3888 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003889 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3890 JniValueType args[1] = {{.v = vm}};
3891 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3892 JniValueType result;
3893 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3894 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3895 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003896 }
3897
Ian Rogers68d8b422014-07-17 11:09:10 -07003898 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3899 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3900 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3901 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3902 JniValueType result;
3903 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3904 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3905 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003906 }
3907
3908 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003909 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3910 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003911 }
3912};
3913
3914const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003915 nullptr, // reserved0
3916 nullptr, // reserved1
3917 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003918 CheckJII::DestroyJavaVM,
3919 CheckJII::AttachCurrentThread,
3920 CheckJII::DetachCurrentThread,
3921 CheckJII::GetEnv,
3922 CheckJII::AttachCurrentThreadAsDaemon
3923};
3924
3925const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3926 return &gCheckInvokeInterface;
3927}
3928
3929} // namespace art