blob: 1c3328e484e04b111482d9f0b676571e7f862864 [file] [log] [blame]
Elliott Hughesa2501992011-08-26 19:39:54 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "check_jni.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070018
Andreas Gampeef4afe92015-07-27 21:03:25 -070019#include <iomanip>
Elliott Hughesa2501992011-08-26 19:39:54 -070020#include <sys/mman.h>
21#include <zlib.h>
22
Andreas Gampe46ee31b2016-12-14 10:11:49 -080023#include "android-base/stringprintf.h"
24
Mathieu Chartierc7853442015-03-27 14:35:38 -070025#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070026#include "art_method-inl.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080027#include "base/logging.h"
Ian Rogersc7dd2952014-10-21 23:31:19 -070028#include "base/to_str.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070029#include "class_linker.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070031#include "dex_file-inl.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070032#include "gc/space/space.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070033#include "java_vm_ext.h"
Andreas Gampe277ccbd2014-11-03 21:36:10 -080034#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080035#include "mirror/class-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/object-inl.h"
37#include "mirror/object_array-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070038#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080039#include "mirror/throwable.h"
Jeff Hao58df3272013-04-22 15:28:53 -070040#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070041#include "scoped_thread_state_change-inl.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070042#include "thread.h"
Ian Rogers68d8b422014-07-17 11:09:10 -070043#include "well_known_classes.h"
Elliott Hughesa2501992011-08-26 19:39:54 -070044
45namespace art {
46
Andreas Gampe46ee31b2016-12-14 10:11:49 -080047using android::base::StringAppendF;
48using android::base::StringPrintf;
49
Elliott Hughesa2501992011-08-26 19:39:54 -070050/*
51 * ===========================================================================
52 * JNI function helpers
53 * ===========================================================================
54 */
55
Elliott Hughes3f6635a2012-06-19 13:37:49 -070056// Flags passed into ScopedCheck.
Elliott Hughesa2501992011-08-26 19:39:54 -070057#define kFlag_Default 0x0000
58
Elliott Hughes3f6635a2012-06-19 13:37:49 -070059#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
60#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
61#define kFlag_CritGet 0x0002 // This is a critical "get".
62#define kFlag_CritRelease 0x0003 // This is a critical "release".
63#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
Elliott Hughesa2501992011-08-26 19:39:54 -070064
Elliott Hughes3f6635a2012-06-19 13:37:49 -070065#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
66#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
Elliott Hughesa2501992011-08-26 19:39:54 -070067
Elliott Hughes3f6635a2012-06-19 13:37:49 -070068#define kFlag_Release 0x0010 // Are we in a non-critical release function?
69#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
Elliott Hughesa2501992011-08-26 19:39:54 -070070
Elliott Hughes3f6635a2012-06-19 13:37:49 -070071#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
Elliott Hughesa2501992011-08-26 19:39:54 -070072
Elliott Hughes485cac42011-12-09 17:49:35 -080073#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
Alex Light48ffe062015-08-19 15:23:23 -070074
75class VarArgs;
Ian Rogers68d8b422014-07-17 11:09:10 -070076/*
77 * Java primitive types:
78 * B - jbyte
79 * C - jchar
80 * D - jdouble
81 * F - jfloat
82 * I - jint
83 * J - jlong
84 * S - jshort
85 * Z - jboolean (shown as true and false)
86 * V - void
87 *
88 * Java reference types:
89 * L - jobject
90 * a - jarray
91 * c - jclass
92 * s - jstring
93 * t - jthrowable
94 *
95 * JNI types:
96 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
97 * f - jfieldID
98 * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
99 * m - jmethodID
100 * p - void*
101 * r - jint (for release mode arguments)
102 * u - const char* (Modified UTF-8)
103 * z - jsize (for lengths; use i if negative values are okay)
104 * v - JavaVM*
105 * w - jobjectRefType
106 * E - JNIEnv*
107 * . - no argument; just print "..." (used for varargs JNI calls)
108 *
109 */
110union JniValueType {
111 jarray a;
112 jboolean b;
113 jclass c;
114 jfieldID f;
115 jint i;
116 jmethodID m;
117 const void* p; // Pointer.
118 jint r; // Release mode.
119 jstring s;
120 jthrowable t;
121 const char* u; // Modified UTF-8.
122 JavaVM* v;
123 jobjectRefType w;
124 jsize z;
125 jbyte B;
126 jchar C;
127 jdouble D;
128 JNIEnv* E;
129 jfloat F;
130 jint I;
131 jlong J;
132 jobject L;
133 jshort S;
134 const void* V; // void
135 jboolean Z;
Alex Light48ffe062015-08-19 15:23:23 -0700136 const VarArgs* va;
137};
138
139/*
140 * A structure containing all the information needed to validate varargs arguments.
141 *
142 * Note that actually getting the arguments from this structure mutates it so should only be done on
143 * owned copies.
144 */
145class VarArgs {
146 public:
147 VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
148 va_copy(vargs_, var);
149 }
150
151 VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
152
153 ~VarArgs() {
154 if (type_ == kTypeVaList) {
155 va_end(vargs_);
156 }
157 }
158
159 VarArgs(VarArgs&& other) {
160 m_ = other.m_;
161 cnt_ = other.cnt_;
162 type_ = other.type_;
163 if (other.type_ == kTypeVaList) {
164 va_copy(vargs_, other.vargs_);
165 } else {
166 ptr_ = other.ptr_;
167 }
168 }
169
170 // This method is const because we need to ensure that one only uses the GetValue method on an
171 // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
172 // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
173 // we want to use one we need to Clone() it.
174 VarArgs Clone() const {
175 if (type_ == kTypeVaList) {
176 // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
177 // messed up if the source argument is not the exact type 'va_list'.
178 return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
179 } else {
180 return VarArgs(m_, cnt_, ptr_);
181 }
182 }
183
184 jmethodID GetMethodID() const {
185 return m_;
186 }
187
188 JniValueType GetValue(char fmt) {
189 JniValueType o;
190 if (type_ == kTypeVaList) {
191 switch (fmt) {
192 case 'Z': o.Z = static_cast<jboolean>(va_arg(vargs_, jint)); break;
193 case 'B': o.B = static_cast<jbyte>(va_arg(vargs_, jint)); break;
194 case 'C': o.C = static_cast<jchar>(va_arg(vargs_, jint)); break;
195 case 'S': o.S = static_cast<jshort>(va_arg(vargs_, jint)); break;
196 case 'I': o.I = va_arg(vargs_, jint); break;
197 case 'J': o.J = va_arg(vargs_, jlong); break;
198 case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
199 case 'D': o.D = va_arg(vargs_, jdouble); break;
200 case 'L': o.L = va_arg(vargs_, jobject); break;
201 default:
202 LOG(FATAL) << "Illegal type format char " << fmt;
203 UNREACHABLE();
204 }
205 } else {
206 CHECK(type_ == kTypePtr);
207 jvalue v = ptr_[cnt_];
208 cnt_++;
209 switch (fmt) {
210 case 'Z': o.Z = v.z; break;
211 case 'B': o.B = v.b; break;
212 case 'C': o.C = v.c; break;
213 case 'S': o.S = v.s; break;
214 case 'I': o.I = v.i; break;
215 case 'J': o.J = v.j; break;
216 case 'F': o.F = v.f; break;
217 case 'D': o.D = v.d; break;
218 case 'L': o.L = v.l; break;
219 default:
220 LOG(FATAL) << "Illegal type format char " << fmt;
221 UNREACHABLE();
222 }
223 }
224 return o;
225 }
226
227 private:
228 VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
229 va_copy(vargs_, var);
230 }
231
232 VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
233
234 enum VarArgsType {
235 kTypeVaList,
236 kTypePtr,
237 };
238
239 jmethodID m_;
240 VarArgsType type_;
241 uint32_t cnt_;
242 union {
243 va_list vargs_;
244 const jvalue* ptr_;
245 };
Elliott Hughesa0957642011-09-02 14:27:33 -0700246};
247
Elliott Hughesa2501992011-08-26 19:39:54 -0700248class ScopedCheck {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800249 public:
Roland Levillain3887c462015-08-12 18:15:42 +0100250 ScopedCheck(int flags, const char* functionName, bool has_method = true)
Ian Rogers68d8b422014-07-17 11:09:10 -0700251 : function_name_(functionName), flags_(flags), indent_(0), has_method_(has_method) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700252 }
253
Ian Rogers68d8b422014-07-17 11:09:10 -0700254 ~ScopedCheck() {}
Elliott Hughesa2501992011-08-26 19:39:54 -0700255
Elliott Hughes81ff3182012-03-23 20:35:56 -0700256 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
257 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
258 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
259 // circumstances, but this is incorrect.
Ian Rogers68d8b422014-07-17 11:09:10 -0700260 bool CheckClassName(const char* class_name) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700261 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700262 AbortF("illegal class name '%s'\n"
263 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
264 class_name);
265 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700266 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700267 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700268 }
269
270 /*
271 * Verify that this instance field ID is valid for this object.
272 *
273 * Assumes "jobj" has already been validated.
274 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700275 bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700276 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700277 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Ian Rogers68d8b422014-07-17 11:09:10 -0700278 if (o == nullptr) {
279 AbortF("field operation on NULL object: %p", java_object);
280 return false;
281 }
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700282 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700283 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700284 AbortF("field operation on invalid %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700285 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700286 java_object);
287 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700288 }
289
Andreas Gampe08883de2016-11-08 13:20:52 -0800290 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800291 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700292 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700293 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800294 mirror::Class* c = o->GetClass();
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700295 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700296 AbortF("jfieldID %s not valid for an object of class %s",
David Sehr709b0702016-10-13 09:12:37 -0700297 f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700298 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700299 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700300 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700301 }
302
303 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700304 * Verify that the pointer value is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -0700305 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700306 bool CheckNonNull(const void* ptr) {
307 if (UNLIKELY(ptr == nullptr)) {
308 AbortF("non-nullable argument was NULL");
309 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700310 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700311 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700312 }
313
314 /*
315 * Verify that the method's return type matches the type of call.
316 * 'expectedType' will be "L" for all objects, including arrays.
317 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700318 bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
319 jmethodID mid, Primitive::Type type, InvokeType invoke)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700320 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800321 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800322 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700323 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700324 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700325 if (type != Primitive::GetType(m->GetShorty()[0])) {
David Sehr709b0702016-10-13 09:12:37 -0700326 AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700327 return false;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700328 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700329 bool is_static = (invoke == kStatic);
330 if (is_static != m->IsStatic()) {
331 if (is_static) {
332 AbortF("calling non-static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700333 m->PrettyMethod().c_str(), function_name_);
Elliott Hughesa2501992011-08-26 19:39:54 -0700334 } else {
Ian Rogers68d8b422014-07-17 11:09:10 -0700335 AbortF("calling static method %s with %s",
David Sehr709b0702016-10-13 09:12:37 -0700336 m->PrettyMethod().c_str(), function_name_);
Ian Rogers68d8b422014-07-17 11:09:10 -0700337 }
338 return false;
339 }
340 if (invoke != kVirtual) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700341 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700342 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700343 AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
David Sehr709b0702016-10-13 09:12:37 -0700344 m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700345 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700346 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700347 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700348 if (invoke != kStatic) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700349 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700350 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700351 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700352 return false;
353 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700354 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
355 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700356 return false;
357 }
358 }
359 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700360 }
361
362 /*
363 * Verify that this static field ID is valid for this class.
364 *
365 * Assumes "java_class" has already been validated.
366 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700367 bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700368 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700369 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Andreas Gampe08883de2016-11-08 13:20:52 -0800370 ArtField* f = CheckFieldID(fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800371 if (f == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700372 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700373 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700374 if (c != f->GetDeclaringClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700375 AbortF("static jfieldID %p not valid for class %s", fid,
376 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700377 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700378 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700379 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700380 }
381
382 /*
Elliott Hughese84278b2012-03-22 10:06:53 -0700383 * Verify that "mid" is appropriate for "java_class".
Elliott Hughesa2501992011-08-26 19:39:54 -0700384 *
385 * A mismatch isn't dangerous, because the jmethodID defines the class. In
Elliott Hughese84278b2012-03-22 10:06:53 -0700386 * fact, java_class is unused in the implementation. It's best if we don't
Elliott Hughesa2501992011-08-26 19:39:54 -0700387 * allow bad code in the system though.
388 *
Elliott Hughese84278b2012-03-22 10:06:53 -0700389 * Instances of "java_class" must be instances of the method's declaring class.
Elliott Hughesa2501992011-08-26 19:39:54 -0700390 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700391 bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700392 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800393 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800394 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700395 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700396 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700397 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700398 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
David Sehr709b0702016-10-13 09:12:37 -0700399 AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
400 mirror::Class::PrettyClass(c).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700401 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700402 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700403 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700404 }
405
406 /*
407 * Verify that "mid" is appropriate for "jobj".
408 *
409 * Make sure the object is an instance of the method's declaring class.
410 * (Note the mid might point to a declaration in an interface; this
411 * will be handled automatically by the instanceof check.)
412 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700413 bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700414 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe13b27842016-11-07 16:48:23 -0800415 ArtMethod* m = CheckMethodID(mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800416 if (m == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700417 return false;
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700418 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700419 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700420 if (o == nullptr) {
David Sehr709b0702016-10-13 09:12:37 -0700421 AbortF("can't call %s on null object", m->PrettyMethod().c_str());
Mathieu Chartiera1e78fa2014-08-20 12:09:38 -0700422 return false;
423 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
David Sehr709b0702016-10-13 09:12:37 -0700424 AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
425 o->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -0700426 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700427 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700428 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700429 }
430
431 /**
432 * The format string is a sequence of the following characters,
433 * and must be followed by arguments of the corresponding types
434 * in the same order.
435 *
436 * Java primitive types:
437 * B - jbyte
438 * C - jchar
439 * D - jdouble
440 * F - jfloat
441 * I - jint
442 * J - jlong
443 * S - jshort
444 * Z - jboolean (shown as true and false)
445 * V - void
446 *
447 * Java reference types:
448 * L - jobject
449 * a - jarray
450 * c - jclass
451 * s - jstring
452 *
453 * JNI types:
454 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
455 * f - jfieldID
456 * m - jmethodID
457 * p - void*
458 * r - jint (for release mode arguments)
Elliott Hughes78090d12011-10-07 14:31:47 -0700459 * u - const char* (Modified UTF-8)
Elliott Hughesa2501992011-08-26 19:39:54 -0700460 * z - jsize (for lengths; use i if negative values are okay)
461 * v - JavaVM*
462 * E - JNIEnv*
Alex Light48ffe062015-08-19 15:23:23 -0700463 * . - VarArgs* for Jni calls with variable length arguments
Elliott Hughesa2501992011-08-26 19:39:54 -0700464 *
465 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
466 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700467 bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700468 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700469 ArtMethod* traceMethod = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700470 if (has_method_ && soa.Vm()->IsTracingEnabled()) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700471 // We need to guard some of the invocation interface's calls: a bad caller might
472 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
Elliott Hughesa0957642011-09-02 14:27:33 -0700473 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -0800474 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
475 traceMethod = self->GetCurrentMethod(nullptr);
Elliott Hughesa2501992011-08-26 19:39:54 -0700476 }
477 }
Elliott Hughesa0957642011-09-02 14:27:33 -0700478
Ian Rogersef7d42f2014-01-06 12:55:46 -0800479 if (((flags_ & kFlag_ForceTrace) != 0) ||
Ian Rogers68d8b422014-07-17 11:09:10 -0700480 (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700481 std::string msg;
Ian Rogers68d8b422014-07-17 11:09:10 -0700482 for (size_t i = 0; fmt[i] != '\0'; ++i) {
483 TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
484 if (fmt[i + 1] != '\0') {
Elliott Hughesa2501992011-08-26 19:39:54 -0700485 StringAppendF(&msg, ", ");
486 }
487 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700488
Elliott Hughes485cac42011-12-09 17:49:35 -0800489 if ((flags_ & kFlag_ForceTrace) != 0) {
490 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
491 } else if (entry) {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700492 if (has_method_) {
David Sehr709b0702016-10-13 09:12:37 -0700493 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700494 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
495 indent_ = methodName.size() + 1;
Elliott Hughesa2501992011-08-26 19:39:54 -0700496 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700497 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
498 indent_ = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700499 }
500 } else {
Elliott Hughes32ae6e32011-09-27 10:46:50 -0700501 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
Elliott Hughesa2501992011-08-26 19:39:54 -0700502 }
503 }
504
505 // We always do the thorough checks on entry, and never on exit...
506 if (entry) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700507 for (size_t i = 0; fmt[i] != '\0'; ++i) {
508 if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
509 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -0700510 }
511 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700512 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700513 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700514 }
515
Ian Rogers68d8b422014-07-17 11:09:10 -0700516 bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
517 bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
Andreas Gampedef194e2015-02-19 15:19:50 -0800518 if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700519 // We need to guard some of the invocation interface's calls: a bad caller might
520 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
521 Thread* self = Thread::Current();
522 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
523 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700524 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
Ian Rogers68d8b422014-07-17 11:09:10 -0700525 should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
526 }
527 }
528 if (should_trace) {
529 std::string msg;
530 for (size_t i = 0; fmt[i] != '\0'; ++i) {
531 TraceNonHeapValue(fmt[i], args[i], &msg);
532 if (fmt[i + 1] != '\0') {
533 StringAppendF(&msg, ", ");
534 }
535 }
536
537 if ((flags_ & kFlag_ForceTrace) != 0) {
538 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
539 } else if (entry) {
540 if (has_method_) {
541 Thread* self = Thread::Current();
542 ScopedObjectAccess soa(self);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700543 ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
David Sehr709b0702016-10-13 09:12:37 -0700544 std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
Ian Rogers68d8b422014-07-17 11:09:10 -0700545 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
546 indent_ = methodName.size() + 1;
547 } else {
548 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
549 indent_ = 0;
550 }
551 } else {
552 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
553 }
554 }
555
556 // We always do the thorough checks on entry, and never on exit...
557 if (entry) {
558 for (size_t i = 0; fmt[i] != '\0'; ++i) {
559 if (!CheckNonHeapValue(fmt[i], args[i])) {
560 return false;
561 }
562 }
563 }
564 return true;
565 }
566
567 bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700568 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700569 ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700570 if (method == nullptr) {
571 AbortF("expected non-null method");
572 return false;
573 }
574 mirror::Class* c = method->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700575 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Method) != c &&
576 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Constructor) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700577 AbortF("expected java.lang.reflect.Method or "
578 "java.lang.reflect.Constructor but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700579 method->PrettyTypeOf().c_str(), jmethod);
Ian Rogers68d8b422014-07-17 11:09:10 -0700580 return false;
581 }
582 return true;
583 }
584
Andreas Gampe13b27842016-11-07 16:48:23 -0800585 bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
586 ArtMethod* method = jni::DecodeArtMethod(mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700587 if (method == nullptr) {
588 AbortF("expected non-null constructor");
589 return false;
590 }
591 if (!method->IsConstructor() || method->IsStatic()) {
David Sehr709b0702016-10-13 09:12:37 -0700592 AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700593 return false;
594 }
595 return true;
596 }
597
598 bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700599 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700600 ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700601 if (field == nullptr) {
602 AbortF("expected non-null java.lang.reflect.Field");
603 return false;
604 }
605 mirror::Class* c = field->GetClass();
Mathieu Chartier0795f232016-09-27 18:43:30 -0700606 if (soa.Decode<mirror::Class>(WellKnownClasses::java_lang_reflect_Field) != c) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700607 AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700608 field->PrettyTypeOf().c_str(), jfield);
Ian Rogers68d8b422014-07-17 11:09:10 -0700609 return false;
610 }
611 return true;
612 }
613
614 bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700615 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700616 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700617 if (!obj->GetClass()->IsThrowableClass()) {
618 AbortF("expected java.lang.Throwable but got object of type "
David Sehr709b0702016-10-13 09:12:37 -0700619 "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700620 return false;
621 }
622 return true;
623 }
624
625 bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700626 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700627 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700628 if (!c->IsThrowableClass()) {
629 AbortF("expected java.lang.Throwable class but got object of "
David Sehr709b0702016-10-13 09:12:37 -0700630 "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700631 return false;
632 }
633 return true;
634 }
635
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700636 bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700637 IndirectRefKind found_kind;
638 if (expected_kind == kLocal) {
Andreas Gampedc061d02016-10-24 13:19:37 -0700639 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700640 if (found_kind == kHandleScopeOrInvalid && self->HandleScopeContains(obj)) {
641 found_kind = kLocal;
642 }
643 } else {
Andreas Gampedc061d02016-10-24 13:19:37 -0700644 found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700645 }
646 if (obj != nullptr && found_kind != expected_kind) {
647 AbortF("expected reference of kind %s but found %s: %p",
Andreas Gampedc061d02016-10-24 13:19:37 -0700648 GetIndirectRefKindString(expected_kind),
649 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
Ian Rogers68d8b422014-07-17 11:09:10 -0700650 obj);
651 return false;
652 }
653 return true;
654 }
655
656 bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700657 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700658 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700659 if (!c->IsInstantiableNonArray()) {
David Sehr709b0702016-10-13 09:12:37 -0700660 AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -0700661 return false;
662 }
663 return true;
664 }
665
666 bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700667 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700668 if (!CheckArray(soa, array)) {
669 return false;
670 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700671 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700672 if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
673 AbortF("incompatible array type %s expected %s[]: %p",
David Sehr709b0702016-10-13 09:12:37 -0700674 a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
Ian Rogers68d8b422014-07-17 11:09:10 -0700675 return false;
676 }
677 return true;
678 }
679
680 bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
681 Primitive::Type type)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700682 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700683 if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
684 return false;
685 }
686 if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
687 return false;
688 }
Andreas Gampe08883de2016-11-08 13:20:52 -0800689 ArtField* field = jni::DecodeArtField(fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700690 DCHECK(field != nullptr); // Already checked by Check.
691 if (is_static != field->IsStatic()) {
692 AbortF("attempt to access %s field %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700693 field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700694 return false;
695 }
696 if (type != field->GetTypeAsPrimitiveType()) {
697 AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700698 field->PrettyField().c_str(),
699 PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
Ian Rogers68d8b422014-07-17 11:09:10 -0700700 PrettyDescriptor(type).c_str(), fid);
701 return false;
702 }
703 if (is_static) {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700704 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700705 if (o == nullptr || !o->IsClass()) {
706 AbortF("attempt to access static field %s with a class argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700707 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700708 return false;
709 }
Mathieu Chartier0795f232016-09-27 18:43:30 -0700710 ObjPtr<mirror::Class> c = o->AsClass();
711 if (c != field->GetDeclaringClass()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700712 AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700713 field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700714 return false;
715 }
716 } else {
Mathieu Chartier0795f232016-09-27 18:43:30 -0700717 ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
Ian Rogers68d8b422014-07-17 11:09:10 -0700718 if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
719 AbortF("attempt to access field %s from an object argument of type %s: %p",
David Sehr709b0702016-10-13 09:12:37 -0700720 field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
Ian Rogers68d8b422014-07-17 11:09:10 -0700721 return false;
722 }
723 }
724 return true;
725 }
726
727 private:
Elliott Hughesa92853e2012-02-07 16:09:27 -0800728 enum InstanceKind {
729 kClass,
Elliott Hughes0f3c5532012-03-30 14:51:51 -0700730 kDirectByteBuffer,
731 kObject,
732 kString,
733 kThrowable,
Elliott Hughesa92853e2012-02-07 16:09:27 -0800734 };
735
736 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700737 * Verify that "jobj" is a valid non-null object reference, and points to
Elliott Hughesa92853e2012-02-07 16:09:27 -0800738 * an instance of expectedClass.
739 *
740 * Because we're looking at an object on the GC heap, we have to switch
741 * to "running" mode before doing the checks.
742 */
Ian Rogers68d8b422014-07-17 11:09:10 -0700743 bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700744 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800745 const char* what = nullptr;
Elliott Hughesa92853e2012-02-07 16:09:27 -0800746 switch (kind) {
747 case kClass:
748 what = "jclass";
749 break;
750 case kDirectByteBuffer:
751 what = "direct ByteBuffer";
752 break;
753 case kObject:
754 what = "jobject";
755 break;
756 case kString:
757 what = "jstring";
758 break;
759 case kThrowable:
760 what = "jthrowable";
761 break;
762 default:
Elliott Hughes7b9d9962012-04-20 18:48:18 -0700763 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
Elliott Hughesa92853e2012-02-07 16:09:27 -0800764 }
765
Ian Rogersef7d42f2014-01-06 12:55:46 -0800766 if (java_object == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700767 if (null_ok) {
768 return true;
769 } else {
770 AbortF("%s received NULL %s", function_name_, what);
771 return false;
772 }
Elliott Hughesa92853e2012-02-07 16:09:27 -0800773 }
774
Mathieu Chartier0795f232016-09-27 18:43:30 -0700775 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(java_object);
Ian Rogersc0542af2014-09-03 16:16:56 -0700776 if (obj == nullptr) {
777 // Either java_object is invalid or is a cleared weak.
778 IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
779 bool okay;
Andreas Gampedc061d02016-10-24 13:19:37 -0700780 if (IndirectReferenceTable::GetIndirectRefKind(ref) != kWeakGlobal) {
Ian Rogersc0542af2014-09-03 16:16:56 -0700781 okay = false;
782 } else {
783 obj = soa.Vm()->DecodeWeakGlobal(soa.Self(), ref);
Mathieu Chartierc4f39252016-10-05 18:32:08 -0700784 okay = Runtime::Current()->IsClearedJniWeakGlobal(obj);
Ian Rogersc0542af2014-09-03 16:16:56 -0700785 }
786 if (!okay) {
787 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700788 what,
789 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
790 java_object,
791 obj.Ptr());
Ian Rogersc0542af2014-09-03 16:16:56 -0700792 return false;
793 }
794 }
795
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700796 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -0700797 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -0700798 AbortF("%s is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -0700799 what,
800 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
801 java_object,
802 obj.Ptr());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800803 return false;
804 }
805
806 bool okay = true;
807 switch (kind) {
808 case kClass:
809 okay = obj->IsClass();
810 break;
811 case kDirectByteBuffer:
812 UNIMPLEMENTED(FATAL);
813 break;
814 case kString:
815 okay = obj->GetClass()->IsStringClass();
816 break;
817 case kThrowable:
818 okay = obj->GetClass()->IsThrowableClass();
819 break;
820 case kObject:
821 break;
822 }
823 if (!okay) {
David Sehr709b0702016-10-13 09:12:37 -0700824 AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
Elliott Hughesa92853e2012-02-07 16:09:27 -0800825 return false;
826 }
827
828 return true;
829 }
830
Ian Rogers68d8b422014-07-17 11:09:10 -0700831 /*
832 * Verify that the "mode" argument passed to a primitive array Release
833 * function is one of the valid values.
834 */
835 bool CheckReleaseMode(jint mode) {
836 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
837 AbortF("unknown value for release mode: %d", mode);
838 return false;
839 }
840 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -0700841 }
842
Ian Rogers68d8b422014-07-17 11:09:10 -0700843 bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700844 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700845 switch (fmt) {
846 case 'a': // jarray
847 return CheckArray(soa, arg.a);
848 case 'c': // jclass
849 return CheckInstance(soa, kClass, arg.c, false);
850 case 'f': // jfieldID
Andreas Gampe08883de2016-11-08 13:20:52 -0800851 return CheckFieldID(arg.f) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700852 case 'm': // jmethodID
Andreas Gampe13b27842016-11-07 16:48:23 -0800853 return CheckMethodID(arg.m) != nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -0700854 case 'r': // release int
855 return CheckReleaseMode(arg.r);
856 case 's': // jstring
857 return CheckInstance(soa, kString, arg.s, false);
858 case 't': // jthrowable
859 return CheckInstance(soa, kThrowable, arg.t, false);
860 case 'E': // JNIEnv*
861 return CheckThread(arg.E);
862 case 'L': // jobject
863 return CheckInstance(soa, kObject, arg.L, true);
Alex Light48ffe062015-08-19 15:23:23 -0700864 case '.': // A VarArgs list
865 return CheckVarArgs(soa, arg.va);
Ian Rogers68d8b422014-07-17 11:09:10 -0700866 default:
867 return CheckNonHeapValue(fmt, arg);
868 }
869 }
870
Alex Light48ffe062015-08-19 15:23:23 -0700871 bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700872 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light48ffe062015-08-19 15:23:23 -0700873 CHECK(args_p != nullptr);
874 VarArgs args(args_p->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800875 ArtMethod* m = CheckMethodID(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700876 if (m == nullptr) {
877 return false;
878 }
879 uint32_t len = 0;
880 const char* shorty = m->GetShorty(&len);
881 // Skip the return type
882 CHECK_GE(len, 1u);
883 len--;
884 shorty++;
885 for (uint32_t i = 0; i < len; i++) {
886 if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
887 return false;
888 }
889 }
890 return true;
891 }
892
Ian Rogers68d8b422014-07-17 11:09:10 -0700893 bool CheckNonHeapValue(char fmt, JniValueType arg) {
894 switch (fmt) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700895 case 'p': // TODO: pointer - null or readable?
896 case 'v': // JavaVM*
897 case 'B': // jbyte
898 case 'C': // jchar
899 case 'D': // jdouble
900 case 'F': // jfloat
901 case 'I': // jint
902 case 'J': // jlong
903 case 'S': // jshort
904 break; // Ignored.
905 case 'b': // jboolean, why two? Fall-through.
906 case 'Z':
907 return CheckBoolean(arg.Z);
908 case 'u': // utf8
909 if ((flags_ & kFlag_Release) != 0) {
910 return CheckNonNull(arg.u);
911 } else {
912 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
913 return CheckUtfString(arg.u, nullable);
914 }
915 case 'w': // jobjectRefType
916 switch (arg.w) {
917 case JNIInvalidRefType:
918 case JNILocalRefType:
919 case JNIGlobalRefType:
920 case JNIWeakGlobalRefType:
921 break;
922 default:
923 AbortF("Unknown reference type");
924 return false;
925 }
926 break;
927 case 'z': // jsize
928 return CheckLengthPositive(arg.z);
929 default:
930 AbortF("unknown format specifier: '%c'", fmt);
931 return false;
932 }
933 return true;
934 }
935
936 void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
937 std::string* msg)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700938 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700939 switch (fmt) {
940 case 'L': // jobject fall-through.
941 case 'a': // jarray fall-through.
942 case 's': // jstring fall-through.
943 case 't': // jthrowable fall-through.
944 if (arg.L == nullptr) {
945 *msg += "NULL";
946 } else {
947 StringAppendF(msg, "%p", arg.L);
948 }
949 break;
950 case 'c': { // jclass
951 jclass jc = arg.c;
Mathieu Chartier0795f232016-09-27 18:43:30 -0700952 ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
Ian Rogers68d8b422014-07-17 11:09:10 -0700953 if (c == nullptr) {
954 *msg += "NULL";
Mathieu Chartier9d156d52016-10-06 17:44:26 -0700955 } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700956 StringAppendF(msg, "INVALID POINTER:%p", jc);
957 } else if (!c->IsClass()) {
David Sehr709b0702016-10-13 09:12:37 -0700958 *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
Ian Rogers68d8b422014-07-17 11:09:10 -0700959 } else {
David Sehr709b0702016-10-13 09:12:37 -0700960 *msg += c->PrettyClass();
Ian Rogers68d8b422014-07-17 11:09:10 -0700961 if (!entry) {
962 StringAppendF(msg, " (%p)", jc);
963 }
964 }
965 break;
966 }
967 case 'f': { // jfieldID
968 jfieldID fid = arg.f;
Andreas Gampe08883de2016-11-08 13:20:52 -0800969 ArtField* f = jni::DecodeArtField(fid);
David Sehr709b0702016-10-13 09:12:37 -0700970 *msg += ArtField::PrettyField(f);
Ian Rogers68d8b422014-07-17 11:09:10 -0700971 if (!entry) {
972 StringAppendF(msg, " (%p)", fid);
973 }
974 break;
975 }
976 case 'm': { // jmethodID
977 jmethodID mid = arg.m;
Andreas Gampe13b27842016-11-07 16:48:23 -0800978 ArtMethod* m = jni::DecodeArtMethod(mid);
David Sehr709b0702016-10-13 09:12:37 -0700979 *msg += ArtMethod::PrettyMethod(m);
Ian Rogers68d8b422014-07-17 11:09:10 -0700980 if (!entry) {
981 StringAppendF(msg, " (%p)", mid);
982 }
983 break;
984 }
Alex Light48ffe062015-08-19 15:23:23 -0700985 case '.': {
986 const VarArgs* va = arg.va;
987 VarArgs args(va->Clone());
Andreas Gampe13b27842016-11-07 16:48:23 -0800988 ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
Alex Light48ffe062015-08-19 15:23:23 -0700989 uint32_t len;
990 const char* shorty = m->GetShorty(&len);
991 CHECK_GE(len, 1u);
992 // Skip past return value.
993 len--;
994 shorty++;
995 // Remove the previous ', ' from the message.
996 msg->erase(msg->length() - 2);
997 for (uint32_t i = 0; i < len; i++) {
998 *msg += ", ";
999 TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1000 }
1001 break;
1002 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001003 default:
1004 TraceNonHeapValue(fmt, arg, msg);
1005 break;
1006 }
1007 }
1008
1009 void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1010 switch (fmt) {
1011 case 'B': // jbyte
1012 if (arg.B >= 0 && arg.B < 10) {
1013 StringAppendF(msg, "%d", arg.B);
1014 } else {
1015 StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1016 }
1017 break;
1018 case 'C': // jchar
1019 if (arg.C < 0x7f && arg.C >= ' ') {
1020 StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1021 } else {
1022 StringAppendF(msg, "U+%x", arg.C);
1023 }
1024 break;
1025 case 'F': // jfloat
1026 StringAppendF(msg, "%g", arg.F);
1027 break;
1028 case 'D': // jdouble
1029 StringAppendF(msg, "%g", arg.D);
1030 break;
1031 case 'S': // jshort
1032 StringAppendF(msg, "%d", arg.S);
1033 break;
1034 case 'i': // jint - fall-through.
1035 case 'I': // jint
1036 StringAppendF(msg, "%d", arg.I);
1037 break;
1038 case 'J': // jlong
1039 StringAppendF(msg, "%" PRId64, arg.J);
1040 break;
1041 case 'Z': // jboolean
1042 case 'b': // jboolean (JNI-style)
1043 *msg += arg.b == JNI_TRUE ? "true" : "false";
1044 break;
1045 case 'V': // void
1046 DCHECK(arg.V == nullptr);
1047 *msg += "void";
1048 break;
1049 case 'v': // JavaVM*
1050 StringAppendF(msg, "(JavaVM*)%p", arg.v);
1051 break;
1052 case 'E':
1053 StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1054 break;
1055 case 'z': // non-negative jsize
1056 // You might expect jsize to be size_t, but it's not; it's the same as jint.
1057 // We only treat this specially so we can do the non-negative check.
1058 // TODO: maybe this wasn't worth it?
1059 StringAppendF(msg, "%d", arg.z);
1060 break;
1061 case 'p': // void* ("pointer")
1062 if (arg.p == nullptr) {
1063 *msg += "NULL";
1064 } else {
1065 StringAppendF(msg, "(void*) %p", arg.p);
1066 }
1067 break;
1068 case 'r': { // jint (release mode)
1069 jint releaseMode = arg.r;
1070 if (releaseMode == 0) {
1071 *msg += "0";
1072 } else if (releaseMode == JNI_ABORT) {
1073 *msg += "JNI_ABORT";
1074 } else if (releaseMode == JNI_COMMIT) {
1075 *msg += "JNI_COMMIT";
1076 } else {
1077 StringAppendF(msg, "invalid release mode %d", releaseMode);
1078 }
1079 break;
1080 }
1081 case 'u': // const char* (Modified UTF-8)
1082 if (arg.u == nullptr) {
1083 *msg += "NULL";
1084 } else {
1085 StringAppendF(msg, "\"%s\"", arg.u);
1086 }
1087 break;
1088 case 'w': // jobjectRefType
1089 switch (arg.w) {
1090 case JNIInvalidRefType:
1091 *msg += "invalid reference type";
1092 break;
1093 case JNILocalRefType:
1094 *msg += "local ref type";
1095 break;
1096 case JNIGlobalRefType:
1097 *msg += "global ref type";
1098 break;
1099 case JNIWeakGlobalRefType:
1100 *msg += "weak global ref type";
1101 break;
1102 default:
1103 *msg += "unknown ref type";
1104 break;
1105 }
1106 break;
Ian Rogers68d8b422014-07-17 11:09:10 -07001107 default:
1108 LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1109 }
1110 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001111 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001112 * Verify that "array" is non-null and points to an Array object.
Elliott Hughesa2501992011-08-26 19:39:54 -07001113 *
1114 * Since we're dealing with objects, switch to "running" mode.
1115 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001116 bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001117 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001118 if (UNLIKELY(java_array == nullptr)) {
1119 AbortF("jarray was NULL");
1120 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001121 }
1122
Mathieu Chartier0795f232016-09-27 18:43:30 -07001123 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001124 if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001125 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001126 AbortF("jarray is an invalid %s: %p (%p)",
Andreas Gampedc061d02016-10-24 13:19:37 -07001127 GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1128 java_array,
1129 a.Ptr());
Ian Rogers68d8b422014-07-17 11:09:10 -07001130 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001131 } else if (!a->IsArrayInstance()) {
David Sehr709b0702016-10-13 09:12:37 -07001132 AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001133 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001134 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001135 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001136 }
1137
Ian Rogers68d8b422014-07-17 11:09:10 -07001138 bool CheckBoolean(jboolean z) {
1139 if (z != JNI_TRUE && z != JNI_FALSE) {
1140 AbortF("unexpected jboolean value: %d", z);
1141 return false;
1142 }
1143 return true;
1144 }
1145
1146 bool CheckLengthPositive(jsize length) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001147 if (length < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001148 AbortF("negative jsize: %d", length);
1149 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
Andreas Gampe08883de2016-11-08 13:20:52 -08001154 ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001155 if (fid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001156 AbortF("jfieldID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001157 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001158 }
Andreas Gampe08883de2016-11-08 13:20:52 -08001159 ArtField* f = jni::DecodeArtField(fid);
Mathieu Chartierc7853442015-03-27 14:35:38 -07001160 // TODO: Better check here.
Mathieu Chartier9d156d52016-10-06 17:44:26 -07001161 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001162 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001163 AbortF("invalid jfieldID: %p", fid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001164 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001165 }
1166 return f;
1167 }
1168
Andreas Gampe13b27842016-11-07 16:48:23 -08001169 ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001170 if (mid == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001171 AbortF("jmethodID was NULL");
Ian Rogersef7d42f2014-01-06 12:55:46 -08001172 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001173 }
Andreas Gampe13b27842016-11-07 16:48:23 -08001174 ArtMethod* m = jni::DecodeArtMethod(mid);
Mathieu Chartiere401d142015-04-22 13:56:20 -07001175 // TODO: Better check here.
1176 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass())) {
Andreas Gampe3fec9ac2016-09-13 10:47:28 -07001177 Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
Ian Rogers68d8b422014-07-17 11:09:10 -07001178 AbortF("invalid jmethodID: %p", mid);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001179 return nullptr;
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001180 }
1181 return m;
1182 }
1183
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07001184 bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001185 Thread* self = Thread::Current();
Ian Rogersef7d42f2014-01-06 12:55:46 -08001186 if (self == nullptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001187 AbortF("a thread (tid %d) is making JNI calls without being attached", GetTid());
1188 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001189 }
1190
Daniel Erat35e827a2016-05-10 18:07:18 -06001191 // Get the current thread's JNIEnv by going through our TLS pointer.
Elliott Hughesa2501992011-08-26 19:39:54 -07001192 JNIEnvExt* threadEnv = self->GetJniEnv();
1193
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001194 // Verify that the current thread is (a) attached and (b) associated with
1195 // this particular instance of JNIEnv.
Ian Rogers68d8b422014-07-17 11:09:10 -07001196 if (env != threadEnv) {
Daniel Erat35e827a2016-05-10 18:07:18 -06001197 // Get the thread owning the JNIEnv that's being used.
1198 Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self;
Ian Rogers68d8b422014-07-17 11:09:10 -07001199 AbortF("thread %s using JNIEnv* from thread %s",
Daniel Erat35e827a2016-05-10 18:07:18 -06001200 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001201 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001202 }
1203
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001204 // Verify that, if this thread previously made a critical "get" call, we
1205 // do the corresponding "release" call before we try anything else.
Ian Rogers68d8b422014-07-17 11:09:10 -07001206 switch (flags_ & kFlag_CritMask) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001207 case kFlag_CritOkay: // okay to call this method
1208 break;
1209 case kFlag_CritBad: // not okay to call
1210 if (threadEnv->critical) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001211 AbortF("thread %s using JNI after critical get",
1212 ToStr<Thread>(*self).c_str());
1213 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001214 }
1215 break;
1216 case kFlag_CritGet: // this is a "get" call
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001217 // Don't check here; we allow nested gets.
Elliott Hughesa2501992011-08-26 19:39:54 -07001218 threadEnv->critical++;
1219 break;
Brian Carlstrom7934ac22013-07-26 10:54:15 -07001220 case kFlag_CritRelease: // this is a "release" call
Elliott Hughesa2501992011-08-26 19:39:54 -07001221 threadEnv->critical--;
1222 if (threadEnv->critical < 0) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001223 AbortF("thread %s called too many critical releases",
1224 ToStr<Thread>(*self).c_str());
1225 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001226 }
1227 break;
1228 default:
Ian Rogers68d8b422014-07-17 11:09:10 -07001229 LOG(FATAL) << "Bad flags (internal error): " << flags_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001230 }
1231
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001232 // Verify that, if an exception has been raised, the native code doesn't
1233 // make any JNI calls other than the Exception* methods.
Ian Rogers68d8b422014-07-17 11:09:10 -07001234 if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
Nicolas Geoffray14691c52015-03-05 10:40:17 +00001235 mirror::Throwable* exception = self->GetException();
1236 AbortF("JNI %s called with pending exception %s",
1237 function_name_,
1238 exception->Dump().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001239 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001240 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001241 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001242 }
1243
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001244 // Verifies that "bytes" points to valid Modified UTF-8 data.
Ian Rogers68d8b422014-07-17 11:09:10 -07001245 bool CheckUtfString(const char* bytes, bool nullable) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001246 if (bytes == nullptr) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001247 if (!nullable) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001248 AbortF("non-nullable const char* was NULL");
1249 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001250 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001251 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001252 }
1253
Ian Rogersef7d42f2014-01-06 12:55:46 -08001254 const char* errorKind = nullptr;
Andreas Gampeef4afe92015-07-27 21:03:25 -07001255 const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
Ian Rogersef7d42f2014-01-06 12:55:46 -08001256 if (errorKind != nullptr) {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001257 // This is an expensive loop that will resize often, but this isn't supposed to hit in
1258 // practice anyways.
1259 std::ostringstream oss;
1260 oss << std::hex;
1261 const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1262 while (*tmp != 0) {
1263 if (tmp == utf8) {
1264 oss << "<";
1265 }
1266 oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1267 if (tmp == utf8) {
1268 oss << '>';
1269 }
1270 tmp++;
1271 if (*tmp != 0) {
1272 oss << ' ';
1273 }
1274 }
1275
Ian Rogers68d8b422014-07-17 11:09:10 -07001276 AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
Andreas Gampeef4afe92015-07-27 21:03:25 -07001277 " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
Ian Rogers68d8b422014-07-17 11:09:10 -07001278 return false;
Elliott Hughesa2501992011-08-26 19:39:54 -07001279 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001280 return true;
Elliott Hughesa2501992011-08-26 19:39:54 -07001281 }
1282
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001283 // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1284 // sequences in place of encoded surrogate pairs.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001285 static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001286 while (*bytes != '\0') {
Andreas Gampeef4afe92015-07-27 21:03:25 -07001287 const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
Elliott Hughesa2501992011-08-26 19:39:54 -07001288 // Switch on the high four bits.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001289 switch (*utf8 >> 4) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001290 case 0x00:
1291 case 0x01:
1292 case 0x02:
1293 case 0x03:
1294 case 0x04:
1295 case 0x05:
1296 case 0x06:
1297 case 0x07:
1298 // Bit pattern 0xxx. No need for any extra bytes.
1299 break;
1300 case 0x08:
1301 case 0x09:
1302 case 0x0a:
1303 case 0x0b:
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001304 // Bit patterns 10xx, which are illegal start bytes.
Elliott Hughesa2501992011-08-26 19:39:54 -07001305 *errorKind = "start";
1306 return utf8;
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001307 case 0x0f:
1308 // Bit pattern 1111, which might be the start of a 4 byte sequence.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001309 if ((*utf8 & 0x08) == 0) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001310 // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1311 // We consume one continuation byte here, and fall through to consume two more.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001312 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1313 if ((*utf8 & 0xc0) != 0x80) {
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001314 *errorKind = "continuation";
1315 return utf8;
1316 }
1317 } else {
1318 *errorKind = "start";
1319 return utf8;
1320 }
1321
1322 // Fall through to the cases below to consume two more continuation bytes.
1323 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001324 case 0x0e:
1325 // Bit pattern 1110, so there are two additional bytes.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001326 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1327 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001328 *errorKind = "continuation";
1329 return utf8;
1330 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +00001331
1332 // Fall through to consume one more continuation byte.
1333 FALLTHROUGH_INTENDED;
Elliott Hughesa2501992011-08-26 19:39:54 -07001334 case 0x0c:
1335 case 0x0d:
1336 // Bit pattern 110x, so there is one additional byte.
Andreas Gampeef4afe92015-07-27 21:03:25 -07001337 utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1338 if ((*utf8 & 0xc0) != 0x80) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001339 *errorKind = "continuation";
1340 return utf8;
1341 }
1342 break;
1343 }
1344 }
1345 return 0;
1346 }
1347
Ian Rogers68d8b422014-07-17 11:09:10 -07001348 void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1349 va_list args;
1350 va_start(args, fmt);
1351 Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1352 va_end(args);
1353 }
1354
1355 // The name of the JNI function being checked.
1356 const char* const function_name_;
1357
1358 const int flags_;
Elliott Hughes92cb4982011-12-16 16:57:28 -08001359 int indent_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001360
Ian Rogers68d8b422014-07-17 11:09:10 -07001361 const bool has_method_;
1362
Elliott Hughesa2501992011-08-26 19:39:54 -07001363 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1364};
1365
Elliott Hughesa2501992011-08-26 19:39:54 -07001366/*
1367 * ===========================================================================
1368 * Guarded arrays
1369 * ===========================================================================
1370 */
1371
Elliott Hughesa2501992011-08-26 19:39:54 -07001372/* this gets tucked in at the start of the buffer; struct size must be even */
Ian Rogers68d8b422014-07-17 11:09:10 -07001373class GuardedCopy {
1374 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07001375 /*
1376 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1377 * filling in the area around it with guard data.
Elliott Hughesa2501992011-08-26 19:39:54 -07001378 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001379 static void* Create(void* original_buf, size_t len, bool mod_okay) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001380 const size_t new_len = LengthIncludingRedZones(len);
1381 uint8_t* const new_buf = DebugAlloc(new_len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001382
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001383 // If modification is not expected, grab a checksum.
Elliott Hughesa2501992011-08-26 19:39:54 -07001384 uLong adler = 0;
Ian Rogers68d8b422014-07-17 11:09:10 -07001385 if (!mod_okay) {
1386 adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
Elliott Hughesa2501992011-08-26 19:39:54 -07001387 }
1388
Ian Rogers68d8b422014-07-17 11:09:10 -07001389 GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
Elliott Hughesa2501992011-08-26 19:39:54 -07001390
Ian Rogers68d8b422014-07-17 11:09:10 -07001391 // Fill begin region with canary pattern.
1392 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1393 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1394 const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1395 if (kCanary[j] == '\0') {
1396 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001397 } else {
1398 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001399 }
1400 }
1401
1402 // Copy the data in; note "len" could be zero.
1403 memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1404
1405 // Fill end region with canary pattern.
1406 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1407 const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1408 if (kCanary[j] == '\0') {
1409 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001410 } else {
1411 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001412 }
1413 }
1414
1415 return const_cast<uint8_t*>(copy->BufferWithinRedZones());
Elliott Hughesa2501992011-08-26 19:39:54 -07001416 }
1417
1418 /*
Ian Rogers68d8b422014-07-17 11:09:10 -07001419 * Create a guarded copy of a primitive array. Modifications to the copied
1420 * data are allowed. Returns a pointer to the copied data.
1421 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001422 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1423 void* original_ptr) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001424 ScopedObjectAccess soa(env);
1425
Mathieu Chartier0795f232016-09-27 18:43:30 -07001426 ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
Ian Rogers68d8b422014-07-17 11:09:10 -07001427 size_t component_size = a->GetClass()->GetComponentSize();
1428 size_t byte_count = a->GetLength() * component_size;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001429 void* result = Create(original_ptr, byte_count, true);
Ian Rogers68d8b422014-07-17 11:09:10 -07001430 if (is_copy != nullptr) {
1431 *is_copy = JNI_TRUE;
1432 }
1433 return result;
1434 }
1435
1436 /*
1437 * Perform the array "release" operation, which may or may not copy data
1438 * back into the managed heap, and may or may not release the underlying storage.
1439 */
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001440 static void* ReleaseGuardedPACopy(const char* function_name, JNIEnv* env,
1441 jarray java_array ATTRIBUTE_UNUSED, void* embedded_buf,
1442 int mode) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001443 ScopedObjectAccess soa(env);
Ian Rogers68d8b422014-07-17 11:09:10 -07001444 if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1445 return nullptr;
1446 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001447 GuardedCopy* const copy = FromEmbedded(embedded_buf);
1448 void* original_ptr = copy->original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001449 if (mode != JNI_ABORT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001450 memcpy(original_ptr, embedded_buf, copy->original_length_);
Ian Rogers68d8b422014-07-17 11:09:10 -07001451 }
1452 if (mode != JNI_COMMIT) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001453 Destroy(embedded_buf);
Ian Rogers68d8b422014-07-17 11:09:10 -07001454 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001455 return original_ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07001456 }
1457
1458
1459 /*
Elliott Hughesa2501992011-08-26 19:39:54 -07001460 * Free up the guard buffer, scrub it, and return the original pointer.
1461 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001462 static void* Destroy(void* embedded_buf) {
1463 GuardedCopy* copy = FromEmbedded(embedded_buf);
1464 void* original_ptr = const_cast<void*>(copy->original_ptr_);
1465 size_t len = LengthIncludingRedZones(copy->original_length_);
1466 DebugFree(copy, len);
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001467 return original_ptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001468 }
1469
1470 /*
1471 * Verify the guard area and, if "modOkay" is false, that the data itself
1472 * has not been altered.
1473 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001474 * The caller has already checked that "dataBuf" is non-null.
Elliott Hughesa2501992011-08-26 19:39:54 -07001475 */
Ian Rogers68d8b422014-07-17 11:09:10 -07001476 static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1477 const GuardedCopy* copy = FromEmbedded(embedded_buf);
1478 return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
Elliott Hughesa2501992011-08-26 19:39:54 -07001479 }
1480
1481 private:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001482 GuardedCopy(void* original_buf, size_t len, uLong adler) :
Ian Rogers68d8b422014-07-17 11:09:10 -07001483 magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1484 }
1485
Elliott Hughes32ae6e32011-09-27 10:46:50 -07001486 static uint8_t* DebugAlloc(size_t len) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001487 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
Elliott Hughesa2501992011-08-26 19:39:54 -07001488 if (result == MAP_FAILED) {
1489 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1490 }
1491 return reinterpret_cast<uint8_t*>(result);
1492 }
1493
Ian Rogers68d8b422014-07-17 11:09:10 -07001494 static void DebugFree(void* buf, size_t len) {
1495 if (munmap(buf, len) != 0) {
1496 PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
Elliott Hughesa2501992011-08-26 19:39:54 -07001497 }
1498 }
1499
Ian Rogers68d8b422014-07-17 11:09:10 -07001500 static size_t LengthIncludingRedZones(size_t len) {
1501 return len + kRedZoneSize;
Elliott Hughesa2501992011-08-26 19:39:54 -07001502 }
1503
Ian Rogers68d8b422014-07-17 11:09:10 -07001504 // Get the GuardedCopy from the interior pointer.
1505 static GuardedCopy* FromEmbedded(void* embedded_buf) {
1506 return reinterpret_cast<GuardedCopy*>(
1507 reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001508 }
1509
Ian Rogers68d8b422014-07-17 11:09:10 -07001510 static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1511 return reinterpret_cast<const GuardedCopy*>(
1512 reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
Elliott Hughesa2501992011-08-26 19:39:54 -07001513 }
Ian Rogers68d8b422014-07-17 11:09:10 -07001514
1515 static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1516 va_list args;
1517 va_start(args, fmt);
1518 Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1519 va_end(args);
1520 }
1521
1522 bool CheckHeader(const char* function_name, bool mod_okay) const {
1523 static const uint32_t kMagicCmp = kGuardMagic;
1524
1525 // Before we do anything with "pExtra", check the magic number. We
1526 // do the check with memcmp rather than "==" in case the pointer is
1527 // unaligned. If it points to completely bogus memory we're going
1528 // to crash, but there's no easy way around that.
1529 if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1530 uint8_t buf[4];
1531 memcpy(buf, &magic_, 4);
1532 AbortF(function_name,
1533 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1534 buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1535 return false;
1536 }
1537
1538 // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1539 // told the client that we made a copy, there's no reason they can't alter the buffer.
1540 if (!mod_okay) {
1541 uLong computed_adler =
1542 adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1543 if (computed_adler != adler_) {
1544 AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1545 computed_adler, adler_, this);
1546 return false;
1547 }
1548 }
1549 return true;
1550 }
1551
1552 bool CheckRedZones(const char* function_name) const {
1553 // Check the begin red zone.
1554 const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1555 for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1556 if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1557 AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1558 return false;
1559 }
1560 if (kCanary[j] == '\0') {
1561 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001562 } else {
1563 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001564 }
1565 }
1566
1567 // Check end region.
1568 for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1569 if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1570 size_t offset_from_buffer_start =
1571 &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1572 AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1573 offset_from_buffer_start);
1574 return false;
1575 }
1576 if (kCanary[j] == '\0') {
1577 j = 0;
tony.ys_liu068361a2015-07-14 16:25:16 +08001578 } else {
1579 j++;
Ian Rogers68d8b422014-07-17 11:09:10 -07001580 }
1581 }
1582 return true;
1583 }
1584
1585 // Location that canary value will be written before the guarded region.
1586 const char* StartRedZone() const {
1587 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1588 return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1589 }
1590
1591 // Return the interior embedded buffer.
1592 const uint8_t* BufferWithinRedZones() const {
1593 const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1594 return embedded_buf;
1595 }
1596
1597 // Location that canary value will be written after the guarded region.
1598 const char* EndRedZone() const {
1599 const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1600 size_t buf_len = LengthIncludingRedZones(original_length_);
1601 return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1602 }
1603
1604 static constexpr size_t kRedZoneSize = 512;
1605 static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1606
1607 // Value written before and after the guarded array.
1608 static const char* const kCanary;
1609
1610 static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1611
1612 const uint32_t magic_;
1613 const uLong adler_;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07001614 void* const original_ptr_;
Ian Rogers68d8b422014-07-17 11:09:10 -07001615 const size_t original_length_;
Elliott Hughesa2501992011-08-26 19:39:54 -07001616};
Ian Rogers68d8b422014-07-17 11:09:10 -07001617const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
Elliott Hughesa2501992011-08-26 19:39:54 -07001618
1619/*
1620 * ===========================================================================
1621 * JNI functions
1622 * ===========================================================================
1623 */
1624
1625class CheckJNI {
1626 public:
1627 static jint GetVersion(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001628 ScopedObjectAccess soa(env);
1629 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1630 JniValueType args[1] = {{.E = env }};
1631 if (sc.Check(soa, true, "E", args)) {
1632 JniValueType result;
1633 result.I = baseEnv(env)->GetVersion(env);
1634 if (sc.Check(soa, false, "I", &result)) {
1635 return result.I;
1636 }
1637 }
1638 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001639 }
1640
Ian Rogers68d8b422014-07-17 11:09:10 -07001641 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1642 ScopedObjectAccess soa(env);
1643 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1644 JniValueType args[2] = {{.E = env }, {.p = vm}};
1645 if (sc.Check(soa, true, "Ep", args)) {
1646 JniValueType result;
1647 result.i = baseEnv(env)->GetJavaVM(env, vm);
1648 if (sc.Check(soa, false, "i", &result)) {
1649 return result.i;
1650 }
1651 }
1652 return JNI_ERR;
1653 }
1654
1655 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1656 ScopedObjectAccess soa(env);
1657 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1658 JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1659 if (sc.Check(soa, true, "EcpI", args)) {
1660 JniValueType result;
1661 result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1662 if (sc.Check(soa, false, "i", &result)) {
1663 return result.i;
1664 }
1665 }
1666 return JNI_ERR;
1667 }
1668
1669 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1670 ScopedObjectAccess soa(env);
1671 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1672 JniValueType args[2] = {{.E = env }, {.c = c}};
1673 if (sc.Check(soa, true, "Ec", args)) {
1674 JniValueType result;
1675 result.i = baseEnv(env)->UnregisterNatives(env, c);
1676 if (sc.Check(soa, false, "i", &result)) {
1677 return result.i;
1678 }
1679 }
1680 return JNI_ERR;
1681 }
1682
1683 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
Ian Rogersc0542af2014-09-03 16:16:56 -07001684 // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1685 // know the object is invalid. The spec says that passing invalid objects or even ones that
1686 // are deleted isn't supported.
Ian Rogers68d8b422014-07-17 11:09:10 -07001687 ScopedObjectAccess soa(env);
1688 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Ian Rogersc0542af2014-09-03 16:16:56 -07001689 JniValueType args[2] = {{.E = env }, {.L = obj}};
1690 if (sc.Check(soa, true, "EL", args)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001691 JniValueType result;
1692 result.w = baseEnv(env)->GetObjectRefType(env, obj);
1693 if (sc.Check(soa, false, "w", &result)) {
1694 return result.w;
1695 }
1696 }
1697 return JNIInvalidRefType;
1698 }
1699
1700 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1701 jsize bufLen) {
1702 ScopedObjectAccess soa(env);
1703 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1704 JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1705 if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1706 JniValueType result;
1707 result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1708 if (sc.Check(soa, false, "c", &result)) {
1709 return result.c;
1710 }
1711 }
1712 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001713 }
1714
1715 static jclass FindClass(JNIEnv* env, const char* name) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001716 ScopedObjectAccess soa(env);
1717 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1718 JniValueType args[2] = {{.E = env}, {.u = name}};
1719 if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1720 JniValueType result;
1721 result.c = baseEnv(env)->FindClass(env, name);
1722 if (sc.Check(soa, false, "c", &result)) {
1723 return result.c;
1724 }
1725 }
1726 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001727 }
1728
Elliott Hughese84278b2012-03-22 10:06:53 -07001729 static jclass GetSuperclass(JNIEnv* env, jclass c) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001730 ScopedObjectAccess soa(env);
1731 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1732 JniValueType args[2] = {{.E = env}, {.c = c}};
1733 if (sc.Check(soa, true, "Ec", args)) {
1734 JniValueType result;
1735 result.c = baseEnv(env)->GetSuperclass(env, c);
1736 if (sc.Check(soa, false, "c", &result)) {
1737 return result.c;
1738 }
1739 }
1740 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001741 }
1742
Elliott Hughese84278b2012-03-22 10:06:53 -07001743 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001744 ScopedObjectAccess soa(env);
1745 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1746 JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1747 if (sc.Check(soa, true, "Ecc", args)) {
1748 JniValueType result;
1749 result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1750 if (sc.Check(soa, false, "b", &result)) {
1751 return result.b;
1752 }
1753 }
1754 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001755 }
1756
1757 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001758 ScopedObjectAccess soa(env);
1759 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1760 JniValueType args[2] = {{.E = env}, {.L = method}};
1761 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1762 JniValueType result;
1763 result.m = baseEnv(env)->FromReflectedMethod(env, method);
1764 if (sc.Check(soa, false, "m", &result)) {
1765 return result.m;
1766 }
1767 }
1768 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001769 }
1770
1771 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001772 ScopedObjectAccess soa(env);
1773 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1774 JniValueType args[2] = {{.E = env}, {.L = field}};
1775 if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1776 JniValueType result;
1777 result.f = baseEnv(env)->FromReflectedField(env, field);
1778 if (sc.Check(soa, false, "f", &result)) {
1779 return result.f;
1780 }
1781 }
1782 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001783 }
1784
1785 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001786 ScopedObjectAccess soa(env);
1787 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1788 JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.b = isStatic}};
1789 if (sc.Check(soa, true, "Ecmb", args)) {
1790 JniValueType result;
1791 result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1792 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1793 DCHECK(sc.CheckReflectedMethod(soa, result.L));
1794 return result.L;
1795 }
1796 }
1797 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001798 }
1799
1800 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001801 ScopedObjectAccess soa(env);
1802 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1803 JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.b = isStatic}};
1804 if (sc.Check(soa, true, "Ecfb", args)) {
1805 JniValueType result;
1806 result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1807 if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1808 DCHECK(sc.CheckReflectedField(soa, result.L));
1809 return result.L;
1810 }
1811 }
1812 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001813 }
1814
1815 static jint Throw(JNIEnv* env, jthrowable obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001816 ScopedObjectAccess soa(env);
1817 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1818 JniValueType args[2] = {{.E = env}, {.t = obj}};
1819 if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
1820 JniValueType result;
1821 result.i = baseEnv(env)->Throw(env, obj);
1822 if (sc.Check(soa, false, "i", &result)) {
1823 return result.i;
1824 }
1825 }
1826 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001827 }
1828
Elliott Hughese84278b2012-03-22 10:06:53 -07001829 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001830 ScopedObjectAccess soa(env);
1831 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
Christopher Ferrisc50358b2015-04-17 13:26:09 -07001832 JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
Ian Rogers68d8b422014-07-17 11:09:10 -07001833 if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
1834 JniValueType result;
1835 result.i = baseEnv(env)->ThrowNew(env, c, message);
1836 if (sc.Check(soa, false, "i", &result)) {
1837 return result.i;
1838 }
1839 }
1840 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001841 }
1842
1843 static jthrowable ExceptionOccurred(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001844 ScopedObjectAccess soa(env);
1845 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1846 JniValueType args[1] = {{.E = env}};
1847 if (sc.Check(soa, true, "E", args)) {
1848 JniValueType result;
1849 result.t = baseEnv(env)->ExceptionOccurred(env);
1850 if (sc.Check(soa, false, "t", &result)) {
1851 return result.t;
1852 }
1853 }
1854 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001855 }
1856
1857 static void ExceptionDescribe(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001858 ScopedObjectAccess soa(env);
1859 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1860 JniValueType args[1] = {{.E = env}};
1861 if (sc.Check(soa, true, "E", args)) {
1862 JniValueType result;
1863 baseEnv(env)->ExceptionDescribe(env);
1864 result.V = nullptr;
1865 sc.Check(soa, false, "V", &result);
1866 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001867 }
1868
1869 static void ExceptionClear(JNIEnv* env) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001870 ScopedObjectAccess soa(env);
1871 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1872 JniValueType args[1] = {{.E = env}};
1873 if (sc.Check(soa, true, "E", args)) {
1874 JniValueType result;
1875 baseEnv(env)->ExceptionClear(env);
1876 result.V = nullptr;
1877 sc.Check(soa, false, "V", &result);
1878 }
1879 }
1880
1881 static jboolean ExceptionCheck(JNIEnv* env) {
1882 ScopedObjectAccess soa(env);
1883 ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
1884 JniValueType args[1] = {{.E = env}};
1885 if (sc.Check(soa, true, "E", args)) {
1886 JniValueType result;
1887 result.b = baseEnv(env)->ExceptionCheck(env);
1888 if (sc.Check(soa, false, "b", &result)) {
1889 return result.b;
1890 }
1891 }
1892 return JNI_FALSE;
Elliott Hughesa2501992011-08-26 19:39:54 -07001893 }
1894
1895 static void FatalError(JNIEnv* env, const char* msg) {
Elliott Hughesc4378df2013-06-14 17:05:13 -07001896 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1897 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1898 // and it's not unimaginable that you don't know that you do. So we allow it.
Ian Rogers68d8b422014-07-17 11:09:10 -07001899 ScopedObjectAccess soa(env);
1900 ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
1901 JniValueType args[2] = {{.E = env}, {.u = msg}};
1902 if (sc.Check(soa, true, "Eu", args)) {
1903 JniValueType result;
1904 baseEnv(env)->FatalError(env, msg);
1905 // Unreachable.
1906 result.V = nullptr;
1907 sc.Check(soa, false, "V", &result);
1908 }
Elliott Hughesa2501992011-08-26 19:39:54 -07001909 }
1910
1911 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001912 ScopedObjectAccess soa(env);
1913 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1914 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1915 if (sc.Check(soa, true, "EI", args)) {
1916 JniValueType result;
1917 result.i = baseEnv(env)->PushLocalFrame(env, capacity);
1918 if (sc.Check(soa, false, "i", &result)) {
1919 return result.i;
1920 }
1921 }
1922 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07001923 }
1924
1925 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001926 ScopedObjectAccess soa(env);
1927 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
1928 JniValueType args[2] = {{.E = env}, {.L = res}};
1929 if (sc.Check(soa, true, "EL", args)) {
1930 JniValueType result;
1931 result.L = baseEnv(env)->PopLocalFrame(env, res);
1932 sc.Check(soa, false, "L", &result);
1933 return result.L;
1934 }
1935 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07001936 }
1937
1938 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001939 return NewRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001940 }
1941
Ian Rogers68d8b422014-07-17 11:09:10 -07001942 static jobject NewLocalRef(JNIEnv* env, jobject obj) {
1943 return NewRef(__FUNCTION__, env, obj, kLocal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001944 }
1945
1946 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
Ian Rogers68d8b422014-07-17 11:09:10 -07001947 return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001948 }
1949
Ian Rogers68d8b422014-07-17 11:09:10 -07001950 static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
1951 DeleteRef(__FUNCTION__, env, obj, kGlobal);
Elliott Hughesa2501992011-08-26 19:39:54 -07001952 }
1953
Ian Rogers68d8b422014-07-17 11:09:10 -07001954 static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
1955 DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
1956 }
1957
1958 static void DeleteLocalRef(JNIEnv* env, jobject obj) {
1959 DeleteRef(__FUNCTION__, env, obj, kLocal);
1960 }
1961
1962 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1963 ScopedObjectAccess soa(env);
1964 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1965 JniValueType args[2] = {{.E = env}, {.I = capacity}};
1966 if (sc.Check(soa, true, "EI", args)) {
1967 JniValueType result;
1968 result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
1969 if (sc.Check(soa, false, "i", &result)) {
1970 return result.i;
1971 }
1972 }
1973 return JNI_ERR;
1974 }
1975
1976 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1977 ScopedObjectAccess soa(env);
1978 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1979 JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
1980 if (sc.Check(soa, true, "ELL", args)) {
1981 JniValueType result;
1982 result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
1983 if (sc.Check(soa, false, "b", &result)) {
1984 return result.b;
1985 }
1986 }
1987 return JNI_FALSE;
1988 }
1989
1990 static jobject AllocObject(JNIEnv* env, jclass c) {
1991 ScopedObjectAccess soa(env);
1992 ScopedCheck sc(kFlag_Default, __FUNCTION__);
1993 JniValueType args[2] = {{.E = env}, {.c = c}};
1994 if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
1995 JniValueType result;
1996 result.L = baseEnv(env)->AllocObject(env, c);
1997 if (sc.Check(soa, false, "L", &result)) {
1998 return result.L;
1999 }
2000 }
2001 return nullptr;
2002 }
2003
2004 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2005 ScopedObjectAccess soa(env);
2006 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002007 VarArgs rest(mid, vargs);
2008 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2009 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002010 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002011 JniValueType result;
2012 result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2013 if (sc.Check(soa, false, "L", &result)) {
2014 return result.L;
2015 }
2016 }
2017 return nullptr;
2018 }
2019
2020 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2021 va_list args;
2022 va_start(args, mid);
2023 jobject result = NewObjectV(env, c, mid, args);
2024 va_end(args);
2025 return result;
2026 }
2027
2028 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
2029 ScopedObjectAccess soa(env);
2030 ScopedCheck sc(kFlag_Default, __FUNCTION__);
Alex Light48ffe062015-08-19 15:23:23 -07002031 VarArgs rest(mid, vargs);
2032 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2033 if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
Andreas Gampe13b27842016-11-07 16:48:23 -08002034 sc.CheckConstructor(mid)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002035 JniValueType result;
2036 result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2037 if (sc.Check(soa, false, "L", &result)) {
2038 return result.L;
2039 }
2040 }
2041 return nullptr;
2042 }
2043
2044 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2045 ScopedObjectAccess soa(env);
2046 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2047 JniValueType args[2] = {{.E = env}, {.L = obj}};
2048 if (sc.Check(soa, true, "EL", args)) {
2049 JniValueType result;
2050 result.c = baseEnv(env)->GetObjectClass(env, obj);
2051 if (sc.Check(soa, false, "c", &result)) {
2052 return result.c;
2053 }
2054 }
2055 return nullptr;
2056 }
2057
2058 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2059 ScopedObjectAccess soa(env);
2060 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2061 JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2062 if (sc.Check(soa, true, "ELc", args)) {
2063 JniValueType result;
2064 result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2065 if (sc.Check(soa, false, "b", &result)) {
2066 return result.b;
2067 }
2068 }
2069 return JNI_FALSE;
2070 }
2071
2072 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2073 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2074 }
2075
2076 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2077 return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2078 }
2079
2080 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2081 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2082 }
2083
2084 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2085 return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2086 }
2087
2088#define FIELD_ACCESSORS(jtype, name, ptype, shorty) \
2089 static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2090 return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2091 } \
2092 \
2093 static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2094 return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2095 } \
2096 \
2097 static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2098 JniValueType value; \
2099 value.shorty = v; \
2100 SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2101 } \
2102 \
2103 static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2104 JniValueType value; \
2105 value.shorty = v; \
2106 SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2107 }
2108
2109 FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L)
2110 FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2111 FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B)
2112 FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C)
2113 FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S)
2114 FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I)
2115 FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J)
2116 FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F)
2117 FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D)
2118#undef FIELD_ACCESSORS
2119
2120 static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) {
2121 CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2122 }
2123
2124 static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2125 jvalue* vargs) {
2126 CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2127 }
2128
2129 static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) {
Marcus Oakland51be0a72014-09-24 15:23:06 +01002130 CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
Ian Rogers68d8b422014-07-17 11:09:10 -07002131 }
2132
2133 static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2134 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2135 }
2136
2137 static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2138 va_list vargs) {
2139 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2140 }
2141
2142 static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2143 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2144 }
2145
2146 static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2147 va_list vargs;
2148 va_start(vargs, mid);
2149 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2150 va_end(vargs);
2151 }
2152
2153 static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2154 va_list vargs;
2155 va_start(vargs, mid);
2156 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2157 va_end(vargs);
2158 }
2159
2160 static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2161 va_list vargs;
2162 va_start(vargs, mid);
2163 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2164 va_end(vargs);
2165 }
2166
2167#define CALL(rtype, name, ptype, shorty) \
2168 static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* vargs) { \
2169 return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2170 } \
2171 \
2172 static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2173 jvalue* vargs) { \
2174 return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2175 } \
2176 \
2177 static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* vargs) { \
2178 return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2179 } \
2180 \
2181 static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2182 return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2183 } \
2184 \
2185 static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2186 va_list vargs) { \
2187 return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2188 } \
2189 \
2190 static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2191 return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2192 } \
2193 \
2194 static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2195 va_list vargs; \
2196 va_start(vargs, mid); \
2197 rtype result = \
2198 CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2199 va_end(vargs); \
2200 return result; \
2201 } \
2202 \
2203 static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2204 ...) { \
2205 va_list vargs; \
2206 va_start(vargs, mid); \
2207 rtype result = \
2208 CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2209 va_end(vargs); \
2210 return result; \
2211 } \
2212 \
2213 static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2214 va_list vargs; \
2215 va_start(vargs, mid); \
2216 rtype result = \
2217 CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2218 va_end(vargs); \
2219 return result; \
2220 }
2221
2222 CALL(jobject, Object, Primitive::kPrimNot, L)
2223 CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2224 CALL(jbyte, Byte, Primitive::kPrimByte, B)
2225 CALL(jchar, Char, Primitive::kPrimChar, C)
2226 CALL(jshort, Short, Primitive::kPrimShort, S)
2227 CALL(jint, Int, Primitive::kPrimInt, I)
2228 CALL(jlong, Long, Primitive::kPrimLong, J)
2229 CALL(jfloat, Float, Primitive::kPrimFloat, F)
2230 CALL(jdouble, Double, Primitive::kPrimDouble, D)
2231#undef CALL
2232
2233 static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2234 ScopedObjectAccess soa(env);
2235 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2236 JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2237 if (sc.Check(soa, true, "Epz", args)) {
2238 JniValueType result;
2239 result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2240 if (sc.Check(soa, false, "s", &result)) {
2241 return result.s;
2242 }
2243 }
2244 return nullptr;
2245 }
2246
2247 static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2248 ScopedObjectAccess soa(env);
2249 ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2250 JniValueType args[2] = {{.E = env}, {.u = chars}};
2251 if (sc.Check(soa, true, "Eu", args)) {
2252 JniValueType result;
2253 // TODO: stale? show pointer and truncate string.
2254 result.s = baseEnv(env)->NewStringUTF(env, chars);
2255 if (sc.Check(soa, false, "s", &result)) {
2256 return result.s;
2257 }
2258 }
2259 return nullptr;
2260 }
2261
2262 static jsize GetStringLength(JNIEnv* env, jstring string) {
2263 ScopedObjectAccess soa(env);
2264 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2265 JniValueType args[2] = {{.E = env}, {.s = string}};
2266 if (sc.Check(soa, true, "Es", args)) {
2267 JniValueType result;
2268 result.z = baseEnv(env)->GetStringLength(env, string);
2269 if (sc.Check(soa, false, "z", &result)) {
2270 return result.z;
2271 }
2272 }
2273 return JNI_ERR;
2274 }
2275
2276 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2277 ScopedObjectAccess soa(env);
2278 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2279 JniValueType args[2] = {{.E = env}, {.s = string}};
2280 if (sc.Check(soa, true, "Es", args)) {
2281 JniValueType result;
2282 result.z = baseEnv(env)->GetStringUTFLength(env, string);
2283 if (sc.Check(soa, false, "z", &result)) {
2284 return result.z;
2285 }
2286 }
2287 return JNI_ERR;
2288 }
2289
2290 static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2291 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2292 is_copy, false, false));
2293 }
2294
2295 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2296 return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2297 is_copy, true, false));
2298 }
2299
2300 static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2301 return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2302 is_copy, false, true));
2303 }
2304
2305 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2306 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2307 }
2308
2309 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2310 ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2311 }
2312
2313 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2314 ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2315 }
2316
2317 static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2318 ScopedObjectAccess soa(env);
2319 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2320 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2321 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2322 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2323 if (sc.Check(soa, true, "EsIIp", args)) {
2324 baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2325 JniValueType result;
2326 result.V = nullptr;
2327 sc.Check(soa, false, "V", &result);
2328 }
2329 }
2330
2331 static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2332 ScopedObjectAccess soa(env);
2333 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2334 JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2335 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2336 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2337 if (sc.Check(soa, true, "EsIIp", args)) {
2338 baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2339 JniValueType result;
2340 result.V = nullptr;
2341 sc.Check(soa, false, "V", &result);
2342 }
2343 }
2344
2345 static jsize GetArrayLength(JNIEnv* env, jarray array) {
2346 ScopedObjectAccess soa(env);
2347 ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2348 JniValueType args[2] = {{.E = env}, {.a = array}};
2349 if (sc.Check(soa, true, "Ea", args)) {
2350 JniValueType result;
2351 result.z = baseEnv(env)->GetArrayLength(env, array);
2352 if (sc.Check(soa, false, "z", &result)) {
2353 return result.z;
2354 }
2355 }
2356 return JNI_ERR;
2357 }
2358
2359 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2360 jobject initial_element) {
2361 ScopedObjectAccess soa(env);
2362 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2363 JniValueType args[4] =
2364 {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2365 if (sc.Check(soa, true, "EzcL", args)) {
2366 JniValueType result;
2367 // Note: assignability tests of initial_element are done in the base implementation.
2368 result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2369 if (sc.Check(soa, false, "a", &result)) {
2370 return down_cast<jobjectArray>(result.a);
2371 }
2372 }
2373 return nullptr;
2374 }
2375
2376 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2377 ScopedObjectAccess soa(env);
2378 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2379 JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2380 if (sc.Check(soa, true, "Eaz", args)) {
2381 JniValueType result;
2382 result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2383 if (sc.Check(soa, false, "L", &result)) {
2384 return result.L;
2385 }
2386 }
2387 return nullptr;
2388 }
2389
2390 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2391 ScopedObjectAccess soa(env);
2392 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2393 JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2394 // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2395 // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2396 // in ArrayStoreExceptions.
2397 if (sc.Check(soa, true, "EaIL", args)) {
2398 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2399 JniValueType result;
2400 result.V = nullptr;
2401 sc.Check(soa, false, "V", &result);
2402 }
2403 }
2404
2405 static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2406 return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2407 Primitive::kPrimBoolean));
2408 }
2409
2410 static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2411 return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2412 Primitive::kPrimByte));
2413 }
2414
2415 static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2416 return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2417 Primitive::kPrimChar));
2418 }
2419
2420 static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2421 return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2422 Primitive::kPrimShort));
2423 }
2424
2425 static jintArray NewIntArray(JNIEnv* env, jsize length) {
2426 return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2427 }
2428
2429 static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2430 return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2431 Primitive::kPrimLong));
2432 }
2433
2434 static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2435 return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2436 Primitive::kPrimFloat));
2437 }
2438
2439 static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2440 return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2441 Primitive::kPrimDouble));
2442 }
2443
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002444// NOLINT added to avoid wrong warning/fix from clang-tidy.
Ian Rogers68d8b422014-07-17 11:09:10 -07002445#define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002446 static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2447 return reinterpret_cast<ctype*>( /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002448 GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2449 } \
2450 \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002451 static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002452 jint mode) { \
2453 ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2454 } \
2455 \
2456 static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -07002457 ctype* buf) { /* NOLINT */ \
Ian Rogers68d8b422014-07-17 11:09:10 -07002458 GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2459 } \
2460 \
2461 static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2462 const ctype* buf) { \
2463 SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2464 }
2465
2466 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2467 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2468 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2469 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2470 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2471 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2472 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2473 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2474#undef PRIMITIVE_ARRAY_FUNCTIONS
2475
2476 static jint MonitorEnter(JNIEnv* env, jobject obj) {
2477 ScopedObjectAccess soa(env);
2478 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2479 JniValueType args[2] = {{.E = env}, {.L = obj}};
2480 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002481 if (obj != nullptr) {
2482 down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2483 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002484 JniValueType result;
2485 result.i = baseEnv(env)->MonitorEnter(env, obj);
2486 if (sc.Check(soa, false, "i", &result)) {
2487 return result.i;
2488 }
2489 }
2490 return JNI_ERR;
2491 }
2492
2493 static jint MonitorExit(JNIEnv* env, jobject obj) {
2494 ScopedObjectAccess soa(env);
2495 ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2496 JniValueType args[2] = {{.E = env}, {.L = obj}};
2497 if (sc.Check(soa, true, "EL", args)) {
Andreas Gampe5f4a09a2015-09-28 13:16:33 -07002498 if (obj != nullptr) {
2499 down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2500 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002501 JniValueType result;
2502 result.i = baseEnv(env)->MonitorExit(env, obj);
2503 if (sc.Check(soa, false, "i", &result)) {
2504 return result.i;
2505 }
2506 }
2507 return JNI_ERR;
2508 }
2509
2510 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2511 ScopedObjectAccess soa(env);
2512 ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2513 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2514 if (sc.Check(soa, true, "Eap", args)) {
2515 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002516 void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2517 if (ptr != nullptr && soa.ForceCopy()) {
2518 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07002519 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002520 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07002521 if (sc.Check(soa, false, "p", &result)) {
2522 return const_cast<void*>(result.p);
2523 }
2524 }
2525 return nullptr;
2526 }
2527
2528 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2529 ScopedObjectAccess soa(env);
2530 ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2531 sc.CheckNonNull(carray);
2532 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2533 if (sc.Check(soa, true, "Eapr", args)) {
2534 if (soa.ForceCopy()) {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07002535 carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
Ian Rogers68d8b422014-07-17 11:09:10 -07002536 }
2537 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2538 JniValueType result;
2539 result.V = nullptr;
2540 sc.Check(soa, false, "V", &result);
2541 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002542 }
2543
2544 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002545 ScopedObjectAccess soa(env);
2546 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2547 JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2548 if (sc.Check(soa, true, "EpJ", args)) {
2549 JniValueType result;
2550 // Note: the validity of address and capacity are checked in the base implementation.
2551 result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2552 if (sc.Check(soa, false, "L", &result)) {
2553 return result.L;
2554 }
Elliott Hughesa2501992011-08-26 19:39:54 -07002555 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002556 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002557 }
2558
2559 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002560 ScopedObjectAccess soa(env);
2561 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2562 JniValueType args[2] = {{.E = env}, {.L = buf}};
2563 if (sc.Check(soa, true, "EL", args)) {
2564 JniValueType result;
2565 // Note: this is implemented in the base environment by a GetLongField which will sanity
2566 // check the type of buf in GetLongField above.
2567 result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2568 if (sc.Check(soa, false, "p", &result)) {
2569 return const_cast<void*>(result.p);
2570 }
2571 }
2572 return nullptr;
Elliott Hughesa2501992011-08-26 19:39:54 -07002573 }
2574
2575 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002576 ScopedObjectAccess soa(env);
2577 ScopedCheck sc(kFlag_Default, __FUNCTION__);
2578 JniValueType args[2] = {{.E = env}, {.L = buf}};
2579 if (sc.Check(soa, true, "EL", args)) {
2580 JniValueType result;
2581 // Note: this is implemented in the base environment by a GetIntField which will sanity
2582 // check the type of buf in GetIntField above.
2583 result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2584 if (sc.Check(soa, false, "J", &result)) {
2585 return result.J;
2586 }
2587 }
2588 return JNI_ERR;
Elliott Hughesa2501992011-08-26 19:39:54 -07002589 }
2590
2591 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07002592 static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2593 return reinterpret_cast<JNIEnvExt*>(env)->vm;
2594 }
2595
2596 static const JNINativeInterface* baseEnv(JNIEnv* env) {
Elliott Hughesa2501992011-08-26 19:39:54 -07002597 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
2598 }
Ian Rogers68d8b422014-07-17 11:09:10 -07002599
2600 static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2601 ScopedObjectAccess soa(env);
2602 ScopedCheck sc(kFlag_Default, function_name);
2603 JniValueType args[2] = {{.E = env}, {.L = obj}};
2604 if (sc.Check(soa, true, "EL", args)) {
2605 JniValueType result;
2606 switch (kind) {
2607 case kGlobal:
2608 result.L = baseEnv(env)->NewGlobalRef(env, obj);
2609 break;
2610 case kLocal:
2611 result.L = baseEnv(env)->NewLocalRef(env, obj);
2612 break;
2613 case kWeakGlobal:
2614 result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2615 break;
2616 default:
2617 LOG(FATAL) << "Unexpected reference kind: " << kind;
2618 }
2619 if (sc.Check(soa, false, "L", &result)) {
2620 DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002621 DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
Ian Rogers68d8b422014-07-17 11:09:10 -07002622 return result.L;
2623 }
2624 }
2625 return nullptr;
2626 }
2627
2628 static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2629 ScopedObjectAccess soa(env);
2630 ScopedCheck sc(kFlag_ExcepOkay, function_name);
2631 JniValueType args[2] = {{.E = env}, {.L = obj}};
2632 sc.Check(soa, true, "EL", args);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002633 if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002634 JniValueType result;
2635 switch (kind) {
2636 case kGlobal:
2637 baseEnv(env)->DeleteGlobalRef(env, obj);
2638 break;
2639 case kLocal:
2640 baseEnv(env)->DeleteLocalRef(env, obj);
2641 break;
2642 case kWeakGlobal:
2643 baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2644 break;
2645 default:
2646 LOG(FATAL) << "Unexpected reference kind: " << kind;
2647 }
2648 result.V = nullptr;
2649 sc.Check(soa, false, "V", &result);
2650 }
2651 }
2652
2653 static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2654 const char* name, const char* sig, bool is_static) {
2655 ScopedObjectAccess soa(env);
2656 ScopedCheck sc(kFlag_Default, function_name);
2657 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2658 if (sc.Check(soa, true, "Ecuu", args)) {
2659 JniValueType result;
2660 if (is_static) {
2661 result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2662 } else {
2663 result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2664 }
2665 if (sc.Check(soa, false, "m", &result)) {
2666 return result.m;
2667 }
2668 }
2669 return nullptr;
2670 }
2671
2672 static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2673 const char* name, const char* sig, bool is_static) {
2674 ScopedObjectAccess soa(env);
2675 ScopedCheck sc(kFlag_Default, function_name);
2676 JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2677 if (sc.Check(soa, true, "Ecuu", args)) {
2678 JniValueType result;
2679 if (is_static) {
2680 result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2681 } else {
2682 result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2683 }
2684 if (sc.Check(soa, false, "f", &result)) {
2685 return result.f;
2686 }
2687 }
2688 return nullptr;
2689 }
2690
2691 static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2692 bool is_static, Primitive::Type type) {
2693 ScopedObjectAccess soa(env);
2694 ScopedCheck sc(kFlag_Default, function_name);
2695 JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2696 JniValueType result;
2697 if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2698 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2699 const char* result_check = nullptr;
2700 switch (type) {
2701 case Primitive::kPrimNot:
2702 if (is_static) {
2703 result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2704 } else {
2705 result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2706 }
2707 result_check = "L";
2708 break;
2709 case Primitive::kPrimBoolean:
2710 if (is_static) {
2711 result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2712 } else {
2713 result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2714 }
2715 result_check = "Z";
2716 break;
2717 case Primitive::kPrimByte:
2718 if (is_static) {
2719 result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2720 } else {
2721 result.B = baseEnv(env)->GetByteField(env, obj, fid);
2722 }
2723 result_check = "B";
2724 break;
2725 case Primitive::kPrimChar:
2726 if (is_static) {
2727 result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2728 } else {
2729 result.C = baseEnv(env)->GetCharField(env, obj, fid);
2730 }
2731 result_check = "C";
2732 break;
2733 case Primitive::kPrimShort:
2734 if (is_static) {
2735 result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2736 } else {
2737 result.S = baseEnv(env)->GetShortField(env, obj, fid);
2738 }
2739 result_check = "S";
2740 break;
2741 case Primitive::kPrimInt:
2742 if (is_static) {
2743 result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2744 } else {
2745 result.I = baseEnv(env)->GetIntField(env, obj, fid);
2746 }
2747 result_check = "I";
2748 break;
2749 case Primitive::kPrimLong:
2750 if (is_static) {
2751 result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2752 } else {
2753 result.J = baseEnv(env)->GetLongField(env, obj, fid);
2754 }
2755 result_check = "J";
2756 break;
2757 case Primitive::kPrimFloat:
2758 if (is_static) {
2759 result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2760 } else {
2761 result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2762 }
2763 result_check = "F";
2764 break;
2765 case Primitive::kPrimDouble:
2766 if (is_static) {
2767 result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
2768 } else {
2769 result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
2770 }
2771 result_check = "D";
2772 break;
2773 case Primitive::kPrimVoid:
2774 LOG(FATAL) << "Unexpected type: " << type;
2775 break;
2776 }
2777 if (sc.Check(soa, false, result_check, &result)) {
2778 return result;
2779 }
2780 }
2781 result.J = 0;
2782 return result;
2783 }
2784
2785 static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2786 bool is_static, Primitive::Type type, JniValueType value) {
2787 ScopedObjectAccess soa(env);
2788 ScopedCheck sc(kFlag_Default, function_name);
2789 JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
2790 char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
2791 type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
2792 if (sc.Check(soa, true, sig, args) &&
2793 sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2794 switch (type) {
2795 case Primitive::kPrimNot:
2796 if (is_static) {
2797 baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
2798 } else {
2799 baseEnv(env)->SetObjectField(env, obj, fid, value.L);
2800 }
2801 break;
2802 case Primitive::kPrimBoolean:
2803 if (is_static) {
2804 baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
2805 } else {
2806 baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
2807 }
2808 break;
2809 case Primitive::kPrimByte:
2810 if (is_static) {
2811 baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
2812 } else {
2813 baseEnv(env)->SetByteField(env, obj, fid, value.B);
2814 }
2815 break;
2816 case Primitive::kPrimChar:
2817 if (is_static) {
2818 baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
2819 } else {
2820 baseEnv(env)->SetCharField(env, obj, fid, value.C);
2821 }
2822 break;
2823 case Primitive::kPrimShort:
2824 if (is_static) {
2825 baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
2826 } else {
2827 baseEnv(env)->SetShortField(env, obj, fid, value.S);
2828 }
2829 break;
2830 case Primitive::kPrimInt:
2831 if (is_static) {
2832 baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
2833 } else {
2834 baseEnv(env)->SetIntField(env, obj, fid, value.I);
2835 }
2836 break;
2837 case Primitive::kPrimLong:
2838 if (is_static) {
2839 baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
2840 } else {
2841 baseEnv(env)->SetLongField(env, obj, fid, value.J);
2842 }
2843 break;
2844 case Primitive::kPrimFloat:
2845 if (is_static) {
2846 baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
2847 } else {
2848 baseEnv(env)->SetFloatField(env, obj, fid, value.F);
2849 }
2850 break;
2851 case Primitive::kPrimDouble:
2852 if (is_static) {
2853 baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
2854 } else {
2855 baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
2856 }
2857 break;
2858 case Primitive::kPrimVoid:
2859 LOG(FATAL) << "Unexpected type: " << type;
2860 break;
2861 }
2862 JniValueType result;
2863 result.V = nullptr;
2864 sc.Check(soa, false, "V", &result);
2865 }
2866 }
2867
2868 static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
Alex Light48ffe062015-08-19 15:23:23 -07002869 jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -07002870 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers68d8b422014-07-17 11:09:10 -07002871 bool checked;
2872 switch (invoke) {
2873 case kVirtual: {
2874 DCHECK(c == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002875 JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
2876 checked = sc.Check(soa, true, "ELm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002877 break;
2878 }
2879 case kDirect: {
Alex Light48ffe062015-08-19 15:23:23 -07002880 JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
2881 checked = sc.Check(soa, true, "ELcm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002882 break;
2883 }
2884 case kStatic: {
2885 DCHECK(obj == nullptr);
Alex Light48ffe062015-08-19 15:23:23 -07002886 JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
2887 checked = sc.Check(soa, true, "Ecm.", args);
Ian Rogers68d8b422014-07-17 11:09:10 -07002888 break;
2889 }
2890 default:
2891 LOG(FATAL) << "Unexpected invoke: " << invoke;
2892 checked = false;
2893 break;
2894 }
2895 return checked;
2896 }
2897
2898 static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
2899 jmethodID mid, jvalue* vargs, Primitive::Type type,
2900 InvokeType invoke) {
2901 ScopedObjectAccess soa(env);
2902 ScopedCheck sc(kFlag_Default, function_name);
2903 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07002904 VarArgs rest(mid, vargs);
2905 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07002906 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
2907 const char* result_check;
2908 switch (type) {
2909 case Primitive::kPrimNot:
2910 result_check = "L";
2911 switch (invoke) {
2912 case kVirtual:
2913 result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
2914 break;
2915 case kDirect:
2916 result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
2917 break;
2918 case kStatic:
2919 result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
2920 break;
2921 default:
2922 break;
2923 }
2924 break;
2925 case Primitive::kPrimBoolean:
2926 result_check = "Z";
2927 switch (invoke) {
2928 case kVirtual:
2929 result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
2930 break;
2931 case kDirect:
2932 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
2933 break;
2934 case kStatic:
2935 result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
2936 break;
2937 default:
2938 break;
2939 }
2940 break;
2941 case Primitive::kPrimByte:
2942 result_check = "B";
2943 switch (invoke) {
2944 case kVirtual:
2945 result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
2946 break;
2947 case kDirect:
2948 result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
2949 break;
2950 case kStatic:
2951 result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
2952 break;
2953 default:
2954 break;
2955 }
2956 break;
2957 case Primitive::kPrimChar:
2958 result_check = "C";
2959 switch (invoke) {
2960 case kVirtual:
2961 result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
2962 break;
2963 case kDirect:
2964 result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
2965 break;
2966 case kStatic:
2967 result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
2968 break;
2969 default:
2970 break;
2971 }
2972 break;
2973 case Primitive::kPrimShort:
2974 result_check = "S";
2975 switch (invoke) {
2976 case kVirtual:
2977 result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
2978 break;
2979 case kDirect:
2980 result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
2981 break;
2982 case kStatic:
2983 result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
2984 break;
2985 default:
2986 break;
2987 }
2988 break;
2989 case Primitive::kPrimInt:
2990 result_check = "I";
2991 switch (invoke) {
2992 case kVirtual:
2993 result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
2994 break;
2995 case kDirect:
2996 result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
2997 break;
2998 case kStatic:
2999 result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3000 break;
3001 default:
3002 break;
3003 }
3004 break;
3005 case Primitive::kPrimLong:
3006 result_check = "J";
3007 switch (invoke) {
3008 case kVirtual:
3009 result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3010 break;
3011 case kDirect:
3012 result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3013 break;
3014 case kStatic:
3015 result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3016 break;
3017 default:
3018 break;
3019 }
3020 break;
3021 case Primitive::kPrimFloat:
3022 result_check = "F";
3023 switch (invoke) {
3024 case kVirtual:
3025 result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3026 break;
3027 case kDirect:
3028 result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3029 break;
3030 case kStatic:
3031 result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3032 break;
3033 default:
3034 break;
3035 }
3036 break;
3037 case Primitive::kPrimDouble:
3038 result_check = "D";
3039 switch (invoke) {
3040 case kVirtual:
3041 result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3042 break;
3043 case kDirect:
3044 result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3045 break;
3046 case kStatic:
3047 result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3048 break;
3049 default:
3050 break;
3051 }
3052 break;
3053 case Primitive::kPrimVoid:
3054 result_check = "V";
3055 result.V = nullptr;
3056 switch (invoke) {
3057 case kVirtual:
3058 baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3059 break;
3060 case kDirect:
3061 baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3062 break;
3063 case kStatic:
3064 baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3065 break;
3066 default:
3067 LOG(FATAL) << "Unexpected invoke: " << invoke;
3068 }
3069 break;
3070 default:
3071 LOG(FATAL) << "Unexpected return type: " << type;
3072 result_check = nullptr;
3073 }
3074 if (sc.Check(soa, false, result_check, &result)) {
3075 return result;
3076 }
3077 }
3078 result.J = 0;
3079 return result;
3080 }
3081
3082 static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3083 jmethodID mid, va_list vargs, Primitive::Type type,
3084 InvokeType invoke) {
3085 ScopedObjectAccess soa(env);
3086 ScopedCheck sc(kFlag_Default, function_name);
3087 JniValueType result;
Alex Light48ffe062015-08-19 15:23:23 -07003088 VarArgs rest(mid, vargs);
3089 if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
Ian Rogers68d8b422014-07-17 11:09:10 -07003090 sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3091 const char* result_check;
3092 switch (type) {
3093 case Primitive::kPrimNot:
3094 result_check = "L";
3095 switch (invoke) {
3096 case kVirtual:
3097 result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3098 break;
3099 case kDirect:
3100 result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3101 break;
3102 case kStatic:
3103 result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3104 break;
3105 default:
3106 LOG(FATAL) << "Unexpected invoke: " << invoke;
3107 }
3108 break;
3109 case Primitive::kPrimBoolean:
3110 result_check = "Z";
3111 switch (invoke) {
3112 case kVirtual:
3113 result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3114 break;
3115 case kDirect:
3116 result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3117 break;
3118 case kStatic:
3119 result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3120 break;
3121 default:
3122 LOG(FATAL) << "Unexpected invoke: " << invoke;
3123 }
3124 break;
3125 case Primitive::kPrimByte:
3126 result_check = "B";
3127 switch (invoke) {
3128 case kVirtual:
3129 result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3130 break;
3131 case kDirect:
3132 result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3133 break;
3134 case kStatic:
3135 result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3136 break;
3137 default:
3138 LOG(FATAL) << "Unexpected invoke: " << invoke;
3139 }
3140 break;
3141 case Primitive::kPrimChar:
3142 result_check = "C";
3143 switch (invoke) {
3144 case kVirtual:
3145 result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3146 break;
3147 case kDirect:
3148 result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3149 break;
3150 case kStatic:
3151 result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3152 break;
3153 default:
3154 LOG(FATAL) << "Unexpected invoke: " << invoke;
3155 }
3156 break;
3157 case Primitive::kPrimShort:
3158 result_check = "S";
3159 switch (invoke) {
3160 case kVirtual:
3161 result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3162 break;
3163 case kDirect:
3164 result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3165 break;
3166 case kStatic:
3167 result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3168 break;
3169 default:
3170 LOG(FATAL) << "Unexpected invoke: " << invoke;
3171 }
3172 break;
3173 case Primitive::kPrimInt:
3174 result_check = "I";
3175 switch (invoke) {
3176 case kVirtual:
3177 result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3178 break;
3179 case kDirect:
3180 result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3181 break;
3182 case kStatic:
3183 result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3184 break;
3185 default:
3186 LOG(FATAL) << "Unexpected invoke: " << invoke;
3187 }
3188 break;
3189 case Primitive::kPrimLong:
3190 result_check = "J";
3191 switch (invoke) {
3192 case kVirtual:
3193 result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3194 break;
3195 case kDirect:
3196 result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3197 break;
3198 case kStatic:
3199 result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3200 break;
3201 default:
3202 LOG(FATAL) << "Unexpected invoke: " << invoke;
3203 }
3204 break;
3205 case Primitive::kPrimFloat:
3206 result_check = "F";
3207 switch (invoke) {
3208 case kVirtual:
3209 result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3210 break;
3211 case kDirect:
3212 result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3213 break;
3214 case kStatic:
3215 result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3216 break;
3217 default:
3218 LOG(FATAL) << "Unexpected invoke: " << invoke;
3219 }
3220 break;
3221 case Primitive::kPrimDouble:
3222 result_check = "D";
3223 switch (invoke) {
3224 case kVirtual:
3225 result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3226 break;
3227 case kDirect:
3228 result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3229 break;
3230 case kStatic:
3231 result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3232 break;
3233 default:
3234 LOG(FATAL) << "Unexpected invoke: " << invoke;
3235 }
3236 break;
3237 case Primitive::kPrimVoid:
3238 result_check = "V";
3239 result.V = nullptr;
3240 switch (invoke) {
3241 case kVirtual:
3242 baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3243 break;
3244 case kDirect:
3245 baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3246 break;
3247 case kStatic:
3248 baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3249 break;
3250 default:
3251 LOG(FATAL) << "Unexpected invoke: " << invoke;
3252 }
3253 break;
3254 default:
3255 LOG(FATAL) << "Unexpected return type: " << type;
3256 result_check = nullptr;
3257 }
3258 if (sc.Check(soa, false, result_check, &result)) {
3259 return result;
3260 }
3261 }
3262 result.J = 0;
3263 return result;
3264 }
3265
3266 static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3267 jboolean* is_copy, bool utf, bool critical) {
3268 ScopedObjectAccess soa(env);
3269 int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3270 ScopedCheck sc(flags, function_name);
3271 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3272 if (sc.Check(soa, true, "Esp", args)) {
3273 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003274 void* ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003275 if (utf) {
3276 CHECK(!critical);
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003277 ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3278 result.u = reinterpret_cast<char*>(ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003279 } else {
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003280 ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3281 baseEnv(env)->GetStringChars(env, string, is_copy));
3282 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003283 }
3284 // TODO: could we be smarter about not copying when local_is_copy?
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003285 if (ptr != nullptr && soa.ForceCopy()) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003286 if (utf) {
3287 size_t length_in_bytes = strlen(result.u) + 1;
3288 result.u =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003289 reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003290 } else {
3291 size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3292 result.p =
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003293 reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
Ian Rogers68d8b422014-07-17 11:09:10 -07003294 }
3295 if (is_copy != nullptr) {
3296 *is_copy = JNI_TRUE;
3297 }
3298 }
3299 if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3300 return utf ? result.u : result.p;
3301 }
3302 }
3303 return nullptr;
3304 }
3305
3306 static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3307 const void* chars, bool utf, bool critical) {
3308 ScopedObjectAccess soa(env);
3309 int flags = kFlag_ExcepOkay | kFlag_Release;
3310 if (critical) {
3311 flags |= kFlag_CritRelease;
3312 }
3313 ScopedCheck sc(flags, function_name);
3314 sc.CheckNonNull(chars);
3315 bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3316 if (force_copy_ok && soa.ForceCopy()) {
3317 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3318 }
3319 if (force_copy_ok) {
3320 JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3321 if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3322 if (utf) {
3323 CHECK(!critical);
3324 baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3325 } else {
3326 if (critical) {
3327 baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3328 } else {
3329 baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3330 }
3331 }
3332 JniValueType result;
3333 sc.Check(soa, false, "V", &result);
3334 }
3335 }
3336 }
3337
3338 static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3339 Primitive::Type type) {
3340 ScopedObjectAccess soa(env);
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003341 ScopedCheck sc(kFlag_Default, function_name);
Ian Rogers68d8b422014-07-17 11:09:10 -07003342 JniValueType args[2] = {{.E = env}, {.z = length}};
3343 if (sc.Check(soa, true, "Ez", args)) {
3344 JniValueType result;
3345 switch (type) {
3346 case Primitive::kPrimBoolean:
3347 result.a = baseEnv(env)->NewBooleanArray(env, length);
3348 break;
3349 case Primitive::kPrimByte:
3350 result.a = baseEnv(env)->NewByteArray(env, length);
3351 break;
3352 case Primitive::kPrimChar:
3353 result.a = baseEnv(env)->NewCharArray(env, length);
3354 break;
3355 case Primitive::kPrimShort:
3356 result.a = baseEnv(env)->NewShortArray(env, length);
3357 break;
3358 case Primitive::kPrimInt:
3359 result.a = baseEnv(env)->NewIntArray(env, length);
3360 break;
3361 case Primitive::kPrimLong:
3362 result.a = baseEnv(env)->NewLongArray(env, length);
3363 break;
3364 case Primitive::kPrimFloat:
3365 result.a = baseEnv(env)->NewFloatArray(env, length);
3366 break;
3367 case Primitive::kPrimDouble:
3368 result.a = baseEnv(env)->NewDoubleArray(env, length);
3369 break;
3370 default:
3371 LOG(FATAL) << "Unexpected primitive type: " << type;
3372 }
3373 if (sc.Check(soa, false, "a", &result)) {
3374 return result.a;
3375 }
3376 }
3377 return nullptr;
3378 }
3379
3380 static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3381 JNIEnv* env, jarray array, jboolean* is_copy) {
3382 ScopedObjectAccess soa(env);
3383 ScopedCheck sc(kFlag_Default, function_name);
3384 JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3385 if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3386 JniValueType result;
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003387 void* ptr = nullptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003388 switch (type) {
3389 case Primitive::kPrimBoolean:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003390 ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3391 is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003392 break;
3393 case Primitive::kPrimByte:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003394 ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003395 break;
3396 case Primitive::kPrimChar:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003397 ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003398 break;
3399 case Primitive::kPrimShort:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003400 ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003401 break;
3402 case Primitive::kPrimInt:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003403 ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003404 break;
3405 case Primitive::kPrimLong:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003406 ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003407 break;
3408 case Primitive::kPrimFloat:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003409 ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003410 break;
3411 case Primitive::kPrimDouble:
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003412 ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
Ian Rogers68d8b422014-07-17 11:09:10 -07003413 break;
3414 default:
3415 LOG(FATAL) << "Unexpected primitive type: " << type;
3416 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003417 if (ptr != nullptr && soa.ForceCopy()) {
3418 ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
Ian Rogers68d8b422014-07-17 11:09:10 -07003419 if (is_copy != nullptr) {
3420 *is_copy = JNI_TRUE;
3421 }
3422 }
Mathieu Chartierb735bd92015-06-24 17:04:17 -07003423 result.p = ptr;
Ian Rogers68d8b422014-07-17 11:09:10 -07003424 if (sc.Check(soa, false, "p", &result)) {
3425 return const_cast<void*>(result.p);
3426 }
3427 }
3428 return nullptr;
3429 }
3430
3431 static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3432 JNIEnv* env, jarray array, void* elems, jint mode) {
3433 ScopedObjectAccess soa(env);
3434 ScopedCheck sc(kFlag_ExcepOkay, function_name);
3435 if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3436 if (soa.ForceCopy()) {
3437 elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3438 }
3439 if (!soa.ForceCopy() || elems != nullptr) {
3440 JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3441 if (sc.Check(soa, true, "Eapr", args)) {
3442 switch (type) {
3443 case Primitive::kPrimBoolean:
3444 baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3445 reinterpret_cast<jboolean*>(elems), mode);
3446 break;
3447 case Primitive::kPrimByte:
3448 baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3449 reinterpret_cast<jbyte*>(elems), mode);
3450 break;
3451 case Primitive::kPrimChar:
3452 baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3453 reinterpret_cast<jchar*>(elems), mode);
3454 break;
3455 case Primitive::kPrimShort:
3456 baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3457 reinterpret_cast<jshort*>(elems), mode);
3458 break;
3459 case Primitive::kPrimInt:
3460 baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3461 reinterpret_cast<jint*>(elems), mode);
3462 break;
3463 case Primitive::kPrimLong:
3464 baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3465 reinterpret_cast<jlong*>(elems), mode);
3466 break;
3467 case Primitive::kPrimFloat:
3468 baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3469 reinterpret_cast<jfloat*>(elems), mode);
3470 break;
3471 case Primitive::kPrimDouble:
3472 baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3473 reinterpret_cast<jdouble*>(elems), mode);
3474 break;
3475 default:
3476 LOG(FATAL) << "Unexpected primitive type: " << type;
3477 }
3478 JniValueType result;
3479 result.V = nullptr;
3480 sc.Check(soa, false, "V", &result);
3481 }
3482 }
3483 }
3484 }
3485
3486 static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3487 jarray array, jsize start, jsize len, void* buf) {
3488 ScopedObjectAccess soa(env);
3489 ScopedCheck sc(kFlag_Default, function_name);
3490 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3491 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3492 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3493 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3494 switch (type) {
3495 case Primitive::kPrimBoolean:
3496 baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3497 reinterpret_cast<jboolean*>(buf));
3498 break;
3499 case Primitive::kPrimByte:
3500 baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3501 reinterpret_cast<jbyte*>(buf));
3502 break;
3503 case Primitive::kPrimChar:
3504 baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3505 reinterpret_cast<jchar*>(buf));
3506 break;
3507 case Primitive::kPrimShort:
3508 baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3509 reinterpret_cast<jshort*>(buf));
3510 break;
3511 case Primitive::kPrimInt:
3512 baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3513 reinterpret_cast<jint*>(buf));
3514 break;
3515 case Primitive::kPrimLong:
3516 baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3517 reinterpret_cast<jlong*>(buf));
3518 break;
3519 case Primitive::kPrimFloat:
3520 baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3521 reinterpret_cast<jfloat*>(buf));
3522 break;
3523 case Primitive::kPrimDouble:
3524 baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3525 reinterpret_cast<jdouble*>(buf));
3526 break;
3527 default:
3528 LOG(FATAL) << "Unexpected primitive type: " << type;
3529 }
3530 JniValueType result;
3531 result.V = nullptr;
3532 sc.Check(soa, false, "V", &result);
3533 }
3534 }
3535
3536 static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3537 jarray array, jsize start, jsize len, const void* buf) {
3538 ScopedObjectAccess soa(env);
3539 ScopedCheck sc(kFlag_Default, function_name);
3540 JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3541 // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3542 // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3543 if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3544 switch (type) {
3545 case Primitive::kPrimBoolean:
3546 baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3547 reinterpret_cast<const jboolean*>(buf));
3548 break;
3549 case Primitive::kPrimByte:
3550 baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3551 reinterpret_cast<const jbyte*>(buf));
3552 break;
3553 case Primitive::kPrimChar:
3554 baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3555 reinterpret_cast<const jchar*>(buf));
3556 break;
3557 case Primitive::kPrimShort:
3558 baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3559 reinterpret_cast<const jshort*>(buf));
3560 break;
3561 case Primitive::kPrimInt:
3562 baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3563 reinterpret_cast<const jint*>(buf));
3564 break;
3565 case Primitive::kPrimLong:
3566 baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3567 reinterpret_cast<const jlong*>(buf));
3568 break;
3569 case Primitive::kPrimFloat:
3570 baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3571 reinterpret_cast<const jfloat*>(buf));
3572 break;
3573 case Primitive::kPrimDouble:
3574 baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3575 reinterpret_cast<const jdouble*>(buf));
3576 break;
3577 default:
3578 LOG(FATAL) << "Unexpected primitive type: " << type;
3579 }
3580 JniValueType result;
3581 result.V = nullptr;
3582 sc.Check(soa, false, "V", &result);
3583 }
3584 }
Elliott Hughesa2501992011-08-26 19:39:54 -07003585};
3586
3587const JNINativeInterface gCheckNativeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003588 nullptr, // reserved0.
3589 nullptr, // reserved1.
3590 nullptr, // reserved2.
3591 nullptr, // reserved3.
Elliott Hughesa2501992011-08-26 19:39:54 -07003592 CheckJNI::GetVersion,
3593 CheckJNI::DefineClass,
3594 CheckJNI::FindClass,
3595 CheckJNI::FromReflectedMethod,
3596 CheckJNI::FromReflectedField,
3597 CheckJNI::ToReflectedMethod,
3598 CheckJNI::GetSuperclass,
3599 CheckJNI::IsAssignableFrom,
3600 CheckJNI::ToReflectedField,
3601 CheckJNI::Throw,
3602 CheckJNI::ThrowNew,
3603 CheckJNI::ExceptionOccurred,
3604 CheckJNI::ExceptionDescribe,
3605 CheckJNI::ExceptionClear,
3606 CheckJNI::FatalError,
3607 CheckJNI::PushLocalFrame,
3608 CheckJNI::PopLocalFrame,
3609 CheckJNI::NewGlobalRef,
3610 CheckJNI::DeleteGlobalRef,
3611 CheckJNI::DeleteLocalRef,
3612 CheckJNI::IsSameObject,
3613 CheckJNI::NewLocalRef,
3614 CheckJNI::EnsureLocalCapacity,
3615 CheckJNI::AllocObject,
3616 CheckJNI::NewObject,
3617 CheckJNI::NewObjectV,
3618 CheckJNI::NewObjectA,
3619 CheckJNI::GetObjectClass,
3620 CheckJNI::IsInstanceOf,
3621 CheckJNI::GetMethodID,
3622 CheckJNI::CallObjectMethod,
3623 CheckJNI::CallObjectMethodV,
3624 CheckJNI::CallObjectMethodA,
3625 CheckJNI::CallBooleanMethod,
3626 CheckJNI::CallBooleanMethodV,
3627 CheckJNI::CallBooleanMethodA,
3628 CheckJNI::CallByteMethod,
3629 CheckJNI::CallByteMethodV,
3630 CheckJNI::CallByteMethodA,
3631 CheckJNI::CallCharMethod,
3632 CheckJNI::CallCharMethodV,
3633 CheckJNI::CallCharMethodA,
3634 CheckJNI::CallShortMethod,
3635 CheckJNI::CallShortMethodV,
3636 CheckJNI::CallShortMethodA,
3637 CheckJNI::CallIntMethod,
3638 CheckJNI::CallIntMethodV,
3639 CheckJNI::CallIntMethodA,
3640 CheckJNI::CallLongMethod,
3641 CheckJNI::CallLongMethodV,
3642 CheckJNI::CallLongMethodA,
3643 CheckJNI::CallFloatMethod,
3644 CheckJNI::CallFloatMethodV,
3645 CheckJNI::CallFloatMethodA,
3646 CheckJNI::CallDoubleMethod,
3647 CheckJNI::CallDoubleMethodV,
3648 CheckJNI::CallDoubleMethodA,
3649 CheckJNI::CallVoidMethod,
3650 CheckJNI::CallVoidMethodV,
3651 CheckJNI::CallVoidMethodA,
3652 CheckJNI::CallNonvirtualObjectMethod,
3653 CheckJNI::CallNonvirtualObjectMethodV,
3654 CheckJNI::CallNonvirtualObjectMethodA,
3655 CheckJNI::CallNonvirtualBooleanMethod,
3656 CheckJNI::CallNonvirtualBooleanMethodV,
3657 CheckJNI::CallNonvirtualBooleanMethodA,
3658 CheckJNI::CallNonvirtualByteMethod,
3659 CheckJNI::CallNonvirtualByteMethodV,
3660 CheckJNI::CallNonvirtualByteMethodA,
3661 CheckJNI::CallNonvirtualCharMethod,
3662 CheckJNI::CallNonvirtualCharMethodV,
3663 CheckJNI::CallNonvirtualCharMethodA,
3664 CheckJNI::CallNonvirtualShortMethod,
3665 CheckJNI::CallNonvirtualShortMethodV,
3666 CheckJNI::CallNonvirtualShortMethodA,
3667 CheckJNI::CallNonvirtualIntMethod,
3668 CheckJNI::CallNonvirtualIntMethodV,
3669 CheckJNI::CallNonvirtualIntMethodA,
3670 CheckJNI::CallNonvirtualLongMethod,
3671 CheckJNI::CallNonvirtualLongMethodV,
3672 CheckJNI::CallNonvirtualLongMethodA,
3673 CheckJNI::CallNonvirtualFloatMethod,
3674 CheckJNI::CallNonvirtualFloatMethodV,
3675 CheckJNI::CallNonvirtualFloatMethodA,
3676 CheckJNI::CallNonvirtualDoubleMethod,
3677 CheckJNI::CallNonvirtualDoubleMethodV,
3678 CheckJNI::CallNonvirtualDoubleMethodA,
3679 CheckJNI::CallNonvirtualVoidMethod,
3680 CheckJNI::CallNonvirtualVoidMethodV,
3681 CheckJNI::CallNonvirtualVoidMethodA,
3682 CheckJNI::GetFieldID,
3683 CheckJNI::GetObjectField,
3684 CheckJNI::GetBooleanField,
3685 CheckJNI::GetByteField,
3686 CheckJNI::GetCharField,
3687 CheckJNI::GetShortField,
3688 CheckJNI::GetIntField,
3689 CheckJNI::GetLongField,
3690 CheckJNI::GetFloatField,
3691 CheckJNI::GetDoubleField,
3692 CheckJNI::SetObjectField,
3693 CheckJNI::SetBooleanField,
3694 CheckJNI::SetByteField,
3695 CheckJNI::SetCharField,
3696 CheckJNI::SetShortField,
3697 CheckJNI::SetIntField,
3698 CheckJNI::SetLongField,
3699 CheckJNI::SetFloatField,
3700 CheckJNI::SetDoubleField,
3701 CheckJNI::GetStaticMethodID,
3702 CheckJNI::CallStaticObjectMethod,
3703 CheckJNI::CallStaticObjectMethodV,
3704 CheckJNI::CallStaticObjectMethodA,
3705 CheckJNI::CallStaticBooleanMethod,
3706 CheckJNI::CallStaticBooleanMethodV,
3707 CheckJNI::CallStaticBooleanMethodA,
3708 CheckJNI::CallStaticByteMethod,
3709 CheckJNI::CallStaticByteMethodV,
3710 CheckJNI::CallStaticByteMethodA,
3711 CheckJNI::CallStaticCharMethod,
3712 CheckJNI::CallStaticCharMethodV,
3713 CheckJNI::CallStaticCharMethodA,
3714 CheckJNI::CallStaticShortMethod,
3715 CheckJNI::CallStaticShortMethodV,
3716 CheckJNI::CallStaticShortMethodA,
3717 CheckJNI::CallStaticIntMethod,
3718 CheckJNI::CallStaticIntMethodV,
3719 CheckJNI::CallStaticIntMethodA,
3720 CheckJNI::CallStaticLongMethod,
3721 CheckJNI::CallStaticLongMethodV,
3722 CheckJNI::CallStaticLongMethodA,
3723 CheckJNI::CallStaticFloatMethod,
3724 CheckJNI::CallStaticFloatMethodV,
3725 CheckJNI::CallStaticFloatMethodA,
3726 CheckJNI::CallStaticDoubleMethod,
3727 CheckJNI::CallStaticDoubleMethodV,
3728 CheckJNI::CallStaticDoubleMethodA,
3729 CheckJNI::CallStaticVoidMethod,
3730 CheckJNI::CallStaticVoidMethodV,
3731 CheckJNI::CallStaticVoidMethodA,
3732 CheckJNI::GetStaticFieldID,
3733 CheckJNI::GetStaticObjectField,
3734 CheckJNI::GetStaticBooleanField,
3735 CheckJNI::GetStaticByteField,
3736 CheckJNI::GetStaticCharField,
3737 CheckJNI::GetStaticShortField,
3738 CheckJNI::GetStaticIntField,
3739 CheckJNI::GetStaticLongField,
3740 CheckJNI::GetStaticFloatField,
3741 CheckJNI::GetStaticDoubleField,
3742 CheckJNI::SetStaticObjectField,
3743 CheckJNI::SetStaticBooleanField,
3744 CheckJNI::SetStaticByteField,
3745 CheckJNI::SetStaticCharField,
3746 CheckJNI::SetStaticShortField,
3747 CheckJNI::SetStaticIntField,
3748 CheckJNI::SetStaticLongField,
3749 CheckJNI::SetStaticFloatField,
3750 CheckJNI::SetStaticDoubleField,
3751 CheckJNI::NewString,
3752 CheckJNI::GetStringLength,
3753 CheckJNI::GetStringChars,
3754 CheckJNI::ReleaseStringChars,
3755 CheckJNI::NewStringUTF,
3756 CheckJNI::GetStringUTFLength,
3757 CheckJNI::GetStringUTFChars,
3758 CheckJNI::ReleaseStringUTFChars,
3759 CheckJNI::GetArrayLength,
3760 CheckJNI::NewObjectArray,
3761 CheckJNI::GetObjectArrayElement,
3762 CheckJNI::SetObjectArrayElement,
3763 CheckJNI::NewBooleanArray,
3764 CheckJNI::NewByteArray,
3765 CheckJNI::NewCharArray,
3766 CheckJNI::NewShortArray,
3767 CheckJNI::NewIntArray,
3768 CheckJNI::NewLongArray,
3769 CheckJNI::NewFloatArray,
3770 CheckJNI::NewDoubleArray,
3771 CheckJNI::GetBooleanArrayElements,
3772 CheckJNI::GetByteArrayElements,
3773 CheckJNI::GetCharArrayElements,
3774 CheckJNI::GetShortArrayElements,
3775 CheckJNI::GetIntArrayElements,
3776 CheckJNI::GetLongArrayElements,
3777 CheckJNI::GetFloatArrayElements,
3778 CheckJNI::GetDoubleArrayElements,
3779 CheckJNI::ReleaseBooleanArrayElements,
3780 CheckJNI::ReleaseByteArrayElements,
3781 CheckJNI::ReleaseCharArrayElements,
3782 CheckJNI::ReleaseShortArrayElements,
3783 CheckJNI::ReleaseIntArrayElements,
3784 CheckJNI::ReleaseLongArrayElements,
3785 CheckJNI::ReleaseFloatArrayElements,
3786 CheckJNI::ReleaseDoubleArrayElements,
3787 CheckJNI::GetBooleanArrayRegion,
3788 CheckJNI::GetByteArrayRegion,
3789 CheckJNI::GetCharArrayRegion,
3790 CheckJNI::GetShortArrayRegion,
3791 CheckJNI::GetIntArrayRegion,
3792 CheckJNI::GetLongArrayRegion,
3793 CheckJNI::GetFloatArrayRegion,
3794 CheckJNI::GetDoubleArrayRegion,
3795 CheckJNI::SetBooleanArrayRegion,
3796 CheckJNI::SetByteArrayRegion,
3797 CheckJNI::SetCharArrayRegion,
3798 CheckJNI::SetShortArrayRegion,
3799 CheckJNI::SetIntArrayRegion,
3800 CheckJNI::SetLongArrayRegion,
3801 CheckJNI::SetFloatArrayRegion,
3802 CheckJNI::SetDoubleArrayRegion,
3803 CheckJNI::RegisterNatives,
3804 CheckJNI::UnregisterNatives,
3805 CheckJNI::MonitorEnter,
3806 CheckJNI::MonitorExit,
3807 CheckJNI::GetJavaVM,
3808 CheckJNI::GetStringRegion,
3809 CheckJNI::GetStringUTFRegion,
3810 CheckJNI::GetPrimitiveArrayCritical,
3811 CheckJNI::ReleasePrimitiveArrayCritical,
3812 CheckJNI::GetStringCritical,
3813 CheckJNI::ReleaseStringCritical,
3814 CheckJNI::NewWeakGlobalRef,
3815 CheckJNI::DeleteWeakGlobalRef,
3816 CheckJNI::ExceptionCheck,
3817 CheckJNI::NewDirectByteBuffer,
3818 CheckJNI::GetDirectBufferAddress,
3819 CheckJNI::GetDirectBufferCapacity,
3820 CheckJNI::GetObjectRefType,
3821};
3822
3823const JNINativeInterface* GetCheckJniNativeInterface() {
3824 return &gCheckNativeInterface;
3825}
3826
3827class CheckJII {
Elliott Hughesba8eee12012-01-24 20:25:24 -08003828 public:
Elliott Hughesa2501992011-08-26 19:39:54 -07003829 static jint DestroyJavaVM(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003830 ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
3831 JniValueType args[1] = {{.v = vm}};
3832 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3833 JniValueType result;
3834 result.i = BaseVm(vm)->DestroyJavaVM(vm);
Andreas Gampedef194e2015-02-19 15:19:50 -08003835 // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
3836 // which will delete the JavaVMExt.
3837 sc.CheckNonHeap(nullptr, false, "i", &result);
Ian Rogers68d8b422014-07-17 11:09:10 -07003838 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003839 }
3840
3841 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003842 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3843 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3844 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3845 JniValueType result;
3846 result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
3847 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3848 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003849 }
3850
3851 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003852 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3853 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
3854 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
3855 JniValueType result;
3856 result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
3857 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3858 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003859 }
3860
3861 static jint DetachCurrentThread(JavaVM* vm) {
Ian Rogers68d8b422014-07-17 11:09:10 -07003862 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3863 JniValueType args[1] = {{.v = vm}};
3864 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
3865 JniValueType result;
3866 result.i = BaseVm(vm)->DetachCurrentThread(vm);
3867 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3868 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003869 }
3870
Ian Rogers68d8b422014-07-17 11:09:10 -07003871 static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
3872 ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
3873 JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
3874 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
3875 JniValueType result;
3876 result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
3877 sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
3878 return result.i;
Elliott Hughesa2501992011-08-26 19:39:54 -07003879 }
3880
3881 private:
Ian Rogers68d8b422014-07-17 11:09:10 -07003882 static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
3883 return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
Elliott Hughesa2501992011-08-26 19:39:54 -07003884 }
3885};
3886
3887const JNIInvokeInterface gCheckInvokeInterface = {
Ian Rogersef7d42f2014-01-06 12:55:46 -08003888 nullptr, // reserved0
3889 nullptr, // reserved1
3890 nullptr, // reserved2
Elliott Hughesa2501992011-08-26 19:39:54 -07003891 CheckJII::DestroyJavaVM,
3892 CheckJII::AttachCurrentThread,
3893 CheckJII::DetachCurrentThread,
3894 CheckJII::GetEnv,
3895 CheckJII::AttachCurrentThreadAsDaemon
3896};
3897
3898const JNIInvokeInterface* GetCheckJniInvokeInterface() {
3899 return &gCheckInvokeInterface;
3900}
3901
3902} // namespace art